tar: handle --mode when extracting archives also

This commit is contained in:
Dan Nelson committed 2026-08-01 15:11:08 -05:00
1 parent e8154e0bfc
commit c26faff361
3 files changed
+74 -2

No files matched your search

+4 -2
View File
@@ -422,8 +422,10 @@ Currently supported only for pax formats
.Po including "pax restricted", the default tar format for
.Nm bsdtar Pc
.It Fl Fl mode Ar permissions
(c, r, u modes only)
Modify the file mode bits stored in the archive.
Modify the file mode bits.
On create, this takes the on-disk mode and modifies it before storing
in the archive.
On extract, the mode from the archive is modified before writing to disk.
Permissions can be absolute (an octal number) or symbolic.
See
.Xr chmod 1
+7
View File
@@ -58,6 +58,7 @@
#include "bsdtar.h"
#include "lafe_err.h"
#include "lafe_setmode.h"
struct progress_data {
struct bsdtar *bsdtar;
@@ -278,6 +279,12 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
if (bsdtar->gname)
archive_entry_set_gname(entry, bsdtar->gname);
if (bsdtar->file_mode) {
mode_t m = archive_entry_mode(entry);
m = lafe_getmode(bsdtar->file_mode, m);
archive_entry_set_mode(entry, m);
}
/*
* Note that pattern exclusions are checked before
* pathname rewrites are handled. This gives more
+63
View File
@@ -6,11 +6,52 @@
*/
#include "test.h"
/* Compare the mode column of tar's list output with an array of expected
* values.
*/
static void check_modes(const char* testname, const char *buf, const char *lines[])
{
int line = 1;
while (*buf && *lines != NULL)
{
failure("On line %d of test %s", line, testname);
assertEqualMem(buf, *lines, strlen(*lines));
while (*buf && !(*buf == '\r'|| *buf == '\n'))
buf++;
while (*buf == '\r' || *buf == '\n')
buf++;
lines++;
line++;
}
if (*lines && ! *buf)
{
failure("On line %d of test %s: unexpected end of file", line, testname);
assert(0);
}
}
DEFINE_TEST(test_option_mode)
{
int rv;
char *p;
const char *test3mtree =
"#mtree\n"
"in/all mode=777 type=file\n"
"in/minimal mode=500 type=file\n";
const char *test3aExpected[] = {
"-rw-r--r--",
"-rw-r--r--",
NULL
};
const char *test3bExpected[] = {
"-rw-rwxr-x",
"-rw---x---",
NULL
};
assertMakeDir("in", 0755);
/* Test invalid modes */
@@ -53,4 +94,26 @@ DEFINE_TEST(test_option_mode)
free(p);
#endif
/* Create an archive file with custom modes. Using mtree here is
* simpler than building a tar file from files, and also works on
* Windows.
*/
assertMakeFile("archive3.mtree", 0644, test3mtree);
/* list, overriding with absolute mode */
assertEqualInt(0,
systemf("%s --mode 644 -tvf archive3.mtree > 3a.out",
testprog));
p = slurpfile(NULL, "3a.out");
check_modes("3a", p, test3aExpected);
free(p);
/* list, overriding with relative mode */
assertEqualInt(0,
systemf("%s --mode u+rw-x,g+X,o-w -tvf archive3.mtree > 3b.out",
testprog));
p = slurpfile(NULL, "3b.out");
check_modes("3b", p, test3bExpected);
free(p);
}