From 99b13cfb9796c39d58d5885c944eae2fb892aa72 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Fri, 3 Jul 2009 17:54:33 +0000 Subject: 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) --- usr.bin/cpio/cmdline.c | 68 ++++++++++++++++++++++++++++++++++++-------------- usr.bin/cpio/cpio.c | 2 +- 2 files changed, 50 insertions(+), 20 deletions(-) (limited to 'usr.bin/cpio') diff --git a/usr.bin/cpio/cmdline.c b/usr.bin/cpio/cmdline.c index 08d08f4e0f80..3970e601cb72 100644 --- a/usr.bin/cpio/cmdline.c +++ b/usr.bin/cpio/cmdline.c @@ -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: - * - Override user but not group - * : - Override both, group is user's default group - * : - Override both - * : - Override group but not user + * - Override user but not group + * : - Override both, group is user's default group + * : - Override user but not group + * : - Override both + * : - 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); diff --git a/usr.bin/cpio/cpio.c b/usr.bin/cpio/cpio.c index 73c66561b147..3b626f7f5405 100644 --- a/usr.bin/cpio/cpio.c +++ b/usr.bin/cpio/cpio.c @@ -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__) -- cgit v1.2.3