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:
Paul Eggert
2011-08-13 10:20:40 -07:00
parent 9fe65e2520
commit 1f9b376c90
8 changed files with 174 additions and 38 deletions
+4 -2
View File
@@ -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
View File
@@ -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
+78 -24
View File
@@ -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;