From d09053013c6b467faa04444f079e9c3c15c04447 Mon Sep 17 00:00:00 2001 From: Rose <83477269+AtariDreams@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:33:21 -0500 Subject: [PATCH] Resolve TODO: Return uname and gname overrides Co-authored-by: Martin Matuska --- cpio/cmdline.c | 18 ++++++++++- cpio/cpio.c | 37 +++++++++++++--------- cpio/cpio.h | 2 +- cpio/test/test_owner_parse.c | 59 ++++++++++++++++++++++++++++-------- 4 files changed, 87 insertions(+), 29 deletions(-) diff --git a/cpio/cmdline.c b/cpio/cmdline.c index ab25492ede..f8e7dd489a 100644 --- a/cpio/cmdline.c +++ b/cpio/cmdline.c @@ -309,7 +309,7 @@ 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; @@ -317,6 +317,9 @@ owner_parse(const char *spec, int *uid, int *gid) *uid = -1; *gid = -1; + *uname = NULL; + *gname = NULL; + if (spec[0] == '\0') return ("Invalid empty user/group spec"); @@ -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 { @@ -373,6 +381,14 @@ 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) { + if (*uname != NULL) { + free(*uname); + *uname = NULL; + } + return ("Couldn't allocate memory"); + } } else { char *end; errno = 0; diff --git a/cpio/cpio.c b/cpio/cpio.c index c9af535f6d..35b89aa19b 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -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; @@ -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'; @@ -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; @@ -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); } @@ -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. @@ -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", diff --git a/cpio/cpio.h b/cpio/cpio.h index 3e97c0900b..a74637cf6e 100644 --- a/cpio/cpio.h +++ b/cpio/cpio.h @@ -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. */ diff --git a/cpio/test/test_owner_parse.c b/cpio/test/test_owner_parse.c index fc6f18943f..d0b7284481 100644 --- a/cpio/test/test_owner_parse.c +++ b/cpio/test/test_owner_parse.c @@ -63,46 +63,69 @@ 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); @@ -112,9 +135,19 @@ DEFINE_TEST(test_owner_parse) * 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 }