Author: kientzle
Date: Fri Jul  3 17:54:33 2009
New Revision: 195318
URL: http://svn.freebsd.org/changeset/base/195318

Log:
  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)

Modified:
  head/usr.bin/cpio/cmdline.c
  head/usr.bin/cpio/cpio.c

Modified: head/usr.bin/cpio/cmdline.c
==============================================================================
--- head/usr.bin/cpio/cmdline.c Fri Jul  3 16:33:42 2009        (r195317)
+++ head/usr.bin/cpio/cmdline.c Fri Jul  3 17:54:33 2009        (r195318)
@@ -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, 
                }
                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);

Modified: head/usr.bin/cpio/cpio.c
==============================================================================
--- head/usr.bin/cpio/cpio.c    Fri Jul  3 16:33:42 2009        (r195317)
+++ head/usr.bin/cpio/cpio.c    Fri Jul  3 17:54:33 2009        (r195318)
@@ -575,7 +575,7 @@ file_to_archive(struct cpio *cpio, const
        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__)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to