This fixes bsdcpio's -R option to accept numeric

user or group Ids as well as user or group names.
In particular, this fixes freesbie2, which uses
-R 0:0 to copy a bunch of files so that the result
will be owned by root.

Also fixes a related bug that mixed-up the uid
and gid specified by -R when in passthrough mode.

Thanks to Dominique Goncalves for reporting this
regression.

Approved by:	re (kib)
This commit is contained in:
kientzle 2009-07-03 17:54:33 +00:00
parent 7ce4ab7ff8
commit 49230574bc
2 changed files with 50 additions and 20 deletions

View File

@ -268,16 +268,36 @@ cpio_getopt(struct cpio *cpio)
* Parse the argument to the -R or --owner flag.
*
* The format is one of the following:
* <user> - Override user but not group
* <user>: - Override both, group is user's default group
* <user>:<group> - Override both
* :<group> - Override group but not user
* <username|uid> - Override user but not group
* <username>: - Override both, group is user's default group
* <uid>: - Override user but not group
* <username|uid>:<groupname|gid> - Override both
* :<groupname|gid> - Override group but not user
*
* Where uid/gid are decimal representations and groupname/username
* are names to be looked up in system database. Note that
* uid/gid parsing takes priority over username/groupname lookup,
* so this won't do a lookup for usernames or group names that
* consist entirely of digits.
*
* A period can be used instead of the colon.
*
* Sets uid/gid as appropriate, -1 indicates uid/gid not specified.
* Sets uid/gid return as appropriate, -1 indicates uid/gid not specified.
*
*/
static int
decimal_parse(const char *p)
{
/* TODO: guard against overflow. */
int n = 0;
for (; *p != '\0'; ++p) {
if (*p < '0' || *p > '9')
return (-1);
n = n * 10 + *p - '0';
}
return (n);
}
int
owner_parse(const char *spec, int *uid, int *gid)
{
@ -318,24 +338,34 @@ owner_parse(const char *spec, int *uid, int *gid)
}
memcpy(user, u, ue - u);
user[ue - u] = '\0';
pwent = getpwnam(user);
if (pwent == NULL) {
cpio_warnc(errno, "Couldn't lookup user ``%s''", user);
return (1);
*uid = decimal_parse(user);
if (*uid < 0) {
/* Couldn't parse as integer, try username lookup. */
pwent = getpwnam(user);
if (pwent == NULL) {
cpio_warnc(errno,
"Couldn't lookup user ``%s''", user);
return (1);
}
*uid = pwent->pw_uid;
if (*ue != '\0' && *g == '\0')
*gid = pwent->pw_gid;
}
free(user);
*uid = pwent->pw_uid;
if (*ue != '\0' && *g == '\0')
*gid = pwent->pw_gid;
}
if (*g != '\0') {
struct group *grp;
grp = getgrnam(g);
if (grp != NULL)
*gid = grp->gr_gid;
else {
cpio_warnc(errno, "Couldn't look up group ``%s''", g);
return (1);
*gid = decimal_parse(g);
if (*gid < 0) {
/* Couldn't parse int, try group name lookup. */
struct group *grp;
grp = getgrnam(g);
if (grp != NULL)
*gid = grp->gr_gid;
else {
cpio_warnc(errno,
"Couldn't look up group ``%s''", g);
return (1);
}
}
}
return (0);

View File

@ -575,7 +575,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
if (cpio->uid_override >= 0)
st.st_uid = cpio->uid_override;
if (cpio->gid_override >= 0)
st.st_gid = cpio->uid_override;
st.st_gid = cpio->gid_override;
archive_entry_copy_stat(entry, &st);
#if !defined(_WIN32) || defined(__CYGWIN__)