aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-20 20:04:49 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-20 20:04:49 +0200
commit997ad2c64abbe931dffa3598b015c5de04e515cf (patch)
tree808dadf75484b464d6b55e06624ff2007f33ed02
parentbff9bbc73fce9a3886992f413fb18fe78c007cbb (diff)
downloadbusybox-w32-997ad2c64abbe931dffa3598b015c5de04e515cf.tar.gz
busybox-w32-997ad2c64abbe931dffa3598b015c5de04e515cf.tar.bz2
busybox-w32-997ad2c64abbe931dffa3598b015c5de04e515cf.zip
unzip: implement -j, closes 9126
function old new delta unzip_main 2642 2703 +61 packed_usage 31747 31770 +23 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 84/0) Total: 84 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/unzip.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/archival/unzip.c b/archival/unzip.c
index 21ba172b5..d5bca08d4 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -62,6 +62,7 @@
62//usage: "\n -l List contents (with -q for short form)" 62//usage: "\n -l List contents (with -q for short form)"
63//usage: "\n -n Never overwrite files (default: ask)" 63//usage: "\n -n Never overwrite files (default: ask)"
64//usage: "\n -o Overwrite" 64//usage: "\n -o Overwrite"
65//usage: "\n -j Do not restore paths"
65//usage: "\n -p Print to stdout" 66//usage: "\n -p Print to stdout"
66//usage: "\n -q Quiet" 67//usage: "\n -q Quiet"
67//usage: "\n -x FILE Exclude FILEs" 68//usage: "\n -x FILE Exclude FILEs"
@@ -455,13 +456,16 @@ static int get_lstat_mode(const char *dst_fn)
455int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 456int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
456int unzip_main(int argc, char **argv) 457int unzip_main(int argc, char **argv)
457{ 458{
458 enum { O_PROMPT, O_NEVER, O_ALWAYS }; 459 enum {
459 460 OPT_l = (1 << 0),
461 OPT_x = (1 << 1),
462 OPT_j = (1 << 2),
463 };
464 unsigned opts;
460 smallint quiet = 0; 465 smallint quiet = 0;
461 IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0; 466 IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0;
462 smallint listing = 0; 467 enum { O_PROMPT, O_NEVER, O_ALWAYS };
463 smallint overwrite = O_PROMPT; 468 smallint overwrite = O_PROMPT;
464 smallint x_opt_seen;
465 uint32_t cdf_offset; 469 uint32_t cdf_offset;
466 unsigned long total_usize; 470 unsigned long total_usize;
467 unsigned long total_size; 471 unsigned long total_size;
@@ -472,7 +476,7 @@ int unzip_main(int argc, char **argv)
472 llist_t *zaccept = NULL; 476 llist_t *zaccept = NULL;
473 llist_t *zreject = NULL; 477 llist_t *zreject = NULL;
474 char *base_dir = NULL; 478 char *base_dir = NULL;
475 int i, opt; 479 int i;
476 char key_buf[80]; /* must match size used by my_fgets80 */ 480 char key_buf[80]; /* must match size used by my_fgets80 */
477 481
478/* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP: 482/* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP:
@@ -516,16 +520,16 @@ int unzip_main(int argc, char **argv)
516 * 204372 1 file 520 * 204372 1 file
517 */ 521 */
518 522
519 x_opt_seen = 0; 523 opts = 0;
520 /* '-' makes getopt return 1 for non-options */ 524 /* '-' makes getopt return 1 for non-options */
521 while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { 525 while ((i = getopt(argc, argv, "-d:lnopqxjv")) != -1) {
522 switch (opt) { 526 switch (i) {
523 case 'd': /* Extract to base directory */ 527 case 'd': /* Extract to base directory */
524 base_dir = optarg; 528 base_dir = optarg;
525 break; 529 break;
526 530
527 case 'l': /* List */ 531 case 'l': /* List */
528 listing = 1; 532 opts |= OPT_l;
529 break; 533 break;
530 534
531 case 'n': /* Never overwrite existing files */ 535 case 'n': /* Never overwrite existing files */
@@ -545,11 +549,15 @@ int unzip_main(int argc, char **argv)
545 549
546 case 'v': /* Verbose list */ 550 case 'v': /* Verbose list */
547 IF_FEATURE_UNZIP_CDF(verbose++;) 551 IF_FEATURE_UNZIP_CDF(verbose++;)
548 listing = 1; 552 opts |= OPT_l;
549 break; 553 break;
550 554
551 case 'x': 555 case 'x':
552 x_opt_seen = 1; 556 opts |= OPT_x;
557 break;
558
559 case 'j':
560 opts |= OPT_j;
553 break; 561 break;
554 562
555 case 1: 563 case 1:
@@ -558,7 +566,7 @@ int unzip_main(int argc, char **argv)
558 /* +5: space for ".zip" and NUL */ 566 /* +5: space for ".zip" and NUL */
559 src_fn = xmalloc(strlen(optarg) + 5); 567 src_fn = xmalloc(strlen(optarg) + 5);
560 strcpy(src_fn, optarg); 568 strcpy(src_fn, optarg);
561 } else if (!x_opt_seen) { 569 } else if (!(opts & OPT_x)) {
562 /* Include files */ 570 /* Include files */
563 llist_add_to(&zaccept, optarg); 571 llist_add_to(&zaccept, optarg);
564 } else { 572 } else {
@@ -626,7 +634,7 @@ int unzip_main(int argc, char **argv)
626 if (quiet <= 1) { /* not -qq */ 634 if (quiet <= 1) { /* not -qq */
627 if (quiet == 0) 635 if (quiet == 0)
628 printf("Archive: %s\n", src_fn); 636 printf("Archive: %s\n", src_fn);
629 if (listing) { 637 if (opts & OPT_l) {
630 puts(verbose ? 638 puts(verbose ?
631 " Length Method Size Cmpr Date Time CRC-32 Name\n" 639 " Length Method Size Cmpr Date Time CRC-32 Name\n"
632 "-------- ------ ------- ---- ---------- ----- -------- ----" 640 "-------- ------ ------- ---- ---------- ----- -------- ----"
@@ -778,13 +786,19 @@ int unzip_main(int argc, char **argv)
778 free(dst_fn); 786 free(dst_fn);
779 dst_fn = xzalloc(zip.fmt.filename_len + 1); 787 dst_fn = xzalloc(zip.fmt.filename_len + 1);
780 xread(zip_fd, dst_fn, zip.fmt.filename_len); 788 xread(zip_fd, dst_fn, zip.fmt.filename_len);
781
782 /* Skip extra header bytes */ 789 /* Skip extra header bytes */
783 unzip_skip(zip.fmt.extra_len); 790 unzip_skip(zip.fmt.extra_len);
784 791
785 /* Guard against "/abspath", "/../" and similar attacks */ 792 /* Guard against "/abspath", "/../" and similar attacks */
786 overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); 793 overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn));
787 794
795 if (opts & OPT_j) /* Strip paths? */
796 overlapping_strcpy(dst_fn, bb_basename(dst_fn));
797
798 /* Did this strip everything ("DIR/" case)? Then skip */
799 if (!dst_fn[0])
800 goto skip_cmpsize;
801
788 /* Filter zip entries */ 802 /* Filter zip entries */
789 if (find_list_entry(zreject, dst_fn) 803 if (find_list_entry(zreject, dst_fn)
790 || (zaccept && !find_list_entry(zaccept, dst_fn)) 804 || (zaccept && !find_list_entry(zaccept, dst_fn))
@@ -792,7 +806,7 @@ int unzip_main(int argc, char **argv)
792 goto skip_cmpsize; 806 goto skip_cmpsize;
793 } 807 }
794 808
795 if (listing) { 809 if (opts & OPT_l) {
796 /* List entry */ 810 /* List entry */
797 char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; 811 char dtbuf[sizeof("mm-dd-yyyy hh:mm")];
798 sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", 812 sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u",
@@ -960,7 +974,7 @@ int unzip_main(int argc, char **argv)
960 total_entries++; 974 total_entries++;
961 } 975 }
962 976
963 if (listing && quiet <= 1) { 977 if ((opts & OPT_l) && quiet <= 1) {
964 if (!verbose) { 978 if (!verbose) {
965 // " Length Date Time Name\n" 979 // " Length Date Time Name\n"
966 // "--------- ---------- ----- ----" 980 // "--------- ---------- ----- ----"