From: Tim Kientzle Date: Sat, 1 May 2010 21:18:38 +0000 (-0400) Subject: Add --gid, --gname, --uid, --uname options to tar. X-Git-Tag: v3.0.0a~1044 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9dd2a0e1cfc2bd542c99deee4b633c8b7e74a862;p=thirdparty%2Flibarchive.git Add --gid, --gname, --uid, --uname options to tar. These allow you to override the user/group information both when creating an archive and when restoring an archive. I've also reimplemented --numeric-owner to be a synonym for --gname="" --uname="". Still needs tests... SVN-Revision: 2349 --- diff --git a/tar/bsdtar.1 b/tar/bsdtar.1 index 1aa494963..41e35ccdc 100644 --- a/tar/bsdtar.1 +++ b/tar/bsdtar.1 @@ -199,6 +199,27 @@ the default is .Pa /dev/sa0 ; on Linux, the default is .Pa /dev/st0 . +.It Fl Fl gid Ar id +Use the provided group id number. +On extract, this overrides the group id in the archive; +the group name in the archive will be ignored. +On create, this overrides the group id read from disk; +if +.Fl Fl gname +is not also specified, the group name will be set to +match the group id. +.It Fl Fl gname Ar name +Use the provided group name. +On extract, this overrides the group name in the archive; +if the provided group name does not exist on the system, +the group id +(from the archive or from the +.Fl Fl gid +option) +will be used instead. +On create, this sets the group name that will be stored +in the archive; +the name will not be verified against the system group database. .It Fl H (c and r mode only) Symbolic links named on the command line will be followed; the @@ -331,9 +352,15 @@ and the default behavior if .Nm is run as non-root. .It Fl Fl numeric-owner -(x mode only) -Ignore symbolic user and group names when restoring archives to disk, -only numeric uid and gid values will be obeyed. +This is equivalent to +.Fl Fl uname +.Qq +.Fl Fl gname +.Qq . +On extract, it causes user and group names in the archive +to be ignored in favor of the numeric user and group ids. +On create, it causes user and group names to not be stored +in the archive. .It Fl O , Fl Fl to-stdout (x, t modes only) In extract (-x) mode, files will be written to standard out rather than @@ -543,6 +570,25 @@ This flag also causes to remove intervening directory symlinks instead of reporting an error. See the SECURITY section below for more details. +.It Fl Fl uid Ar id +Use the provided user id number and ignore the user +name from the archive. +On create, if +.Fl Fl uname +is not also specified, the user name will be set to +match the user id. +.It Fl Fl uname Ar name +Use the provided user name. +On extract, this overrides the user name in the archive; +if the provided user name does not exist on the system, +it will be ignored and the user id +(from the archive or from the +.Fl Fl uid +option) +will be used instead. +On create, this sets the user name that will be stored +in the archive; +the name is not verified against the system user database. .It Fl Fl use-compress-program Ar program Pipe the input (in x or t mode) or the output (in c mode) through .Pa program diff --git a/tar/bsdtar.c b/tar/bsdtar.c index eb0fd70e2..f0690fa3b 100644 --- a/tar/bsdtar.c +++ b/tar/bsdtar.c @@ -149,6 +149,8 @@ main(int argc, char **argv) bsdtar = &bsdtar_storage; memset(bsdtar, 0, sizeof(*bsdtar)); bsdtar->fd = -1; /* Mark as "unused" */ + bsdtar->gid = -1; + bsdtar->uid = -1; option_o = 0; #if defined(HAVE_SIGACTION) && (defined(SIGINFO) || defined(SIGUSR1)) @@ -278,12 +280,19 @@ main(int argc, char **argv) case OPTION_FORMAT: /* GNU tar, others */ bsdtar->create_format = bsdtar->optarg; break; - case OPTION_OPTIONS: - bsdtar->option_options = bsdtar->optarg; - break; case 'f': /* SUSv2 */ bsdtar->filename = bsdtar->optarg; break; + case OPTION_GID: /* cpio */ + t = atoi(bsdtar->optarg); + if (t < 0) + lafe_errc(1, 0, + "Argument to --gid must be positive"); + bsdtar->gid = t; + break; + case OPTION_GNAME: /* cpio */ + bsdtar->gname = bsdtar->optarg; + break; case 'H': /* BSD convention */ bsdtar->symlink_mode = 'H'; break; @@ -411,7 +420,8 @@ main(int argc, char **argv) bsdtar->option_null++; break; case OPTION_NUMERIC_OWNER: /* GNU tar */ - bsdtar->option_numeric_owner++; + bsdtar->uname = ""; + bsdtar->gname = ""; break; case 'O': /* GNU tar */ bsdtar->option_stdout = 1; @@ -422,6 +432,9 @@ main(int argc, char **argv) case OPTION_ONE_FILE_SYSTEM: /* GNU tar */ bsdtar->option_dont_traverse_mounts = 1; break; + case OPTION_OPTIONS: + bsdtar->option_options = bsdtar->optarg; + break; #if 0 /* * The common BSD -P option is not necessary, since @@ -487,6 +500,16 @@ main(int argc, char **argv) case 'u': /* SUSv2 */ set_mode(bsdtar, opt); break; + case OPTION_UID: /* cpio */ + t = atoi(bsdtar->optarg); + if (t < 0) + lafe_errc(1, 0, + "Argument to --uid must be positive"); + bsdtar->uid = t; + break; + case OPTION_UNAME: /* cpio */ + bsdtar->uname = bsdtar->optarg; + break; case 'v': /* SUSv2 */ bsdtar->verbose++; break; diff --git a/tar/bsdtar.h b/tar/bsdtar.h index 33371a47d..97826b288 100644 --- a/tar/bsdtar.h +++ b/tar/bsdtar.h @@ -54,6 +54,10 @@ struct bsdtar { int verbose; /* -v */ int extract_flags; /* Flags for extract operation */ int strip_components; /* Remove this many leading dirs */ + int gid; /* --gid */ + const char *gname; /* --gname */ + int uid; /* --uid */ + const char *uname; /* --uname */ char mode; /* Program mode: 'c', 't', 'r', 'u', 'x' */ char symlink_mode; /* H or L, per BSD conventions */ char create_compression; /* j, y, or z */ @@ -68,7 +72,6 @@ struct bsdtar { char option_no_owner; /* -o */ char option_no_subdirs; /* -n */ char option_null; /* --null */ - char option_numeric_owner; /* --numeric-owner */ char option_stdout; /* -O */ char option_totals; /* --totals */ char option_unlink_first; /* -U */ @@ -113,7 +116,8 @@ enum { OPTION_DISABLE_COPYFILE, OPTION_EXCLUDE, OPTION_FORMAT, - OPTION_OPTIONS, + OPTION_GID, + OPTION_GNAME, OPTION_HELP, OPTION_INCLUDE, OPTION_KEEP_NEWER_FILES, @@ -128,10 +132,13 @@ enum { OPTION_NULL, OPTION_NUMERIC_OWNER, OPTION_ONE_FILE_SYSTEM, + OPTION_OPTIONS, OPTION_POSIX, OPTION_SAME_OWNER, OPTION_STRIP_COMPONENTS, OPTION_TOTALS, + OPTION_UID, + OPTION_UNAME, OPTION_USE_COMPRESS_PROGRAM, OPTION_VERSION }; diff --git a/tar/cmdline.c b/tar/cmdline.c index f53a76385..22346f154 100644 --- a/tar/cmdline.c +++ b/tar/cmdline.c @@ -85,6 +85,8 @@ static struct option { { "file", 1, 'f' }, { "files-from", 1, 'T' }, { "format", 1, OPTION_FORMAT }, + { "gid", 1, OPTION_GID }, + { "gname", 1, OPTION_GNAME }, { "gunzip", 0, 'z' }, { "gzip", 0, 'z' }, { "help", 0, OPTION_HELP }, @@ -119,6 +121,8 @@ static struct option { { "strip-components", 1, OPTION_STRIP_COMPONENTS }, { "to-stdout", 0, 'O' }, { "totals", 0, OPTION_TOTALS }, + { "uid", 1, OPTION_UID }, + { "uname", 1, OPTION_UNAME }, { "uncompress", 0, 'Z' }, { "unlink", 0, 'U' }, { "unlink-first", 0, 'U' }, diff --git a/tar/read.c b/tar/read.c index b6b4a7e9f..d5520dcbb 100644 --- a/tar/read.c +++ b/tar/read.c @@ -204,10 +204,18 @@ read_archive(struct bsdtar *bsdtar, char mode) if (r == ARCHIVE_FATAL) break; - if (bsdtar->option_numeric_owner) { + if (bsdtar->uid >= 0) { + archive_entry_set_uid(entry, bsdtar->uid); archive_entry_set_uname(entry, NULL); + } + if (bsdtar->gid >= 0) { + archive_entry_set_gid(entry, bsdtar->gid); archive_entry_set_gname(entry, NULL); } + if (bsdtar->uname) + archive_entry_set_uname(entry, bsdtar->uname); + if (bsdtar->gname >= 0) + archive_entry_set_gname(entry, bsdtar->gname); /* * Exclude entries that are too old. diff --git a/tar/write.c b/tar/write.c index ab370385c..4f3b5df17 100644 --- a/tar/write.c +++ b/tar/write.c @@ -833,6 +833,24 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) #endif r = archive_read_disk_entry_from_file(bsdtar->diskreader, entry, -1, st); + if (bsdtar->uid >= 0) { + archive_entry_set_uid(entry, bsdtar->uid); + if (!bsdtar->uname) + archive_entry_set_gname(entry, + archive_read_disk_uname(bsdtar->diskreader, + bsdtar->uid)); + } + if (bsdtar->gid >= 0) { + archive_entry_set_gid(entry, bsdtar->gid); + if (!bsdtar->gname) + archive_entry_set_gname(entry, + archive_read_disk_gname(bsdtar->diskreader, + bsdtar->gid)); + } + if (bsdtar->uname) + archive_entry_set_uname(entry, bsdtar->uname); + if (bsdtar->gname) + archive_entry_set_uname(entry, bsdtar->gname); if (r != ARCHIVE_OK) lafe_warnc(archive_errno(bsdtar->diskreader), "%s", archive_error_string(bsdtar->diskreader));