tar: add --mode option (compatible with gnutar)

This commit is contained in:
Dan Nelson committed 2026-08-01 15:11:08 -05:00
1 parent 19ff56da4f
commit e8154e0bfc
13 files changed
+616 -3

No files matched your search

+2
View File
@@ -21,6 +21,8 @@ IF(ENABLE_TAR)
../libarchive_fe/lafe_err.c
../libarchive_fe/lafe_err.h
../libarchive_fe/lafe_platform.h
../libarchive_fe/lafe_setmode.c
../libarchive_fe/lafe_setmode.h
../libarchive_fe/line_reader.c
../libarchive_fe/line_reader.h
../libarchive_fe/passphrase.c
+7
View File
@@ -421,6 +421,13 @@ is run in x mode as root.
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.
Permissions can be absolute (an octal number) or symbolic.
See
.Xr chmod 1
for more information and examples of both types.
.It Fl Fl mtime Ar date
(c, r, u modes only)
Set the modification times of added files to the specified date.
+10
View File
@@ -56,6 +56,7 @@
#include "bsdtar.h"
#include "lafe_err.h"
#include "lafe_setmode.h"
#if ARCHIVE_VERSION_NUMBER < 4000000 && !defined(_PATH_DEFTAPE)
// Libarchive 4.0 and later will NOT define _PATH_DEFTAPE
@@ -512,6 +513,14 @@ main(int argc, char **argv)
bsdtar->extract_flags |= ARCHIVE_EXTRACT_MAC_METADATA;
bsdtar->flags |= OPTFLAG_MAC_METADATA;
break;
case OPTION_MODE: /* GNU tar */
free(bsdtar->file_mode);
bsdtar->file_mode = lafe_setmode(bsdtar->argument);
if (bsdtar->file_mode == NULL)
lafe_errc(1, 0,
"Invalid file mode: %s",
bsdtar->argument);
break;
case 'n': /* GNU tar */
bsdtar->flags |= OPTFLAG_NO_SUBDIRS;
break;
@@ -1023,6 +1032,7 @@ main(int argc, char **argv)
#endif
cset_free(bsdtar->cset);
passphrase_free(bsdtar->ppbuff);
free(bsdtar->file_mode);
if (bsdtar->return_value != 0)
lafe_warnc(0,
+2
View File
@@ -47,6 +47,7 @@ struct bsdtar {
const char *gname; /* --gname */
int uid; /* --uid */
const char *uname; /* --uname */
void *file_mode; /* --mode */
const char *passphrase; /* --passphrase */
int mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */
char symlink_mode; /* H or L, per BSD conventions */
@@ -186,6 +187,7 @@ enum {
OPTION_ZSTD,
OPTION_MTIME,
OPTION_CLAMP_MTIME,
OPTION_MODE,
};
int bsdtar_getopt(struct bsdtar *);
+1
View File
@@ -95,6 +95,7 @@ static const struct bsdtar_option {
{ "lzma", 0, OPTION_LZMA },
{ "lzop", 0, OPTION_LZOP },
{ "mac-metadata", 0, OPTION_MAC_METADATA },
{ "mode", 1, OPTION_MODE },
{ "modification-time", 0, 'm' },
{ "mtime", 1, OPTION_MTIME },
{ "newer", 1, OPTION_NEWER_CTIME },
+1
View File
@@ -59,6 +59,7 @@ IF(ENABLE_TAR AND ENABLE_TEST)
test_option_lz4.c
test_option_lzma.c
test_option_lzop.c
test_option_mode.c
test_option_mtime.c
test_option_n.c
test_option_newer_than.c
+56
View File
@@ -0,0 +1,56 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2026 Dan Nelson
* All rights reserved.
*/
#include "test.h"
DEFINE_TEST(test_option_mode)
{
int rv;
char *p;
assertMakeDir("in", 0755);
/* Test invalid modes */
rv = systemf("%s --mode 8 -cf archive.tar in > 1.out 2> 1.err",
testprog);
assert(rv != 0);
rv = systemf("%s --mode a+a -cf archive.tar in > 2.out 2> 2.err",
testprog);
assert(rv != 0);
/* Create some files with different modes */
assertMakeFile("in/all", 0777, "");
assertMakeFile("in/minimal", 0500, "");
/* Archive and override using an absolute mode */
assertEqualInt(0,
systemf("%s --mode 644 -cf archive1.tar "
"in/all in/minimal", testprog));
/* Verify the modes */
p = slurpfile(NULL, "archive1.tar");
assertEqualString(p + 100,"000644 ");
assertEqualString(p + 612,"000644 ");
free(p);
/* Skip relative symbolic mode checks on Windows; on-disk files always have
* mode 644.
*/
#if !defined(_WIN32) || defined(__CYGWIN__)
/* Archive and override using a symbolic mode */
assertEqualInt(0,
systemf("%s --mode u+rw-x,g+X,o-w -cf archive2.tar "
"in/all in/minimal", testprog));
/* Verify the modes */
p = slurpfile(NULL, "archive2.tar");
assertEqualString(p + 100,"000675 ");
assertEqualString(p + 612,"000610 ");
free(p);
#endif
}
+7
View File
@@ -59,6 +59,7 @@
#include "bsdtar.h"
#include "lafe_err.h"
#include "lafe_setmode.h"
#include "line_reader.h"
#ifndef O_BINARY
@@ -942,6 +943,12 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
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);
}
/*
* Rewrite the pathname to be archived. If rewrite
* fails, skip the entry.