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:#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:#define unzip_full_usage "\n\n" | ||||||
| //usage:       "Extract files from ZIP archives\n" | //usage:       "Extract files from ZIP archives\n" | ||||||
| //usage:     "\n	-l	List archive contents (with -q for short form)" | //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	-o	Overwrite" | ||||||
| //usage:     "\n	-p	Send output to stdout" | //usage:     "\n	-p	Send output to stdout" | ||||||
| //usage:     "\n	-q	Quiet" | //usage:     "\n	-q	Quiet" | ||||||
| @@ -277,6 +277,7 @@ int unzip_main(int argc, char **argv) | |||||||
| 	IF_NOT_DESKTOP(const) smallint verbose = 0; | 	IF_NOT_DESKTOP(const) smallint verbose = 0; | ||||||
| 	smallint listing = 0; | 	smallint listing = 0; | ||||||
| 	smallint overwrite = O_PROMPT; | 	smallint overwrite = O_PROMPT; | ||||||
|  | 	smallint x_opt_seen; | ||||||
| #if ENABLE_DESKTOP | #if ENABLE_DESKTOP | ||||||
| 	uint32_t cdf_offset; | 	uint32_t cdf_offset; | ||||||
| #endif | #endif | ||||||
| @@ -290,7 +291,6 @@ int unzip_main(int argc, char **argv) | |||||||
| 	llist_t *zreject = NULL; | 	llist_t *zreject = NULL; | ||||||
| 	char *base_dir = NULL; | 	char *base_dir = NULL; | ||||||
| 	int i, opt; | 	int i, opt; | ||||||
| 	int opt_range = 0; |  | ||||||
| 	char key_buf[80]; | 	char key_buf[80]; | ||||||
| 	struct stat stat_buf; | 	struct stat stat_buf; | ||||||
|  |  | ||||||
| @@ -335,11 +335,14 @@ int unzip_main(int argc, char **argv) | |||||||
|  *    204372                   1 file |  *    204372                   1 file | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | 	x_opt_seen = 0; | ||||||
| 	/* '-' makes getopt return 1 for non-options */ | 	/* '-' makes getopt return 1 for non-options */ | ||||||
| 	while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { | 	while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { | ||||||
| 		switch (opt_range) { |  | ||||||
| 		case 0: /* Options */ |  | ||||||
| 		switch (opt) { | 		switch (opt) { | ||||||
|  | 		case 'd':  /* Extract to base directory */ | ||||||
|  | 			base_dir = optarg; | ||||||
|  | 			break; | ||||||
|  |  | ||||||
| 		case 'l': /* List */ | 		case 'l': /* List */ | ||||||
| 			listing = 1; | 			listing = 1; | ||||||
| 			break; | 			break; | ||||||
| @@ -364,52 +367,49 @@ int unzip_main(int argc, char **argv) | |||||||
| 			listing = 1; | 			listing = 1; | ||||||
| 			break; | 			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 */ | 				/* +5: space for ".zip" and NUL */ | ||||||
| 				src_fn = xmalloc(strlen(optarg) + 5); | 				src_fn = xmalloc(strlen(optarg) + 5); | ||||||
| 				strcpy(src_fn, optarg); | 				strcpy(src_fn, optarg); | ||||||
| 				opt_range++; | 			} else if (!x_opt_seen) { | ||||||
| 				break; | 				/* Include files */ | ||||||
|  |  | ||||||
| 			default: |  | ||||||
| 				bb_show_usage(); |  | ||||||
| 			} |  | ||||||
| 			break; |  | ||||||
|  |  | ||||||
| 		case 1: /* Include files */ |  | ||||||
| 			if (opt == 1) { |  | ||||||
| 				llist_add_to(&zaccept, optarg); | 				llist_add_to(&zaccept, optarg); | ||||||
| 				break; | 			} else { | ||||||
| 			} | 				/* Exclude files */ | ||||||
| 			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) { |  | ||||||
| 				llist_add_to(&zreject, optarg); | 				llist_add_to(&zreject, optarg); | ||||||
| 				break; |  | ||||||
| 			} | 			} | ||||||
| 			if (opt == 'd') { /* Extract to base directory */ |  | ||||||
| 				base_dir = optarg; |  | ||||||
| 				opt_range++; |  | ||||||
| 			break; | 			break; | ||||||
| 			} |  | ||||||
| 			/* fall through */ |  | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			bb_show_usage(); | 			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(); | 		bb_show_usage(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -420,17 +420,20 @@ int unzip_main(int argc, char **argv) | |||||||
| 		if (overwrite == O_PROMPT) | 		if (overwrite == O_PROMPT) | ||||||
| 			overwrite = O_NEVER; | 			overwrite = O_NEVER; | ||||||
| 	} else { | 	} else { | ||||||
| 		static const char extn[][5] = {"", ".zip", ".ZIP"}; | 		static const char extn[][5] = { ".zip", ".ZIP" }; | ||||||
| 		int orig_src_fn_len = strlen(src_fn); | 		char *ext = src_fn + strlen(src_fn); | ||||||
| 		int src_fd = -1; | 		int src_fd; | ||||||
|  |  | ||||||
| 		for (i = 0; (i < 3) && (src_fd == -1); i++) { | 		i = 0; | ||||||
| 			strcpy(src_fn + orig_src_fn_len, extn[i]); | 		for (;;) { | ||||||
| 			src_fd = open(src_fn, O_RDONLY); | 			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) { | 			strcpy(ext, extn[i - 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); |  | ||||||
| 		} | 		} | ||||||
| 		xmove_fd(src_fd, zip_fd); | 		xmove_fd(src_fd, zip_fd); | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user