mirror of
https://git.savannah.gnu.org/git/tar.git
synced 2026-09-06 08:16:54 +00:00
tar: --owner and --group names and numbers
The --owner and --group options now accept operands of the form NAME:NUM, so that you can specify both symbolic name and numeric ID for owner and group. Also, in these options, NAME no longer needs to be present in the current host's user and group databases; this implements Debian enhancement request 136231 <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=136231> reported by Mark W. Eichin, communicated by Thayne Harbaugh to bug-tar in <http://lists.gnu.org/archive/html/bug-tar/2011-08/msg00001.html>. * NEWS, doc/tar.texi (Option Summary, override): Document enhancement. * src/common.h (group_name_option, owner_name_option): New decls. * src/create.c (start_header): Don't assume owner and group names are in current host database. * src/tar.c (parse_owner_group): New function, for parsing NAME:NUM. (parse_opt): Use it. (decode_options): Initialize owner_name_option, group_name_option. * tests/owner.at: New file, to test this enhancement. * tests/Makefile.am (TESTSUITE_AT): Add it. * tests/testsuite.at: Include it.
This commit is contained in:
+4
-2
@@ -158,7 +158,8 @@ enum exclusion_tag_type
|
||||
};
|
||||
|
||||
/* Specified value to be put into tar file in place of stat () results, or
|
||||
just -1 if such an override should not take place. */
|
||||
just null and -1 if such an override should not take place. */
|
||||
GLOBAL char const *group_name_option;
|
||||
GLOBAL gid_t group_option;
|
||||
|
||||
GLOBAL bool ignore_failed_read_option;
|
||||
@@ -230,7 +231,8 @@ GLOBAL bool numeric_owner_option;
|
||||
GLOBAL bool one_file_system_option;
|
||||
|
||||
/* Specified value to be put into tar file in place of stat () results, or
|
||||
just -1 if such an override should not take place. */
|
||||
just null and -1 if such an override should not take place. */
|
||||
GLOBAL char const *owner_name_option;
|
||||
GLOBAL uid_t owner_option;
|
||||
|
||||
GLOBAL bool recursive_unlink_option;
|
||||
|
||||
+9
-2
@@ -920,8 +920,15 @@ start_header (struct tar_stat_info *st)
|
||||
}
|
||||
else
|
||||
{
|
||||
uid_to_uname (st->stat.st_uid, &st->uname);
|
||||
gid_to_gname (st->stat.st_gid, &st->gname);
|
||||
if (owner_name_option)
|
||||
st->uname = xstrdup (owner_name_option);
|
||||
else
|
||||
uid_to_uname (st->stat.st_uid, &st->uname);
|
||||
|
||||
if (group_name_option)
|
||||
st->gname = xstrdup (group_name_option);
|
||||
else
|
||||
gid_to_gname (st->stat.st_gid, &st->gname);
|
||||
|
||||
if (archive_format == POSIX_FORMAT
|
||||
&& (strlen (st->uname) > UNAME_FIELD_SIZE
|
||||
|
||||
@@ -1364,6 +1364,58 @@ expand_pax_option (struct tar_args *targs, const char *arg)
|
||||
}
|
||||
|
||||
|
||||
static uintmax_t
|
||||
parse_owner_group (char *arg, uintmax_t field_max, char const **name_option)
|
||||
{
|
||||
strtol_error err;
|
||||
uintmax_t u = UINTMAX_MAX;
|
||||
char *end;
|
||||
char const *name = 0;
|
||||
char const *invalid_num = 0;
|
||||
char *colon = strchr (arg, ':');
|
||||
|
||||
if (colon)
|
||||
{
|
||||
char const *num = colon + 1;
|
||||
*colon = '\0';
|
||||
if (*arg)
|
||||
name = arg;
|
||||
if (num && (! (xstrtoumax (num, &end, 10, &u, "") == LONGINT_OK
|
||||
&& u <= field_max)))
|
||||
invalid_num = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
uintmax_t u1;
|
||||
switch ('0' <= *arg && *arg <= '9'
|
||||
? xstrtoumax (arg, &end, 10, &u1, "")
|
||||
: LONGINT_INVALID)
|
||||
{
|
||||
default:
|
||||
name = arg;
|
||||
break;
|
||||
|
||||
case LONGINT_OK:
|
||||
if (u1 <= field_max)
|
||||
{
|
||||
u = u1;
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case LONGINT_OVERFLOW:
|
||||
invalid_num = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid_num)
|
||||
FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (invalid_num),
|
||||
_("Invalid owner or group ID")));
|
||||
if (name)
|
||||
*name_option = name;
|
||||
return u;
|
||||
}
|
||||
|
||||
#define TAR_SIZE_SUFFIXES "bBcGgkKMmPTtw"
|
||||
|
||||
static error_t
|
||||
@@ -1836,17 +1888,18 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
break;
|
||||
|
||||
case GROUP_OPTION:
|
||||
if (! (strlen (arg) < GNAME_FIELD_SIZE
|
||||
&& gname_to_gid (arg, &group_option)))
|
||||
{
|
||||
uintmax_t g;
|
||||
if (xstrtoumax (arg, 0, 10, &g, "") == LONGINT_OK
|
||||
&& g == (gid_t) g)
|
||||
group_option = g;
|
||||
else
|
||||
FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
||||
_("Invalid group")));
|
||||
}
|
||||
{
|
||||
uintmax_t u = parse_owner_group (arg, TYPE_MAXIMUM (gid_t),
|
||||
&group_name_option);
|
||||
if (u == UINTMAX_MAX)
|
||||
{
|
||||
group_option = -1;
|
||||
if (group_name_option)
|
||||
gname_to_gid (group_name_option, &group_option);
|
||||
}
|
||||
else
|
||||
group_option = u;
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_OPTION:
|
||||
@@ -1922,17 +1975,18 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
break;
|
||||
|
||||
case OWNER_OPTION:
|
||||
if (! (strlen (arg) < UNAME_FIELD_SIZE
|
||||
&& uname_to_uid (arg, &owner_option)))
|
||||
{
|
||||
uintmax_t u;
|
||||
if (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK
|
||||
&& u == (uid_t) u)
|
||||
owner_option = u;
|
||||
else
|
||||
FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (arg),
|
||||
_("Invalid owner")));
|
||||
}
|
||||
{
|
||||
uintmax_t u = parse_owner_group (arg, TYPE_MAXIMUM (uid_t),
|
||||
&owner_name_option);
|
||||
if (u == UINTMAX_MAX)
|
||||
{
|
||||
owner_option = -1;
|
||||
if (owner_name_option)
|
||||
uname_to_uid (owner_name_option, &owner_option);
|
||||
}
|
||||
else
|
||||
owner_option = u;
|
||||
}
|
||||
break;
|
||||
|
||||
case QUOTE_CHARS_OPTION:
|
||||
@@ -2241,8 +2295,8 @@ decode_options (int argc, char **argv)
|
||||
tar_sparse_major = 1;
|
||||
tar_sparse_minor = 0;
|
||||
|
||||
owner_option = -1;
|
||||
group_option = -1;
|
||||
owner_option = -1; owner_name_option = NULL;
|
||||
group_option = -1; group_name_option = NULL;
|
||||
|
||||
check_device_option = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user