aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2012-06-15 16:43:26 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2012-06-15 16:43:26 +0200
commitc5b01016e622f01dfa9c8c542c0968fe37d4a5f2 (patch)
treee45679f07399c053c71f0d3a9b08ef74ce38239b
parent604499e5a93d8055a761e968b12d6a0907bc3d0a (diff)
downloadbusybox-w32-c5b01016e622f01dfa9c8c542c0968fe37d4a5f2.tar.gz
busybox-w32-c5b01016e622f01dfa9c8c542c0968fe37d4a5f2.tar.bz2
busybox-w32-c5b01016e622f01dfa9c8c542c0968fe37d4a5f2.zip
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>
-rw-r--r--archival/unzip.c137
1 files changed, 70 insertions, 67 deletions
diff --git a/archival/unzip.c b/archival/unzip.c
index c1b945a44..380674701 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -20,11 +20,11 @@
20 */ 20 */
21 21
22//usage:#define unzip_trivial_usage 22//usage:#define unzip_trivial_usage
23//usage: "[-opts[modifiers]] FILE[.zip] [LIST] [-x XLIST] [-d DIR]" 23//usage: "[-lnopq] FILE[.zip] [LIST] [-x XLIST] [-d DIR]"
24//usage:#define unzip_full_usage "\n\n" 24//usage:#define unzip_full_usage "\n\n"
25//usage: "Extract files from ZIP archives\n" 25//usage: "Extract files from ZIP archives\n"
26//usage: "\n -l List archive contents (with -q for short form)" 26//usage: "\n -l List archive contents (with -q for short form)"
27//usage: "\n -n Never overwrite files (default)" 27//usage: "\n -n Never overwrite files (default: ask)"
28//usage: "\n -o Overwrite" 28//usage: "\n -o Overwrite"
29//usage: "\n -p Send output to stdout" 29//usage: "\n -p Send output to stdout"
30//usage: "\n -q Quiet" 30//usage: "\n -q Quiet"
@@ -277,6 +277,7 @@ int unzip_main(int argc, char **argv)
277 IF_NOT_DESKTOP(const) smallint verbose = 0; 277 IF_NOT_DESKTOP(const) smallint verbose = 0;
278 smallint listing = 0; 278 smallint listing = 0;
279 smallint overwrite = O_PROMPT; 279 smallint overwrite = O_PROMPT;
280 smallint x_opt_seen;
280#if ENABLE_DESKTOP 281#if ENABLE_DESKTOP
281 uint32_t cdf_offset; 282 uint32_t cdf_offset;
282#endif 283#endif
@@ -290,7 +291,6 @@ int unzip_main(int argc, char **argv)
290 llist_t *zreject = NULL; 291 llist_t *zreject = NULL;
291 char *base_dir = NULL; 292 char *base_dir = NULL;
292 int i, opt; 293 int i, opt;
293 int opt_range = 0;
294 char key_buf[80]; 294 char key_buf[80];
295 struct stat stat_buf; 295 struct stat stat_buf;
296 296
@@ -335,81 +335,81 @@ int unzip_main(int argc, char **argv)
335 * 204372 1 file 335 * 204372 1 file
336 */ 336 */
337 337
338 x_opt_seen = 0;
338 /* '-' makes getopt return 1 for non-options */ 339 /* '-' makes getopt return 1 for non-options */
339 while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { 340 while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) {
340 switch (opt_range) { 341 switch (opt) {
341 case 0: /* Options */ 342 case 'd': /* Extract to base directory */
342 switch (opt) { 343 base_dir = optarg;
343 case 'l': /* List */ 344 break;
344 listing = 1;
345 break;
346 345
347 case 'n': /* Never overwrite existing files */ 346 case 'l': /* List */
348 overwrite = O_NEVER; 347 listing = 1;
349 break; 348 break;
350 349
351 case 'o': /* Always overwrite existing files */ 350 case 'n': /* Never overwrite existing files */
352 overwrite = O_ALWAYS; 351 overwrite = O_NEVER;
353 break; 352 break;
354 353
355 case 'p': /* Extract files to stdout and fall through to set verbosity */ 354 case 'o': /* Always overwrite existing files */
356 dst_fd = STDOUT_FILENO; 355 overwrite = O_ALWAYS;
356 break;
357 357
358 case 'q': /* Be quiet */ 358 case 'p': /* Extract files to stdout and fall through to set verbosity */
359 quiet++; 359 dst_fd = STDOUT_FILENO;
360 break;
361 360
362 case 'v': /* Verbose list */ 361 case 'q': /* Be quiet */
363 IF_DESKTOP(verbose++;) 362 quiet++;
364 listing = 1; 363 break;
365 break;
366 364
367 case 1: /* The zip file */ 365 case 'v': /* Verbose list */
368 /* +5: space for ".zip" and NUL */ 366 IF_DESKTOP(verbose++;)
369 src_fn = xmalloc(strlen(optarg) + 5); 367 listing = 1;
370 strcpy(src_fn, optarg); 368 break;
371 opt_range++;
372 break;
373 369
374 default: 370 case 'x':
375 bb_show_usage(); 371 x_opt_seen = 1;
376 }
377 break; 372 break;
378 373
379 case 1: /* Include files */ 374 case 1:
380 if (opt == 1) { 375 if (!src_fn) {
376 /* The zip file */
377 /* +5: space for ".zip" and NUL */
378 src_fn = xmalloc(strlen(optarg) + 5);
379 strcpy(src_fn, optarg);
380 } else if (!x_opt_seen) {
381 /* Include files */
381 llist_add_to(&zaccept, optarg); 382 llist_add_to(&zaccept, optarg);
382 break; 383 } else {
383 } 384 /* Exclude files */
384 if (opt == 'd') {
385 base_dir = optarg;
386 opt_range += 2;
387 break;
388 }
389 if (opt == 'x') {
390 opt_range++;
391 break;
392 }
393 bb_show_usage();
394
395 case 2 : /* Exclude files */
396 if (opt == 1) {
397 llist_add_to(&zreject, optarg); 385 llist_add_to(&zreject, optarg);
398 break;
399 } 386 }
400 if (opt == 'd') { /* Extract to base directory */ 387 break;
401 base_dir = optarg;
402 opt_range++;
403 break;
404 }
405 /* fall through */
406 388
407 default: 389 default:
408 bb_show_usage(); 390 bb_show_usage();
409 } 391 }
410 } 392 }
411 393
412 if (src_fn == NULL) { 394#ifndef __GLIBC__
395 /*
396 * This code is needed for non-GNU getopt
397 * which doesn't understand "-" in option string.
398 * The -x option won't work properly in this case:
399 * "unzip a.zip q -x w e" will be interpreted as
400 * "unzip a.zip q w e -x" = "unzip a.zip q w e"
401 */
402 argv += optind;
403 if (argv[0]) {
404 /* +5: space for ".zip" and NUL */
405 src_fn = xmalloc(strlen(argv[0]) + 5);
406 strcpy(src_fn, argv[0]);
407 while (*++argv)
408 llist_add_to(&zaccept, *argv);
409 }
410#endif
411
412 if (!src_fn) {
413 bb_show_usage(); 413 bb_show_usage();
414 } 414 }
415 415
@@ -420,17 +420,20 @@ int unzip_main(int argc, char **argv)
420 if (overwrite == O_PROMPT) 420 if (overwrite == O_PROMPT)
421 overwrite = O_NEVER; 421 overwrite = O_NEVER;
422 } else { 422 } else {
423 static const char extn[][5] = {"", ".zip", ".ZIP"}; 423 static const char extn[][5] = { ".zip", ".ZIP" };
424 int orig_src_fn_len = strlen(src_fn); 424 char *ext = src_fn + strlen(src_fn);
425 int src_fd = -1; 425 int src_fd;
426 426
427 for (i = 0; (i < 3) && (src_fd == -1); i++) { 427 i = 0;
428 strcpy(src_fn + orig_src_fn_len, extn[i]); 428 for (;;) {
429 src_fd = open(src_fn, O_RDONLY); 429 src_fd = open(src_fn, O_RDONLY);
430 } 430 if (src_fd >= 0)
431 if (src_fd == -1) { 431 break;
432 src_fn[orig_src_fn_len] = '\0'; 432 if (++i > 2) {
433 bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); 433 *ext = '\0';
434 bb_error_msg_and_die("can't open %s[.zip]", src_fn);
435 }
436 strcpy(ext, extn[i - 1]);
434 } 437 }
435 xmove_fd(src_fd, zip_fd); 438 xmove_fd(src_fd, zip_fd);
436 } 439 }