unzip: make options parsing more robust on getopt w/o gnu extensions
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@googlemail.com>
This commit is contained in:
		| @@ -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,11 +335,14 @@ 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 'd':  /* Extract to base directory */ | ||||
| 			base_dir = optarg; | ||||
| 			break; | ||||
|  | ||||
| 		case 'l': /* List */ | ||||
| 			listing = 1; | ||||
| 			break; | ||||
| @@ -364,52 +367,49 @@ int unzip_main(int argc, char **argv) | ||||
| 			listing = 1; | ||||
| 			break; | ||||
|  | ||||
| 			case 1: /* The zip file */ | ||||
| 		case 'x': | ||||
| 			x_opt_seen = 1; | ||||
| 			break; | ||||
|  | ||||
| 		case 1: | ||||
| 			if (!src_fn) { | ||||
| 				/* The zip file */ | ||||
| 				/* +5: space for ".zip" and NUL */ | ||||
| 				src_fn = xmalloc(strlen(optarg) + 5); | ||||
| 				strcpy(src_fn, optarg); | ||||
| 				opt_range++; | ||||
| 				break; | ||||
|  | ||||
| 			default: | ||||
| 				bb_show_usage(); | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 		case 1: /* Include files */ | ||||
| 			if (opt == 1) { | ||||
| 			} 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 */ | ||||
|  | ||||
| 		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 >= 0) | ||||
| 				break; | ||||
| 			if (++i > 2) { | ||||
| 				*ext = '\0'; | ||||
| 				bb_error_msg_and_die("can't open %s[.zip]", src_fn); | ||||
| 			} | ||||
| 		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); | ||||
| 			strcpy(ext, extn[i - 1]); | ||||
| 		} | ||||
| 		xmove_fd(src_fd, zip_fd); | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user