[git commit] unzip: make options parsing more robust on getopt w/o gnu extensions

Denys Vlasenko vda.linux at googlemail.com
Fri Jun 15 14:43:26 UTC 2012


commit: http://git.busybox.net/busybox/commit/?id=c5b01016e622f01dfa9c8c542c0968fe37d4a5f2
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Also, code shrank:

function                                             old     new   delta
static.extn                                           15      10      -5
packed_usage                                       29231   29217     -14
unzip_main                                          2388    2291     -97
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-116)           Total: -116 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 archival/unzip.c |  137 +++++++++++++++++++++++++++--------------------------
 1 files changed, 70 insertions(+), 67 deletions(-)

diff --git a/archival/unzip.c b/archival/unzip.c
index c1b945a..3806747 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -20,11 +20,11 @@
  */
 
 //usage:#define unzip_trivial_usage
-//usage:       "[-opts[modifiers]] FILE[.zip] [LIST] [-x XLIST] [-d DIR]"
+//usage:       "[-lnopq] FILE[.zip] [LIST] [-x XLIST] [-d DIR]"
 //usage:#define unzip_full_usage "\n\n"
 //usage:       "Extract files from ZIP archives\n"
 //usage:     "\n	-l	List archive contents (with -q for short form)"
-//usage:     "\n	-n	Never overwrite files (default)"
+//usage:     "\n	-n	Never overwrite files (default: ask)"
 //usage:     "\n	-o	Overwrite"
 //usage:     "\n	-p	Send output to stdout"
 //usage:     "\n	-q	Quiet"
@@ -277,6 +277,7 @@ int unzip_main(int argc, char **argv)
 	IF_NOT_DESKTOP(const) smallint verbose = 0;
 	smallint listing = 0;
 	smallint overwrite = O_PROMPT;
+	smallint x_opt_seen;
 #if ENABLE_DESKTOP
 	uint32_t cdf_offset;
 #endif
@@ -290,7 +291,6 @@ int unzip_main(int argc, char **argv)
 	llist_t *zreject = NULL;
 	char *base_dir = NULL;
 	int i, opt;
-	int opt_range = 0;
 	char key_buf[80];
 	struct stat stat_buf;
 
@@ -335,81 +335,81 @@ int unzip_main(int argc, char **argv)
  *    204372                   1 file
  */
 
+	x_opt_seen = 0;
 	/* '-' makes getopt return 1 for non-options */
 	while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) {
-		switch (opt_range) {
-		case 0: /* Options */
-			switch (opt) {
-			case 'l': /* List */
-				listing = 1;
-				break;
+		switch (opt) {
+		case 'd':  /* Extract to base directory */
+			base_dir = optarg;
+			break;
 
-			case 'n': /* Never overwrite existing files */
-				overwrite = O_NEVER;
-				break;
+		case 'l': /* List */
+			listing = 1;
+			break;
 
-			case 'o': /* Always overwrite existing files */
-				overwrite = O_ALWAYS;
-				break;
+		case 'n': /* Never overwrite existing files */
+			overwrite = O_NEVER;
+			break;
 
-			case 'p': /* Extract files to stdout and fall through to set verbosity */
-				dst_fd = STDOUT_FILENO;
+		case 'o': /* Always overwrite existing files */
+			overwrite = O_ALWAYS;
+			break;
 
-			case 'q': /* Be quiet */
-				quiet++;
-				break;
+		case 'p': /* Extract files to stdout and fall through to set verbosity */
+			dst_fd = STDOUT_FILENO;
 
-			case 'v': /* Verbose list */
-				IF_DESKTOP(verbose++;)
-				listing = 1;
-				break;
+		case 'q': /* Be quiet */
+			quiet++;
+			break;
 
-			case 1: /* The zip file */
-				/* +5: space for ".zip" and NUL */
-				src_fn = xmalloc(strlen(optarg) + 5);
-				strcpy(src_fn, optarg);
-				opt_range++;
-				break;
+		case 'v': /* Verbose list */
+			IF_DESKTOP(verbose++;)
+			listing = 1;
+			break;
 
-			default:
-				bb_show_usage();
-			}
+		case 'x':
+			x_opt_seen = 1;
 			break;
 
-		case 1: /* Include files */
-			if (opt == 1) {
+		case 1:
+			if (!src_fn) {
+				/* The zip file */
+				/* +5: space for ".zip" and NUL */
+				src_fn = xmalloc(strlen(optarg) + 5);
+				strcpy(src_fn, optarg);
+			} else if (!x_opt_seen) {
+				/* Include files */
 				llist_add_to(&zaccept, optarg);
-				break;
-			}
-			if (opt == 'd') {
-				base_dir = optarg;
-				opt_range += 2;
-				break;
-			}
-			if (opt == 'x') {
-				opt_range++;
-				break;
-			}
-			bb_show_usage();
-
-		case 2 : /* Exclude files */
-			if (opt == 1) {
+			} else {
+				/* Exclude files */
 				llist_add_to(&zreject, optarg);
-				break;
 			}
-			if (opt == 'd') { /* Extract to base directory */
-				base_dir = optarg;
-				opt_range++;
-				break;
-			}
-			/* fall through */
+			break;
 
 		default:
 			bb_show_usage();
 		}
 	}
 
-	if (src_fn == NULL) {
+#ifndef __GLIBC__
+	/*
+	 * This code is needed for non-GNU getopt
+	 * which doesn't understand "-" in option string.
+	 * The -x option won't work properly in this case:
+	 * "unzip a.zip q -x w e" will be interpreted as
+	 * "unzip a.zip q w e -x" = "unzip a.zip q w e"
+	 */
+	argv += optind;
+	if (argv[0]) {
+		/* +5: space for ".zip" and NUL */
+		src_fn = xmalloc(strlen(argv[0]) + 5);
+		strcpy(src_fn, argv[0]);
+		while (*++argv)
+			llist_add_to(&zaccept, *argv);
+	}
+#endif
+
+	if (!src_fn) {
 		bb_show_usage();
 	}
 
@@ -420,17 +420,20 @@ int unzip_main(int argc, char **argv)
 		if (overwrite == O_PROMPT)
 			overwrite = O_NEVER;
 	} else {
-		static const char extn[][5] = {"", ".zip", ".ZIP"};
-		int orig_src_fn_len = strlen(src_fn);
-		int src_fd = -1;
+		static const char extn[][5] = { ".zip", ".ZIP" };
+		char *ext = src_fn + strlen(src_fn);
+		int src_fd;
 
-		for (i = 0; (i < 3) && (src_fd == -1); i++) {
-			strcpy(src_fn + orig_src_fn_len, extn[i]);
+		i = 0;
+		for (;;) {
 			src_fd = open(src_fn, O_RDONLY);
-		}
-		if (src_fd == -1) {
-			src_fn[orig_src_fn_len] = '\0';
-			bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn);
+			if (src_fd >= 0)
+				break;
+			if (++i > 2) {
+				*ext = '\0';
+				bb_error_msg_and_die("can't open %s[.zip]", src_fn);
+			}
+			strcpy(ext, extn[i - 1]);
 		}
 		xmove_fd(src_fd, zip_fd);
 	}


More information about the busybox-cvs mailing list