* Returns NULL if no error, otherwise returns error string for display.
*
*/
-const char *
-owner_parse(const char *spec, int *uid, int *gid)
+int
+owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
{
static char errbuff[128];
const char *u, *ue, *g;
- *uid = -1;
- *gid = -1;
+ owner->uid = -1;
+ owner->gid = -1;
+
+ owner->uname = NULL;
+ owner->gname = NULL;
- if (spec[0] == '\0')
- return ("Invalid empty user/group spec");
+ if (spec[0] == '\0') {
+ *errmsg = "Invalid empty user/group spec";
+ return (-1);
+ }
/*
* Split spec into [user][:.][group]
user = (char *)malloc(ue - u + 1);
if (user == NULL)
- return ("Couldn't allocate memory");
+ goto alloc_error;
memcpy(user, u, ue - u);
user[ue - u] = '\0';
if ((pwent = getpwnam(user)) != NULL) {
- *uid = pwent->pw_uid;
+ owner->uid = pwent->pw_uid;
+ owner->uname = strdup(pwent->pw_name);
+ if (owner->uname == NULL) {
+ free(user);
+ goto alloc_error;
+ }
if (*ue != '\0')
- *gid = pwent->pw_gid;
+ owner->gid = pwent->pw_gid;
} else {
char *end;
errno = 0;
- *uid = (int)strtoul(user, &end, 10);
+ owner->uid = (int)strtoul(user, &end, 10);
if (errno || *end != '\0') {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup user ``%s''", user);
errbuff[sizeof(errbuff) - 1] = '\0';
free(user);
- return (errbuff);
+ *errmsg = errbuff;
+ return (-1);
}
}
free(user);
if (*g != '\0') {
struct group *grp;
if ((grp = getgrnam(g)) != NULL) {
- *gid = grp->gr_gid;
+ owner->gid = grp->gr_gid;
+ owner->gname = strdup(grp->gr_name);
+ if (owner->gname == NULL) {
+ free(owner->uname);
+ owner->uname = NULL;
+ goto alloc_error;
+ }
} else {
char *end;
errno = 0;
- *gid = (int)strtoul(g, &end, 10);
+ owner->gid = (int)strtoul(g, &end, 10);
if (errno || *end != '\0') {
snprintf(errbuff, sizeof(errbuff),
"Couldn't lookup group ``%s''", g);
errbuff[sizeof(errbuff) - 1] = '\0';
- return (errbuff);
+ *errmsg = errbuff;
+ return (-1);
}
}
}
- return (NULL);
+ return (0);
+alloc_error:
+ *errmsg = "Couldn't allocate memory";
+ return (-1);
}
static char buff[16384];
struct cpio _cpio; /* Allocated on stack. */
struct cpio *cpio;
+ struct cpio_owner owner;
const char *errmsg;
char *tptr;
- int uid, gid;
int opt, t;
cpio = &_cpio;
cpio->buff = buff;
cpio->buff_size = sizeof(buff);
+
#if defined(HAVE_SIGACTION) && defined(SIGPIPE)
{ /* Ignore SIGPIPE signals. */
struct sigaction sa;
#endif
cpio->uid_override = -1;
+ cpio->uname_override = NULL;
cpio->gid_override = -1;
+ cpio->gname_override = NULL;
cpio->argv = argv;
cpio->argc = argc;
cpio->mode = '\0';
cpio->quiet = 1;
break;
case 'R': /* GNU cpio, also --owner */
- /* TODO: owner_parse should return uname/gname
- * also; use that to set [ug]name_override. */
- errmsg = owner_parse(cpio->argument, &uid, &gid);
- if (errmsg) {
+ errmsg = NULL;
+ if (owner_parse(cpio->argument, &owner, &errmsg) != 0) {
+ if (!errmsg)
+ errmsg = "Error parsing owner";
lafe_warnc(-1, "%s", errmsg);
usage();
}
- if (uid != -1) {
- cpio->uid_override = uid;
- cpio->uname_override = NULL;
- }
- if (gid != -1) {
- cpio->gid_override = gid;
- cpio->gname_override = NULL;
- }
+ if (owner.uid != -1)
+ cpio->uid_override = owner.uid;
+ if (owner.uname != NULL)
+ cpio->uname_override = owner.uname;
+ if (owner.gid != -1)
+ cpio->gid_override = owner.gid;
+ if (owner.gname != NULL)
+ cpio->gname_override = owner.gname;
break;
case 'r': /* POSIX 1997 */
cpio->option_rename = 1;
}
archive_match_free(cpio->matching);
- free_cache(cpio->gname_cache);
free_cache(cpio->uname_cache);
+ free(cpio->uname_override);
+ free_cache(cpio->gname_cache);
+ free(cpio->gname_override);
archive_read_close(cpio->archive_read_disk);
archive_read_free(cpio->archive_read_disk);
free(cpio->destdir);
+
passphrase_free(cpio->ppbuff);
return (cpio->return_value);
}
return (r);
}
- if (cpio->uid_override >= 0) {
+ if (cpio->uid_override >= 0)
archive_entry_set_uid(entry, cpio->uid_override);
+ if (cpio->gname_override != NULL)
archive_entry_set_uname(entry, cpio->uname_override);
- }
- if (cpio->gid_override >= 0) {
+ if (cpio->gid_override >= 0)
archive_entry_set_gid(entry, cpio->gid_override);
+ if (cpio->gname_override != NULL)
archive_entry_set_gname(entry, cpio->gname_override);
- }
/*
* Generate a destination path for this entry.
fprintf(stderr, ".");
if (cpio->uid_override >= 0)
archive_entry_set_uid(entry, cpio->uid_override);
+ if (cpio->uname_override != NULL)
+ archive_entry_set_uname(entry, cpio->uname_override);
if (cpio->gid_override >= 0)
archive_entry_set_gid(entry, cpio->gid_override);
+ if (cpio->gname_override != NULL)
+ archive_entry_set_gname(entry, cpio->gname_override);
r = archive_write_header(ext, entry);
if (r != ARCHIVE_OK) {
fprintf(stderr, "%s: %s\n",
failure("%d", i);
return (0);
}
+
+static void
+free_cpio_owner(struct cpio_owner *owner) {
+ owner->uid = -1;
+ owner->gid = -1;
+ free(owner->uname);
+ free(owner->gname);
+}
#endif
DEFINE_TEST(test_owner_parse)
#if !defined(ROOT)
skipping("No uid/gid configuration for this OS");
#else
- int uid, gid;
+ struct cpio_owner owner;
+ const char *errstr;
- assert(NULL == owner_parse(ROOT, &uid, &gid));
- assert(int_in_list(uid, root_uids,
+ assert(0 == owner_parse(ROOT, &owner, &errstr));
+ assert(int_in_list(owner.uid, root_uids,
sizeof(root_uids)/sizeof(root_uids[0])));
- assertEqualInt(-1, gid);
-
+ assertEqualInt(-1, owner.gid);
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse(ROOT ":", &uid, &gid));
- assert(int_in_list(uid, root_uids,
+ assert(0 == owner_parse(ROOT ":", &owner, &errstr));
+ assert(int_in_list(owner.uid, root_uids,
sizeof(root_uids)/sizeof(root_uids[0])));
- assert(int_in_list(gid, root_gids,
+ assert(int_in_list(owner.gid, root_gids,
sizeof(root_gids)/sizeof(root_gids[0])));
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse(ROOT ".", &uid, &gid));
- assert(int_in_list(uid, root_uids,
+ assert(0 == owner_parse(ROOT ".", &owner, &errstr));
+ assert(int_in_list(owner.uid, root_uids,
sizeof(root_uids)/sizeof(root_uids[0])));
- assert(int_in_list(gid, root_gids,
+ assert(int_in_list(owner.gid, root_gids,
sizeof(root_gids)/sizeof(root_gids[0])));
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse("111", &uid, &gid));
- assertEqualInt(111, uid);
- assertEqualInt(-1, gid);
+ assert(0 == owner_parse("111", &owner, &errstr));
+ assertEqualInt(111, owner.uid);
+ assertEqualInt(-1, owner.gid);
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse("112:", &uid, &gid));
- assertEqualInt(112, uid);
+ assert(0 == owner_parse("112:", &owner, &errstr));
+ assertEqualInt(112, owner.uid);
/* Can't assert gid, since we don't know gid for user #112. */
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse("113.", &uid, &gid));
- assertEqualInt(113, uid);
+ assert(0 == owner_parse("113.", &owner, &errstr));
+ assertEqualInt(113, owner.uid);
/* Can't assert gid, since we don't know gid for user #113. */
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse(":114", &uid, &gid));
- assertEqualInt(-1, uid);
- assertEqualInt(114, gid);
+ assert(0 == owner_parse(":114", &owner, &errstr));
+ assertEqualInt(-1, owner.uid);
+ assertEqualInt(114, owner.gid);
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse(".115", &uid, &gid));
- assertEqualInt(-1, uid);
- assertEqualInt(115, gid);
+ assert(0 == owner_parse(".115", &owner, &errstr));
+ assertEqualInt(-1, owner.uid);
+ assertEqualInt(115, owner.gid);
+ free_cpio_owner(&owner);
- assert(NULL == owner_parse("116:117", &uid, &gid));
- assertEqualInt(116, uid);
- assertEqualInt(117, gid);
+ assert(0 == owner_parse("116:117", &owner, &errstr));
+ assertEqualInt(116, owner.uid);
+ assertEqualInt(117, owner.gid);
+ free_cpio_owner(&owner);
/*
* TODO: Lookup current user/group name, build strings and
* users.
*/
- assert(NULL != owner_parse(":nonexistentgroup", &uid, &gid));
- assert(NULL != owner_parse(ROOT ":nonexistentgroup", &uid, &gid));
- assert(NULL !=
- owner_parse("nonexistentuser:nonexistentgroup", &uid, &gid));
+ errstr = NULL;
+ assert(0 != owner_parse(":nonexistentgroup", &owner, &errstr));
+ assertEqualString(errstr, "Couldn't lookup group ``nonexistentgroup''");
+ free_cpio_owner(&owner);
+
+ errstr = NULL;
+ assert(0 != owner_parse(ROOT ":nonexistentgroup", &owner, &errstr));
+ assertEqualString(errstr, "Couldn't lookup group ``nonexistentgroup''");
+ free_cpio_owner(&owner);
+
+ errstr = NULL;
+ assert(0 != owner_parse("nonexistentuser:nonexistentgroup", &owner,
+ &errstr));
+ assertEqualString(errstr, "Couldn't lookup user ``nonexistentuser''");
+ free_cpio_owner(&owner);
#endif
}