]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Support decimal uid/gid when parsing -R/--owner option.
authorTim Kientzle <kientzle@gmail.com>
Thu, 2 Jul 2009 04:17:34 +0000 (00:17 -0400)
committerTim Kientzle <kientzle@gmail.com>
Thu, 2 Jul 2009 04:17:34 +0000 (00:17 -0400)
Extend existing test to cover new functionality.
Rework this test slightly to reduce conditionals for Cygwin.

SVN-Revision: 1208

cpio/cmdline.c
cpio/test/test_owner_parse.c

index 33307bb34f0476d64fc18e3f46bfc9c0eb5c8c28..f090e260b5486f08c629c337ee8169027f3a155f 100644 (file)
@@ -271,16 +271,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)
 {
@@ -321,24 +341,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) {
-                       lafe_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) {
+                               lafe_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 {
-                       lafe_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 {
+                               lafe_warnc(errno,
+                                   "Couldn't look up group ``%s''", g);
+                               return (1);
+                       }
                }
        }
        return (0);
index b756a2f811e10e4325fe7ba3e95ad73c8e97905b..050d5a088d28d3e4563503b5e89db12dc58392bf 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2009 Tim Kientzle
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,16 +38,23 @@ __FBSDID("$FreeBSD$");
  *       Use CreateWellKnownSID() and LookupAccountName()?
  */
 #define ROOT "Administrator"
-#define ROOT_UID 500
-#define ROOT_GID1 513
-#define ROOT_GID2 545
-#define ROOT_GID3 544
+static int root_uids[] = { 500 };
+static int root_gids[] = { 513, 545, 544 };
 #else
 #define ROOT "root"
-#define ROOT_UID 0
-#define ROOT_GID 0
+static int root_uids[] = { 0 };
+static int root_gids[] = { 0 };
 #endif
 
+static int
+int_in_list(int i, int *l, size_t n)
+{
+       while (n-- > 0)
+               if (*l++ == i)
+                       return (1);
+       return (0);
+}
+
 DEFINE_TEST(test_owner_parse)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -56,38 +63,49 @@ DEFINE_TEST(test_owner_parse)
 #else
        int uid, gid;
 
-       lafe_progname = "Ignore this message";
+       lafe_progname = "cpio";
 
        assertEqualInt(0, owner_parse(ROOT, &uid, &gid));
-       assertEqualInt(ROOT_UID, uid);
+       assert(int_in_list(uid, root_uids,
+               sizeof(root_uids)/sizeof(root_uids[0])));
        assertEqualInt(-1, gid);
 
 
        assertEqualInt(0, owner_parse(ROOT ":", &uid, &gid));
-       assertEqualInt(ROOT_UID, uid);
-#if defined(__CYGWIN__)
-       {
-               int gidIsOneOf = (ROOT_GID1 == gid)
-                       || (ROOT_GID2 == gid)
-                       || (ROOT_GID3 == gid);
-               assertEqualInt(1, gidIsOneOf);
-       }
-#else
-       assertEqualInt(ROOT_GID, gid);
-#endif
+       assert(int_in_list(uid, root_uids,
+               sizeof(root_uids)/sizeof(root_uids[0])));
+       assert(int_in_list(gid, root_gids,
+               sizeof(root_gids)/sizeof(root_gids[0])));
 
        assertEqualInt(0, owner_parse(ROOT ".", &uid, &gid));
-       assertEqualInt(ROOT_UID, uid);
-#if defined(__CYGWIN__)
-       {
-               int gidIsOneOf = (ROOT_GID1 == gid)
-                       || (ROOT_GID2 == gid)
-                       || (ROOT_GID3 == gid);
-               assertEqualInt(1, gidIsOneOf);
-       }
-#else
-       assertEqualInt(ROOT_GID, gid);
-#endif
+       assert(int_in_list(uid, root_uids,
+               sizeof(root_uids)/sizeof(root_uids[0])));
+       assert(int_in_list(gid, root_gids,
+               sizeof(root_gids)/sizeof(root_gids[0])));
+
+       assertEqualInt(0, owner_parse("111", &uid, &gid));
+       assertEqualInt(111, uid);
+       assertEqualInt(-1, gid);
+
+       assertEqualInt(0, owner_parse("112:", &uid, &gid));
+       assertEqualInt(112, uid);
+       /* Can't assert gid, since we don't know gid for user #112. */
+
+       assertEqualInt(0, owner_parse("113.", &uid, &gid));
+       assertEqualInt(113, uid);
+       /* Can't assert gid, since we don't know gid for user #113. */
+
+       assertEqualInt(0, owner_parse(":114", &uid, &gid));
+       assertEqualInt(-1, uid);
+       assertEqualInt(114, gid);
+
+       assertEqualInt(0, owner_parse(".115", &uid, &gid));
+       assertEqualInt(-1, uid);
+       assertEqualInt(115, gid);
+
+       assertEqualInt(0, owner_parse("116:117", &uid, &gid));
+       assertEqualInt(116, uid);
+       assertEqualInt(117, gid);
 
        /*
         * TODO: Lookup current user/group name, build strings and
@@ -104,6 +122,7 @@ DEFINE_TEST(test_owner_parse)
         * Alternatively, redirect stderr temporarily to suppress the output.
         */
 
+       lafe_progname = "Ignore this message";
        assertEqualInt(1, owner_parse(":nonexistentgroup", &uid, &gid));
        assertEqualInt(1, owner_parse(ROOT ":nonexistentgroup", &uid, &gid));
        assertEqualInt(1,