summaryrefslogtreecommitdiff
path: root/cpio/cmdline.c
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@gmail.com>2009-07-19 04:35:58 -0400
committerTim Kientzle <kientzle@gmail.com>2009-07-19 04:35:58 -0400
commit85c48957c151e86b9e20c4b3fcaa95f815d7a44c (patch)
tree7ef47b5bbb6091de9feec4539497336d540eed01 /cpio/cmdline.c
parent6f0409633d03a5eb1a72b262a156ebeae5d82f20 (diff)
downloadlibarchive-85c48957c151e86b9e20c4b3fcaa95f815d7a44c.tar.gz
Merge r195389 from FreeBSD-CURRENT: Rework the
numeric uid/gid support for the -R option. SVN-Revision: 1242
Diffstat (limited to 'cpio/cmdline.c')
-rw-r--r--cpio/cmdline.c58
1 files changed, 24 insertions, 34 deletions
diff --git a/cpio/cmdline.c b/cpio/cmdline.c
index 6dd6082b..d16386ca 100644
--- a/cpio/cmdline.c
+++ b/cpio/cmdline.c
@@ -279,29 +279,14 @@ cpio_getopt(struct cpio *cpio)
* :<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.
+ * are names to be looked up in system database. Note that we try
+ * to look up an argument as a name first, then try numeric parsing.
*
* A period can be used instead of the colon.
*
* 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)
{
@@ -310,6 +295,9 @@ owner_parse(const char *spec, int *uid, int *gid)
*uid = -1;
*gid = -1;
+ if (spec[0] == '\0')
+ return (1);
+
/*
* Split spec into [user][:.][group]
* u -> first char of username, NULL if no username
@@ -342,32 +330,34 @@ owner_parse(const char *spec, int *uid, int *gid)
}
memcpy(user, u, ue - u);
user[ue - u] = '\0';
- *uid = decimal_parse(user);
- if (*uid < 0) {
- /* Couldn't parse as integer, try username lookup. */
- pwent = getpwnam(user);
- if (pwent == NULL) {
+ if ((pwent = getpwnam(user)) != NULL) {
+ *uid = pwent->pw_uid;
+ if (*ue != '\0')
+ *gid = pwent->pw_gid;
+ } else {
+ char *end;
+ errno = 0;
+ *uid = strtoul(user, &end, 10);
+ if (errno || *end != '\0') {
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);
}
+
if (*g != '\0') {
- *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 {
+ struct group *grp;
+ if ((grp = getgrnam(g)) != NULL) {
+ *gid = grp->gr_gid;
+ } else {
+ char *end;
+ errno = 0;
+ *gid = strtoul(g, &end, 10);
+ if (errno || *end != '\0') {
lafe_warnc(errno,
- "Couldn't look up group ``%s''", g);
+ "Couldn't lookup group ``%s''", g);
return (1);
}
}