Skip to content

Commit

Permalink
Resolve TODO: Return uname and gname overrides
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Matuska <[email protected]>
  • Loading branch information
AreaZR and mmatuska committed May 10, 2024
1 parent eac15e2 commit 5c0db0d
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 29 deletions.
16 changes: 15 additions & 1 deletion cpio/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,17 @@ cpio_getopt(struct cpio *cpio)
*
*/
const char *
owner_parse(const char *spec, int *uid, int *gid)
owner_parse(const char *spec, int *uid, int *gid, char **uname, char **gname)
{
static char errbuff[128];
const char *u, *ue, *g;

*uid = -1;
*gid = -1;

*uname = NULL;
*gname = NULL;

if (spec[0] == '\0')
return ("Invalid empty user/group spec");

Expand Down Expand Up @@ -352,6 +355,11 @@ owner_parse(const char *spec, int *uid, int *gid)
user[ue - u] = '\0';
if ((pwent = getpwnam(user)) != NULL) {
*uid = pwent->pw_uid;
*uname = strdup(pwent->pw_name);
if (*uname == NULL) {
free(user);
return ("Couldn't allocate memory");
}
if (*ue != '\0')
*gid = pwent->pw_gid;
} else {
Expand All @@ -373,6 +381,12 @@ owner_parse(const char *spec, int *uid, int *gid)
struct group *grp;
if ((grp = getgrnam(g)) != NULL) {
*gid = grp->gr_gid;
*gname = strdup(grp->gr_name);
if (*gname == NULL) {
free(*uname);
*uname = NULL;
return ("Couldn't allocate memory");
}
} else {
char *end;
errno = 0;
Expand Down
37 changes: 23 additions & 14 deletions cpio/cpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ main(int argc, char *argv[])
struct cpio _cpio; /* Allocated on stack. */
struct cpio *cpio;
const char *errmsg;
char *uname, *gname;
char *tptr;
int uid, gid;
int opt, t;
Expand Down Expand Up @@ -161,7 +162,9 @@ main(int argc, char *argv[])
#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';
Expand Down Expand Up @@ -320,21 +323,20 @@ main(int argc, char *argv[])
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);
errmsg = owner_parse(cpio->argument, &uid, &gid,
&uname, &gname);
if (errmsg) {
lafe_warnc(-1, "%s", errmsg);
usage();
}
if (uid != -1) {
if (uid != -1)
cpio->uid_override = uid;
cpio->uname_override = NULL;
}
if (gid != -1) {
if (uname != NULL)
cpio->uname_override = uname;
if (gid != -1)
cpio->gid_override = gid;
cpio->gname_override = NULL;
}
if (gname != NULL)
cpio->gname_override = gname;
break;
case 'r': /* POSIX 1997 */
cpio->option_rename = 1;
Expand Down Expand Up @@ -439,11 +441,14 @@ main(int argc, char *argv[])
}

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);
}
Expand Down Expand Up @@ -728,14 +733,14 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
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.
Expand Down Expand Up @@ -1015,8 +1020,12 @@ mode_in(struct cpio *cpio)
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",
Expand Down
2 changes: 1 addition & 1 deletion cpio/cpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ struct cpio {
char *ppbuff;
};

const char *owner_parse(const char *, int *, int *);
const char *owner_parse(const char *, int *, int *, char **, char **);


/* Fake short equivalents for long options that otherwise lack them. */
Expand Down
61 changes: 48 additions & 13 deletions cpio/test/test_owner_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,58 +63,93 @@ DEFINE_TEST(test_owner_parse)
skipping("No uid/gid configuration for this OS");
#else
int uid, gid;
char *uname, *gname;

assert(NULL == owner_parse(ROOT, &uid, &gid));
assert(NULL == owner_parse(ROOT, &uid, &gid, &uname, &gname));
assert(int_in_list(uid, root_uids,
sizeof(root_uids)/sizeof(root_uids[0])));
assertEqualInt(-1, gid);
free(uname);
free(gname);


assert(NULL == owner_parse(ROOT ":", &uid, &gid));
assert(NULL == owner_parse(ROOT ":", &uid, &gid, &uname, &gname));
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])));
free(uname);
free(gname);

assert(NULL == owner_parse(ROOT ".", &uid, &gid));

assert(NULL == owner_parse(ROOT ".", &uid, &gid, &uname, &gname));
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])));
free(uname);
free(gname);


assert(NULL == owner_parse("111", &uid, &gid));
assert(NULL == owner_parse("111", &uid, &gid, &uname, &gname));
assertEqualInt(111, uid);
assertEqualInt(-1, gid);
free(uname);
free(gname);

assert(NULL == owner_parse("112:", &uid, &gid));

assert(NULL == owner_parse("112:", &uid, &gid, &uname, &gname));
assertEqualInt(112, uid);
/* Can't assert gid, since we don't know gid for user #112. */
free(uname);
free(gname);

assert(NULL == owner_parse("113.", &uid, &gid));
assert(NULL == owner_parse("113.", &uid, &gid, &uname, &gname));
assertEqualInt(113, uid);
/* Can't assert gid, since we don't know gid for user #113. */
free(uname);
free(gname);


assert(NULL == owner_parse(":114", &uid, &gid));
assert(NULL == owner_parse(":114", &uid, &gid, &uname, &gname));
assertEqualInt(-1, uid);
assertEqualInt(114, gid);
free(uname);
free(gname);

assert(NULL == owner_parse(".115", &uid, &gid));

assert(NULL == owner_parse(".115", &uid, &gid, &uname, &gname));
assertEqualInt(-1, uid);
assertEqualInt(115, gid);
free(uname);
free(gname);


assert(NULL == owner_parse("116:117", &uid, &gid));
assert(NULL == owner_parse("116:117", &uid, &gid, &uname, &gname));
assertEqualInt(116, uid);
assertEqualInt(117, gid);
free(uname);
free(gname);

/*
* TODO: Lookup current user/group name, build strings and
* use those to verify username/groupname lookups for ordinary
* users.
*/

assert(NULL != owner_parse(":nonexistentgroup", &uid, &gid));
assert(NULL != owner_parse(ROOT ":nonexistentgroup", &uid, &gid));
assert(NULL !=
owner_parse("nonexistentuser:nonexistentgroup", &uid, &gid));
assert(NULL != owner_parse(":nonexistentgroup", &uid, &gid, &uname,
&gname));
free(uname);
free(gname);

assert(NULL != owner_parse(ROOT ":nonexistentgroup", &uid, &gid,
&uname, &gname));
free(uname);
free(gname);

assert(NULL != owner_parse("nonexistentuser:nonexistentgroup", &uid,
&gid, &uname, &gname));
free(uname);
free(gname);
#endif
}

0 comments on commit 5c0db0d

Please sign in to comment.