summaryrefslogtreecommitdiffstats
path: root/usr.bin/cpio
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2009-07-03 17:54:33 +0000
committerkientzle <kientzle@FreeBSD.org>2009-07-03 17:54:33 +0000
commit49230574bc3ffa0492adf89dfd2c3acca620b5a6 (patch)
tree612c1e7e7f2222f2d4a36a9df0148424d38236f9 /usr.bin/cpio
parent7ce4ab7ff8542c3c45b1203177f667e0ee30a088 (diff)
downloadFreeBSD-src-49230574bc3ffa0492adf89dfd2c3acca620b5a6.zip
FreeBSD-src-49230574bc3ffa0492adf89dfd2c3acca620b5a6.tar.gz
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)
Diffstat (limited to 'usr.bin/cpio')
-rw-r--r--usr.bin/cpio/cmdline.c68
-rw-r--r--usr.bin/cpio/cpio.c2
2 files changed, 50 insertions, 20 deletions
diff --git a/usr.bin/cpio/cmdline.c b/usr.bin/cpio/cmdline.c
index 08d08f4..3970e60 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:
- * <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);
diff --git a/usr.bin/cpio/cpio.c b/usr.bin/cpio/cpio.c
index 73c6656..3b626f7 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__)
OpenPOWER on IntegriCloud