[PATCH] cpio: implement -R/--owner

Aaro Koskinen aaro.koskinen at iki.fi
Thu Oct 15 19:43:35 UTC 2015


Implement -R/--owner to force ownership of files.

function                                             old     new   delta
cpio_main                                            501     556     +55
usage_messages                                     40468   40504     +36
get_header_cpio                                      910     943     +33
cpio_o                                               814     844     +30
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 154/0)             Total: 154 bytes

Signed-off-by: Aaro Koskinen <aaro.koskinen at iki.fi>
---
 archival/cpio.c                       | 40 ++++++++++++++++++++++++++++++-----
 archival/libarchive/get_header_cpio.c |  6 ++++++
 include/bb_archive.h                  |  1 +
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/archival/cpio.c b/archival/cpio.c
index cdc16c1..05a20c7 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -71,6 +71,7 @@
 //usage:     "\n	-v	Verbose"
 //usage:     "\n	-u	Overwrite"
 //usage:     "\n	-F FILE	Input (-t,-i,-p) or output (-o) file"
+//usage:     "\n	-R UGID Set owner of created files"
 //usage:	IF_FEATURE_CPIO_O(
 //usage:     "\n	-H newc	Archive format"
 //usage:	)
@@ -150,7 +151,8 @@ enum {
 	OPT_PRESERVE_MTIME     = (1 << 6),
 	OPT_DEREF              = (1 << 7),
 	OPT_FILE               = (1 << 8),
-	OPTBIT_FILE = 8,
+	OPT_OWNER              = (1 << 9),
+	OPTBIT_OWNER = 9,
 	IF_FEATURE_CPIO_O(OPTBIT_CREATE     ,)
 	IF_FEATURE_CPIO_O(OPTBIT_FORMAT     ,)
 	IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,)
@@ -163,7 +165,20 @@ enum {
 	OPT_2STDOUT            = IF_LONG_OPTS(     (1 << OPTBIT_2STDOUT    )) + 0,
 };
 
-#define OPTION_STR "it0uvdmLF:"
+#define OPTION_STR "it0uvdmLF:R:"
+
+struct globals {
+	struct bb_uidgid_t owner_ugid;
+} FIX_ALIASING;
+#define G (*(struct globals*)&bb_common_bufsiz1)
+#define owner_ugid (G.owner_ugid)
+void BUG_cpio_globals_too_big(void);
+#define INIT_G() do { \
+	if (sizeof(G) > COMMON_BUFSIZE) \
+		BUG_cpio_globals_too_big(); \
+	owner_ugid.uid = -1L; \
+	owner_ugid.gid = -1L; \
+} while (0)
 
 #if ENABLE_FEATURE_CPIO_O
 static off_t cpio_pad4(off_t size)
@@ -223,6 +238,11 @@ static NOINLINE int cpio_o(void)
 				bb_simple_perror_msg_and_die(name);
 			}
 
+			if (owner_ugid.uid != (uid_t)-1L)
+				st.st_uid = owner_ugid.uid;
+			if (owner_ugid.gid != (gid_t)-1L)
+				st.st_gid = owner_ugid.gid;
+
 			if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode)))
 				st.st_size = 0; /* paranoia */
 
@@ -339,6 +359,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
 {
 	archive_handle_t *archive_handle;
 	char *cpio_filename;
+	char *cpio_owner;
 	IF_FEATURE_CPIO_O(const char *cpio_fmt = "";)
 	unsigned opt;
 
@@ -353,12 +374,14 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
 		"pass-through\0" No_argument       "p"
 #endif
 #endif
+		"owner\0"        Required_argument "R"
 		"verbose\0"      No_argument       "v"
 		"quiet\0"        No_argument       "\xff"
 		"to-stdout\0"    No_argument       "\xfe"
 		;
 #endif
 
+	INIT_G();
 	archive_handle = init_handle();
 	/* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */
 	archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
@@ -369,14 +392,21 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
 	/* -L makes sense only with -o or -p */
 
 #if !ENABLE_FEATURE_CPIO_O
-	opt = getopt32(argv, OPTION_STR, &cpio_filename);
+	opt = getopt32(argv, OPTION_STR, &cpio_filename, &cpio_owner);
+#else
+	opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"),
+		       &cpio_filename, &cpio_owner, &cpio_fmt);
+#endif
 	argv += optind;
+	if (opt & OPT_OWNER) {
+		parse_chown_usergroup_or_die(&owner_ugid, cpio_owner);
+		archive_handle->cpio__owner = &owner_ugid;
+	}
+#if !ENABLE_FEATURE_CPIO_O
 	if (opt & OPT_FILE) { /* -F */
 		xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
 	}
 #else
-	opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt);
-	argv += optind;
 	if ((opt & (OPT_FILE|OPT_CREATE)) == OPT_FILE) { /* -F without -o */
 		xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
 	}
diff --git a/archival/libarchive/get_header_cpio.c b/archival/libarchive/get_header_cpio.c
index 7861d1f..1cfcf56 100644
--- a/archival/libarchive/get_header_cpio.c
+++ b/archival/libarchive/get_header_cpio.c
@@ -52,6 +52,12 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
 			&major, &minor, &namesize) != 10)
 		bb_error_msg_and_die("damaged cpio file");
 	file_header->mode = mode;
+	if (archive_handle->cpio__owner) {
+		if (archive_handle->cpio__owner->uid != (uid_t)-1L)
+			uid = archive_handle->cpio__owner->uid;
+		if (archive_handle->cpio__owner->gid != (gid_t)-1L)
+			gid = archive_handle->cpio__owner->gid;
+	}
 	file_header->uid = uid;
 	file_header->gid = gid;
 	file_header->mtime = mtime;
diff --git a/include/bb_archive.h b/include/bb_archive.h
index 5d9e24c..84164e4 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -97,6 +97,7 @@ typedef struct archive_handle_t {
 	uoff_t cpio__blocks;
 	struct hardlinks_t *cpio__hardlinks_to_create;
 	struct hardlinks_t *cpio__created_hardlinks;
+	struct bb_uidgid_t *cpio__owner;
 #endif
 #if ENABLE_DPKG || ENABLE_DPKG_DEB
 	/* Temporary storage */
-- 
2.4.0



More information about the busybox mailing list