diff options
Diffstat (limited to 'archival')
-rw-r--r-- | archival/Config.src | 10 | ||||
-rw-r--r-- | archival/ar.c | 2 | ||||
-rw-r--r-- | archival/bbunzip.c | 76 | ||||
-rw-r--r-- | archival/bzip2.c | 16 | ||||
-rw-r--r-- | archival/cpio.c | 4 | ||||
-rw-r--r-- | archival/gzip.c | 28 | ||||
-rw-r--r-- | archival/libarchive/Kbuild.src | 3 | ||||
-rw-r--r-- | archival/libarchive/data_extract_all.c | 6 | ||||
-rw-r--r-- | archival/libarchive/decompress_bunzip2.c | 6 | ||||
-rw-r--r-- | archival/libarchive/decompress_unlzma.c | 31 | ||||
-rw-r--r-- | archival/lzop.c | 3 | ||||
-rw-r--r-- | archival/tar.c | 35 | ||||
-rw-r--r-- | archival/unzip.c | 489 |
13 files changed, 394 insertions, 315 deletions
diff --git a/archival/Config.src b/archival/Config.src index 5e7cfc0a4..0c97f3d7c 100644 --- a/archival/Config.src +++ b/archival/Config.src | |||
@@ -8,32 +8,22 @@ menu "Archival Utilities" | |||
8 | config FEATURE_SEAMLESS_XZ | 8 | config FEATURE_SEAMLESS_XZ |
9 | bool "Make tar, rpm, modprobe etc understand .xz data" | 9 | bool "Make tar, rpm, modprobe etc understand .xz data" |
10 | default y | 10 | default y |
11 | help | ||
12 | Make tar, rpm, modprobe etc understand .xz data. | ||
13 | 11 | ||
14 | config FEATURE_SEAMLESS_LZMA | 12 | config FEATURE_SEAMLESS_LZMA |
15 | bool "Make tar, rpm, modprobe etc understand .lzma data" | 13 | bool "Make tar, rpm, modprobe etc understand .lzma data" |
16 | default y | 14 | default y |
17 | help | ||
18 | Make tar, rpm, modprobe etc understand .lzma data. | ||
19 | 15 | ||
20 | config FEATURE_SEAMLESS_BZ2 | 16 | config FEATURE_SEAMLESS_BZ2 |
21 | bool "Make tar, rpm, modprobe etc understand .bz2 data" | 17 | bool "Make tar, rpm, modprobe etc understand .bz2 data" |
22 | default y | 18 | default y |
23 | help | ||
24 | Make tar, rpm, modprobe etc understand .bz2 data. | ||
25 | 19 | ||
26 | config FEATURE_SEAMLESS_GZ | 20 | config FEATURE_SEAMLESS_GZ |
27 | bool "Make tar, rpm, modprobe etc understand .gz data" | 21 | bool "Make tar, rpm, modprobe etc understand .gz data" |
28 | default y | 22 | default y |
29 | help | ||
30 | Make tar, rpm, modprobe etc understand .gz data. | ||
31 | 23 | ||
32 | config FEATURE_SEAMLESS_Z | 24 | config FEATURE_SEAMLESS_Z |
33 | bool "Make tar, rpm, modprobe etc understand .Z data" | 25 | bool "Make tar, rpm, modprobe etc understand .Z data" |
34 | default n # it is ancient | 26 | default n # it is ancient |
35 | help | ||
36 | Make tar, rpm, modprobe etc understand .Z data. | ||
37 | 27 | ||
38 | INSERT | 28 | INSERT |
39 | 29 | ||
diff --git a/archival/ar.c b/archival/ar.c index a850868f6..f9f712fde 100644 --- a/archival/ar.c +++ b/archival/ar.c | |||
@@ -31,7 +31,7 @@ | |||
31 | //config: probably say N here: most compilers come with their own ar utility. | 31 | //config: probably say N here: most compilers come with their own ar utility. |
32 | //config: | 32 | //config: |
33 | //config:config FEATURE_AR_LONG_FILENAMES | 33 | //config:config FEATURE_AR_LONG_FILENAMES |
34 | //config: bool "Support for long filenames (not needed for debs)" | 34 | //config: bool "Support long filenames (not needed for debs)" |
35 | //config: default y | 35 | //config: default y |
36 | //config: depends on AR | 36 | //config: depends on AR |
37 | //config: help | 37 | //config: help |
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 343aec9bd..311c7333e 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -12,9 +12,9 @@ | |||
12 | //kbuild:lib-$(CONFIG_LZOPCAT) += bbunzip.o | 12 | //kbuild:lib-$(CONFIG_LZOPCAT) += bbunzip.o |
13 | //kbuild:lib-$(CONFIG_UNLZOP) += bbunzip.o | 13 | //kbuild:lib-$(CONFIG_UNLZOP) += bbunzip.o |
14 | /* bzip2_main() too: */ | 14 | /* bzip2_main() too: */ |
15 | //kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o | 15 | //kbuild:lib-$(CONFIG_FEATURE_BZIP2_DECOMPRESS) += bbunzip.o |
16 | /* gzip_main() too: */ | 16 | /* gzip_main() too: */ |
17 | //kbuild:lib-$(CONFIG_GZIP) += bbunzip.o | 17 | //kbuild:lib-$(CONFIG_FEATURE_GZIP_DECOMPRESS) += bbunzip.o |
18 | 18 | ||
19 | /* Note: must be kept in sync with archival/lzop.c */ | 19 | /* Note: must be kept in sync with archival/lzop.c */ |
20 | enum { | 20 | enum { |
@@ -25,7 +25,7 @@ enum { | |||
25 | OPT_QUIET = 1 << 3, | 25 | OPT_QUIET = 1 << 3, |
26 | OPT_DECOMPRESS = 1 << 4, | 26 | OPT_DECOMPRESS = 1 << 4, |
27 | OPT_TEST = 1 << 5, | 27 | OPT_TEST = 1 << 5, |
28 | SEAMLESS_MAGIC = (1 << 31) * SEAMLESS_COMPRESSION, | 28 | SEAMLESS_MAGIC = (1 << 31) * ENABLE_ZCAT * SEAMLESS_COMPRESSION, |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static | 31 | static |
@@ -127,7 +127,7 @@ int FAST_FUNC bbunpack(char **argv, | |||
127 | 127 | ||
128 | if (!(option_mask32 & SEAMLESS_MAGIC)) { | 128 | if (!(option_mask32 & SEAMLESS_MAGIC)) { |
129 | init_transformer_state(&xstate); | 129 | init_transformer_state(&xstate); |
130 | xstate.signature_skipped = 0; | 130 | /*xstate.signature_skipped = 0; - already is */ |
131 | /*xstate.src_fd = STDIN_FILENO; - already is */ | 131 | /*xstate.src_fd = STDIN_FILENO; - already is */ |
132 | xstate.dst_fd = STDOUT_FILENO; | 132 | xstate.dst_fd = STDOUT_FILENO; |
133 | status = unpacker(&xstate); | 133 | status = unpacker(&xstate); |
@@ -199,7 +199,7 @@ int FAST_FUNC bbunpack(char **argv, | |||
199 | } | 199 | } |
200 | 200 | ||
201 | #if ENABLE_UNCOMPRESS \ | 201 | #if ENABLE_UNCOMPRESS \ |
202 | || ENABLE_BUNZIP2 || ENABLE_BZCAT \ | 202 | || ENABLE_FEATURE_BZIP2_DECOMPRESS \ |
203 | || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \ | 203 | || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \ |
204 | || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ | 204 | || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ |
205 | static | 205 | static |
@@ -297,6 +297,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) | |||
297 | //config:config GUNZIP | 297 | //config:config GUNZIP |
298 | //config: bool "gunzip" | 298 | //config: bool "gunzip" |
299 | //config: default y | 299 | //config: default y |
300 | //config: select FEATURE_GZIP_DECOMPRESS | ||
300 | //config: help | 301 | //config: help |
301 | //config: gunzip is used to decompress archives created by gzip. | 302 | //config: gunzip is used to decompress archives created by gzip. |
302 | //config: You can use the `-t' option to test the integrity of | 303 | //config: You can use the `-t' option to test the integrity of |
@@ -305,6 +306,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) | |||
305 | //config:config ZCAT | 306 | //config:config ZCAT |
306 | //config: bool "zcat" | 307 | //config: bool "zcat" |
307 | //config: default y | 308 | //config: default y |
309 | //config: select FEATURE_GZIP_DECOMPRESS | ||
308 | //config: help | 310 | //config: help |
309 | //config: Alias to "gunzip -c". | 311 | //config: Alias to "gunzip -c". |
310 | //config: | 312 | //config: |
@@ -312,14 +314,11 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) | |||
312 | //config: bool "Enable long options" | 314 | //config: bool "Enable long options" |
313 | //config: default y | 315 | //config: default y |
314 | //config: depends on (GUNZIP || ZCAT) && LONG_OPTS | 316 | //config: depends on (GUNZIP || ZCAT) && LONG_OPTS |
315 | //config: help | ||
316 | //config: Enable use of long options. | ||
317 | 317 | ||
318 | //applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) | 318 | //applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) |
319 | // APPLET_ODDNAME:name main location suid_type help | ||
319 | //applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) | 320 | //applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) |
320 | //kbuild:lib-$(CONFIG_GUNZIP) += bbunzip.o | 321 | #if ENABLE_FEATURE_GZIP_DECOMPRESS |
321 | //kbuild:lib-$(CONFIG_ZCAT) += bbunzip.o | ||
322 | #if ENABLE_GUNZIP || ENABLE_ZCAT | ||
323 | static | 322 | static |
324 | char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM) | 323 | char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM) |
325 | { | 324 | { |
@@ -387,7 +386,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
387 | 386 | ||
388 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); | 387 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); |
389 | } | 388 | } |
390 | #endif | 389 | #endif /* FEATURE_GZIP_DECOMPRESS */ |
391 | 390 | ||
392 | 391 | ||
393 | /* | 392 | /* |
@@ -410,6 +409,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
410 | //config:config BUNZIP2 | 409 | //config:config BUNZIP2 |
411 | //config: bool "bunzip2" | 410 | //config: bool "bunzip2" |
412 | //config: default y | 411 | //config: default y |
412 | //config: select FEATURE_BZIP2_DECOMPRESS | ||
413 | //config: help | 413 | //config: help |
414 | //config: bunzip2 is a compression utility using the Burrows-Wheeler block | 414 | //config: bunzip2 is a compression utility using the Burrows-Wheeler block |
415 | //config: sorting text compression algorithm, and Huffman coding. Compression | 415 | //config: sorting text compression algorithm, and Huffman coding. Compression |
@@ -423,14 +423,14 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
423 | //config:config BZCAT | 423 | //config:config BZCAT |
424 | //config: bool "bzcat" | 424 | //config: bool "bzcat" |
425 | //config: default y | 425 | //config: default y |
426 | //config: select FEATURE_BZIP2_DECOMPRESS | ||
426 | //config: help | 427 | //config: help |
427 | //config: Alias to "bunzip2 -c". | 428 | //config: Alias to "bunzip2 -c". |
428 | 429 | ||
429 | //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) | 430 | //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) |
431 | // APPLET_ODDNAME:name main location suid_type help | ||
430 | //applet:IF_BZCAT(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat)) | 432 | //applet:IF_BZCAT(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat)) |
431 | //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o | 433 | #if ENABLE_FEATURE_BZIP2_DECOMPRESS |
432 | //kbuild:lib-$(CONFIG_BZCAT) += bbunzip.o | ||
433 | #if ENABLE_BUNZIP2 || ENABLE_BZCAT | ||
434 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 434 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
435 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) | 435 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) |
436 | { | 436 | { |
@@ -471,26 +471,6 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
471 | //usage: "[FILE]..." | 471 | //usage: "[FILE]..." |
472 | //usage:#define lzcat_full_usage "\n\n" | 472 | //usage:#define lzcat_full_usage "\n\n" |
473 | //usage: "Decompress to stdout" | 473 | //usage: "Decompress to stdout" |
474 | //usage: | ||
475 | //usage:#define unxz_trivial_usage | ||
476 | //usage: "[-cf] [FILE]..." | ||
477 | //usage:#define unxz_full_usage "\n\n" | ||
478 | //usage: "Decompress FILE (or stdin)\n" | ||
479 | //usage: "\n -c Write to stdout" | ||
480 | //usage: "\n -f Force" | ||
481 | //usage: | ||
482 | //usage:#define xz_trivial_usage | ||
483 | //usage: "-d [-cf] [FILE]..." | ||
484 | //usage:#define xz_full_usage "\n\n" | ||
485 | //usage: "Decompress FILE (or stdin)\n" | ||
486 | //usage: "\n -d Decompress" | ||
487 | //usage: "\n -c Write to stdout" | ||
488 | //usage: "\n -f Force" | ||
489 | //usage: | ||
490 | //usage:#define xzcat_trivial_usage | ||
491 | //usage: "[FILE]..." | ||
492 | //usage:#define xzcat_full_usage "\n\n" | ||
493 | //usage: "Decompress to stdout" | ||
494 | 474 | ||
495 | //config:config UNLZMA | 475 | //config:config UNLZMA |
496 | //config: bool "unlzma" | 476 | //config: bool "unlzma" |
@@ -524,7 +504,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
524 | //config: IOW: you'll get lzma applet, but it will always require -d option. | 504 | //config: IOW: you'll get lzma applet, but it will always require -d option. |
525 | //config: | 505 | //config: |
526 | //config:config FEATURE_LZMA_FAST | 506 | //config:config FEATURE_LZMA_FAST |
527 | //config: bool "Optimize unlzma for speed" | 507 | //config: bool "Optimize for speed" |
528 | //config: default n | 508 | //config: default n |
529 | //config: depends on UNLZMA || LZCAT || LZMA | 509 | //config: depends on UNLZMA || LZCAT || LZMA |
530 | //config: help | 510 | //config: help |
@@ -532,8 +512,9 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
532 | //config: a 1K bigger binary. | 512 | //config: a 1K bigger binary. |
533 | 513 | ||
534 | //applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP)) | 514 | //applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP)) |
515 | // APPLET_ODDNAME:name main location suid_type help | ||
535 | //applet:IF_LZCAT(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat)) | 516 | //applet:IF_LZCAT(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat)) |
536 | //applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) | 517 | //applet:IF_LZMA( APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) |
537 | //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o | 518 | //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o |
538 | //kbuild:lib-$(CONFIG_LZCAT) += bbunzip.o | 519 | //kbuild:lib-$(CONFIG_LZCAT) += bbunzip.o |
539 | //kbuild:lib-$(CONFIG_LZMA) += bbunzip.o | 520 | //kbuild:lib-$(CONFIG_LZMA) += bbunzip.o |
@@ -557,6 +538,26 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
557 | #endif | 538 | #endif |
558 | 539 | ||
559 | 540 | ||
541 | //usage:#define unxz_trivial_usage | ||
542 | //usage: "[-cf] [FILE]..." | ||
543 | //usage:#define unxz_full_usage "\n\n" | ||
544 | //usage: "Decompress FILE (or stdin)\n" | ||
545 | //usage: "\n -c Write to stdout" | ||
546 | //usage: "\n -f Force" | ||
547 | //usage: | ||
548 | //usage:#define xz_trivial_usage | ||
549 | //usage: "-d [-cf] [FILE]..." | ||
550 | //usage:#define xz_full_usage "\n\n" | ||
551 | //usage: "Decompress FILE (or stdin)\n" | ||
552 | //usage: "\n -d Decompress" | ||
553 | //usage: "\n -c Write to stdout" | ||
554 | //usage: "\n -f Force" | ||
555 | //usage: | ||
556 | //usage:#define xzcat_trivial_usage | ||
557 | //usage: "[FILE]..." | ||
558 | //usage:#define xzcat_full_usage "\n\n" | ||
559 | //usage: "Decompress to stdout" | ||
560 | |||
560 | //config:config UNXZ | 561 | //config:config UNXZ |
561 | //config: bool "unxz" | 562 | //config: bool "unxz" |
562 | //config: default y | 563 | //config: default y |
@@ -577,8 +578,9 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
577 | //config: IOW: you'll get xz applet, but it will always require -d option. | 578 | //config: IOW: you'll get xz applet, but it will always require -d option. |
578 | 579 | ||
579 | //applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP)) | 580 | //applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP)) |
581 | // APPLET_ODDNAME:name main location suid_type help | ||
580 | //applet:IF_XZCAT(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat)) | 582 | //applet:IF_XZCAT(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat)) |
581 | //applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) | 583 | //applet:IF_XZ( APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) |
582 | //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o | 584 | //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o |
583 | //kbuild:lib-$(CONFIG_XZCAT) += bbunzip.o | 585 | //kbuild:lib-$(CONFIG_XZCAT) += bbunzip.o |
584 | //kbuild:lib-$(CONFIG_XZ) += bbunzip.o | 586 | //kbuild:lib-$(CONFIG_XZ) += bbunzip.o |
diff --git a/archival/bzip2.c b/archival/bzip2.c index 47fa29af3..7e38e78b3 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c | |||
@@ -19,6 +19,15 @@ | |||
19 | //config: | 19 | //config: |
20 | //config: Unless you have a specific application which requires bzip2, you | 20 | //config: Unless you have a specific application which requires bzip2, you |
21 | //config: should probably say N here. | 21 | //config: should probably say N here. |
22 | //config: | ||
23 | //config:config FEATURE_BZIP2_DECOMPRESS | ||
24 | //config: bool "Enable decompression" | ||
25 | //config: default y | ||
26 | //config: depends on BZIP2 || BUNZIP2 || BZCAT | ||
27 | //config: help | ||
28 | //config: Enable -d (--decompress) and -t (--test) options for bzip2. | ||
29 | //config: This will be automatically selected if bunzip2 or bzcat is | ||
30 | //config: enabled. | ||
22 | 31 | ||
23 | //applet:IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) | 32 | //applet:IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) |
24 | //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o | 33 | //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o |
@@ -28,7 +37,10 @@ | |||
28 | //usage:#define bzip2_full_usage "\n\n" | 37 | //usage:#define bzip2_full_usage "\n\n" |
29 | //usage: "Compress FILEs (or stdin) with bzip2 algorithm\n" | 38 | //usage: "Compress FILEs (or stdin) with bzip2 algorithm\n" |
30 | //usage: "\n -1..9 Compression level" | 39 | //usage: "\n -1..9 Compression level" |
40 | //usage: IF_FEATURE_BZIP2_DECOMPRESS( | ||
31 | //usage: "\n -d Decompress" | 41 | //usage: "\n -d Decompress" |
42 | //usage: "\n -t Test file integrity" | ||
43 | //usage: ) | ||
32 | //usage: "\n -c Write to stdout" | 44 | //usage: "\n -c Write to stdout" |
33 | //usage: "\n -f Force" | 45 | //usage: "\n -f Force" |
34 | 46 | ||
@@ -184,8 +196,8 @@ int bzip2_main(int argc UNUSED_PARAM, char **argv) | |||
184 | 196 | ||
185 | opt_complementary = "s2"; /* -s means -2 (compatibility) */ | 197 | opt_complementary = "s2"; /* -s means -2 (compatibility) */ |
186 | /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ | 198 | /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ |
187 | opt = getopt32(argv, "cfv" IF_BUNZIP2("dt") "123456789qzs"); | 199 | opt = getopt32(argv, "cfv" IF_FEATURE_BZIP2_DECOMPRESS("dt") "123456789qzs"); |
188 | #if ENABLE_BUNZIP2 /* bunzip2_main may not be visible... */ | 200 | #if ENABLE_FEATURE_BZIP2_DECOMPRESS /* bunzip2_main may not be visible... */ |
189 | if (opt & 0x18) // -d and/or -t | 201 | if (opt & 0x18) // -d and/or -t |
190 | return bunzip2_main(argc, argv); | 202 | return bunzip2_main(argc, argv); |
191 | opt >>= 5; | 203 | opt >>= 5; |
diff --git a/archival/cpio.c b/archival/cpio.c index 540218cb2..683f0bb1f 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -29,7 +29,7 @@ | |||
29 | //config: should probably say N here. | 29 | //config: should probably say N here. |
30 | //config: | 30 | //config: |
31 | //config:config FEATURE_CPIO_O | 31 | //config:config FEATURE_CPIO_O |
32 | //config: bool "Support for archive creation" | 32 | //config: bool "Support archive creation" |
33 | //config: default y | 33 | //config: default y |
34 | //config: depends on CPIO | 34 | //config: depends on CPIO |
35 | //config: help | 35 | //config: help |
@@ -37,7 +37,7 @@ | |||
37 | //config: format only. | 37 | //config: format only. |
38 | //config: | 38 | //config: |
39 | //config:config FEATURE_CPIO_P | 39 | //config:config FEATURE_CPIO_P |
40 | //config: bool "Support for passthrough mode" | 40 | //config: bool "Support passthrough mode" |
41 | //config: default y | 41 | //config: default y |
42 | //config: depends on FEATURE_CPIO_O | 42 | //config: depends on FEATURE_CPIO_O |
43 | //config: help | 43 | //config: help |
diff --git a/archival/gzip.c b/archival/gzip.c index 9e0bee815..e698c26cd 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -48,11 +48,9 @@ aa: 85.1% -- replaced with aa.gz | |||
48 | //config: bool "Enable long options" | 48 | //config: bool "Enable long options" |
49 | //config: default y | 49 | //config: default y |
50 | //config: depends on GZIP && LONG_OPTS | 50 | //config: depends on GZIP && LONG_OPTS |
51 | //config: help | ||
52 | //config: Enable use of long options, increases size by about 106 Bytes | ||
53 | //config: | 51 | //config: |
54 | //config:config GZIP_FAST | 52 | //config:config GZIP_FAST |
55 | //config: int "Trade memory for gzip speed (0:small,slow - 2:fast,big)" | 53 | //config: int "Trade memory for speed (0:small,slow - 2:fast,big)" |
56 | //config: default 0 | 54 | //config: default 0 |
57 | //config: range 0 2 | 55 | //config: range 0 2 |
58 | //config: depends on GZIP | 56 | //config: depends on GZIP |
@@ -72,19 +70,29 @@ aa: 85.1% -- replaced with aa.gz | |||
72 | //config: is 6. If levels 1-3 are specified, 4 is used. | 70 | //config: is 6. If levels 1-3 are specified, 4 is used. |
73 | //config: If this option is not selected, -N options are ignored and -9 | 71 | //config: If this option is not selected, -N options are ignored and -9 |
74 | //config: is used. | 72 | //config: is used. |
73 | //config: | ||
74 | //config:config FEATURE_GZIP_DECOMPRESS | ||
75 | //config: bool "Enable decompression" | ||
76 | //config: default y | ||
77 | //config: depends on GZIP || GUNZIP || ZCAT | ||
78 | //config: help | ||
79 | //config: Enable -d (--decompress) and -t (--test) options for gzip. | ||
80 | //config: This will be automatically selected if gunzip or zcat is | ||
81 | //config: enabled. | ||
75 | 82 | ||
76 | //applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP)) | 83 | //applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP)) |
77 | //kbuild:lib-$(CONFIG_GZIP) += gzip.o | 84 | //kbuild:lib-$(CONFIG_GZIP) += gzip.o |
78 | 85 | ||
79 | //usage:#define gzip_trivial_usage | 86 | //usage:#define gzip_trivial_usage |
80 | //usage: "[-cf" IF_GUNZIP("d") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." | 87 | //usage: "[-cf" IF_FEATURE_GZIP_DECOMPRESS("dt") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." |
81 | //usage:#define gzip_full_usage "\n\n" | 88 | //usage:#define gzip_full_usage "\n\n" |
82 | //usage: "Compress FILEs (or stdin)\n" | 89 | //usage: "Compress FILEs (or stdin)\n" |
83 | //usage: IF_FEATURE_GZIP_LEVELS( | 90 | //usage: IF_FEATURE_GZIP_LEVELS( |
84 | //usage: "\n -1..9 Compression level" | 91 | //usage: "\n -1..9 Compression level" |
85 | //usage: ) | 92 | //usage: ) |
86 | //usage: IF_GUNZIP( | 93 | //usage: IF_FEATURE_GZIP_DECOMPRESS( |
87 | //usage: "\n -d Decompress" | 94 | //usage: "\n -d Decompress" |
95 | //usage: "\n -t Test file integrity" | ||
88 | //usage: ) | 96 | //usage: ) |
89 | //usage: "\n -c Write to stdout" | 97 | //usage: "\n -c Write to stdout" |
90 | //usage: "\n -f Force" | 98 | //usage: "\n -f Force" |
@@ -2154,7 +2162,7 @@ static const char gzip_longopts[] ALIGN1 = | |||
2154 | "to-stdout\0" No_argument "c" | 2162 | "to-stdout\0" No_argument "c" |
2155 | "force\0" No_argument "f" | 2163 | "force\0" No_argument "f" |
2156 | "verbose\0" No_argument "v" | 2164 | "verbose\0" No_argument "v" |
2157 | #if ENABLE_GUNZIP | 2165 | #if ENABLE_FEATURE_GZIP_DECOMPRESS |
2158 | "decompress\0" No_argument "d" | 2166 | "decompress\0" No_argument "d" |
2159 | "uncompress\0" No_argument "d" | 2167 | "uncompress\0" No_argument "d" |
2160 | "test\0" No_argument "t" | 2168 | "test\0" No_argument "t" |
@@ -2181,7 +2189,7 @@ static const char gzip_longopts[] ALIGN1 = | |||
2181 | */ | 2189 | */ |
2182 | 2190 | ||
2183 | int gzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 2191 | int gzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
2184 | #if ENABLE_GUNZIP | 2192 | #if ENABLE_FEATURE_GZIP_DECOMPRESS |
2185 | int gzip_main(int argc, char **argv) | 2193 | int gzip_main(int argc, char **argv) |
2186 | #else | 2194 | #else |
2187 | int gzip_main(int argc UNUSED_PARAM, char **argv) | 2195 | int gzip_main(int argc UNUSED_PARAM, char **argv) |
@@ -2211,13 +2219,13 @@ int gzip_main(int argc UNUSED_PARAM, char **argv) | |||
2211 | applet_long_options = gzip_longopts; | 2219 | applet_long_options = gzip_longopts; |
2212 | #endif | 2220 | #endif |
2213 | /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ | 2221 | /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ |
2214 | opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "qn123456789"); | 2222 | opt = getopt32(argv, "cfv" IF_FEATURE_GZIP_DECOMPRESS("dt") "qn123456789"); |
2215 | #if ENABLE_GUNZIP /* gunzip_main may not be visible... */ | 2223 | #if ENABLE_FEATURE_GZIP_DECOMPRESS /* gunzip_main may not be visible... */ |
2216 | if (opt & 0x18) // -d and/or -t | 2224 | if (opt & 0x18) // -d and/or -t |
2217 | return gunzip_main(argc, argv); | 2225 | return gunzip_main(argc, argv); |
2218 | #endif | 2226 | #endif |
2219 | #ifdef ENABLE_FEATURE_GZIP_LEVELS | 2227 | #ifdef ENABLE_FEATURE_GZIP_LEVELS |
2220 | opt >>= ENABLE_GUNZIP ? 7 : 5; /* drop cfv[dt]qn bits */ | 2228 | opt >>= ENABLE_FEATURE_GZIP_DECOMPRESS ? 7 : 5; /* drop cfv[dt]qn bits */ |
2221 | if (opt == 0) | 2229 | if (opt == 0) |
2222 | opt = 1 << 6; /* default: 6 */ | 2230 | opt = 1 << 6; /* default: 6 */ |
2223 | opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */ | 2231 | opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */ |
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index ad5c5c42d..eaf67451f 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src | |||
@@ -53,12 +53,15 @@ lib-$(CONFIG_LZOPCAT) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o | |||
53 | lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o | 53 | lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o |
54 | lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o | 54 | lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o |
55 | lib-$(CONFIG_BZCAT) += open_transformer.o decompress_bunzip2.o | 55 | lib-$(CONFIG_BZCAT) += open_transformer.o decompress_bunzip2.o |
56 | lib-$(CONFIG_FEATURE_UNZIP_BZIP2) += open_transformer.o decompress_bunzip2.o | ||
56 | lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o | 57 | lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o |
57 | lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o | 58 | lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o |
58 | lib-$(CONFIG_LZMA) += open_transformer.o decompress_unlzma.o | 59 | lib-$(CONFIG_LZMA) += open_transformer.o decompress_unlzma.o |
60 | lib-$(CONFIG_FEATURE_UNZIP_LZMA) += open_transformer.o decompress_unlzma.o | ||
59 | lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o | 61 | lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o |
60 | lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o | 62 | lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o |
61 | lib-$(CONFIG_XZ) += open_transformer.o decompress_unxz.o | 63 | lib-$(CONFIG_XZ) += open_transformer.o decompress_unxz.o |
64 | lib-$(CONFIG_FEATURE_UNZIP_XZ) += open_transformer.o decompress_unxz.o | ||
62 | lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o | 65 | lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o |
63 | lib-$(CONFIG_ZCAT) += open_transformer.o decompress_gunzip.o | 66 | lib-$(CONFIG_ZCAT) += open_transformer.o decompress_gunzip.o |
64 | lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o | 67 | lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o |
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index bd034afdc..1830ffb8d 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c | |||
@@ -127,8 +127,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
127 | if (hard_link) { | 127 | if (hard_link) { |
128 | res = link(hard_link, dst_name); | 128 | res = link(hard_link, dst_name); |
129 | if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { | 129 | if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |
130 | /* shared message */ | ||
130 | bb_perror_msg("can't create %slink " | 131 | bb_perror_msg("can't create %slink " |
131 | "from %s to %s", "hard", | 132 | "%s to %s", "hard", |
132 | dst_name, | 133 | dst_name, |
133 | hard_link); | 134 | hard_link); |
134 | } | 135 | } |
@@ -181,8 +182,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
181 | if (res != 0 | 182 | if (res != 0 |
182 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | 183 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
183 | ) { | 184 | ) { |
185 | /* shared message */ | ||
184 | bb_perror_msg("can't create %slink " | 186 | bb_perror_msg("can't create %slink " |
185 | "from %s to %s", "sym", | 187 | "%s to %s", "sym", |
186 | dst_name, | 188 | dst_name, |
187 | file_header->link_target); | 189 | file_header->link_target); |
188 | } | 190 | } |
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index fe5953da2..4fb989c29 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c | |||
@@ -134,7 +134,7 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted) | |||
134 | 134 | ||
135 | /* Avoid 32-bit overflow (dump bit buffer to top of output) */ | 135 | /* Avoid 32-bit overflow (dump bit buffer to top of output) */ |
136 | if (bit_count >= 24) { | 136 | if (bit_count >= 24) { |
137 | bits = bd->inbufBits & ((1 << bit_count) - 1); | 137 | bits = bd->inbufBits & ((1U << bit_count) - 1); |
138 | bits_wanted -= bit_count; | 138 | bits_wanted -= bit_count; |
139 | bits <<= bits_wanted; | 139 | bits <<= bits_wanted; |
140 | bit_count = 0; | 140 | bit_count = 0; |
@@ -158,11 +158,11 @@ static int get_next_block(bunzip_data *bd) | |||
158 | { | 158 | { |
159 | struct group_data *hufGroup; | 159 | struct group_data *hufGroup; |
160 | int dbufCount, dbufSize, groupCount, *base, *limit, selector, | 160 | int dbufCount, dbufSize, groupCount, *base, *limit, selector, |
161 | i, j, t, runPos, symCount, symTotal, nSelectors, byteCount[256]; | 161 | i, j, runPos, symCount, symTotal, nSelectors, byteCount[256]; |
162 | int runCnt = runCnt; /* for compiler */ | 162 | int runCnt = runCnt; /* for compiler */ |
163 | uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; | 163 | uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; |
164 | uint32_t *dbuf; | 164 | uint32_t *dbuf; |
165 | unsigned origPtr; | 165 | unsigned origPtr, t; |
166 | 166 | ||
167 | dbuf = bd->dbuf; | 167 | dbuf = bd->dbuf; |
168 | dbufSize = bd->dbufSize; | 168 | dbufSize = bd->dbufSize; |
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index c8622f97b..a9040877e 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c | |||
@@ -278,9 +278,10 @@ unpack_lzma_stream(transformer_state_t *xstate) | |||
278 | 278 | ||
279 | if (state >= LZMA_NUM_LIT_STATES) { | 279 | if (state >= LZMA_NUM_LIT_STATES) { |
280 | int match_byte; | 280 | int match_byte; |
281 | uint32_t pos = buffer_pos - rep0; | 281 | uint32_t pos; |
282 | 282 | ||
283 | while (pos >= header.dict_size) | 283 | pos = buffer_pos - rep0; |
284 | if ((int32_t)pos < 0) | ||
284 | pos += header.dict_size; | 285 | pos += header.dict_size; |
285 | match_byte = buffer[pos]; | 286 | match_byte = buffer[pos]; |
286 | do { | 287 | do { |
@@ -336,9 +337,11 @@ unpack_lzma_stream(transformer_state_t *xstate) | |||
336 | ); | 337 | ); |
337 | if (!rc_is_bit_1(rc, prob2)) { | 338 | if (!rc_is_bit_1(rc, prob2)) { |
338 | #if ENABLE_FEATURE_LZMA_FAST | 339 | #if ENABLE_FEATURE_LZMA_FAST |
339 | uint32_t pos = buffer_pos - rep0; | 340 | uint32_t pos; |
340 | state = state < LZMA_NUM_LIT_STATES ? 9 : 11; | 341 | state = state < LZMA_NUM_LIT_STATES ? 9 : 11; |
341 | while (pos >= header.dict_size) | 342 | |
343 | pos = buffer_pos - rep0; | ||
344 | if ((int32_t)pos < 0) | ||
342 | pos += header.dict_size; | 345 | pos += header.dict_size; |
343 | previous_byte = buffer[pos]; | 346 | previous_byte = buffer[pos]; |
344 | goto one_byte1; | 347 | goto one_byte1; |
@@ -429,10 +432,25 @@ unpack_lzma_stream(transformer_state_t *xstate) | |||
429 | } | 432 | } |
430 | 433 | ||
431 | len += LZMA_MATCH_MIN_LEN; | 434 | len += LZMA_MATCH_MIN_LEN; |
435 | /* | ||
436 | * LZMA SDK has this optimized: | ||
437 | * it precalculates size and copies many bytes | ||
438 | * in a loop with simpler checks, a-la: | ||
439 | * do | ||
440 | * *(dest) = *(dest + ofs); | ||
441 | * while (++dest != lim); | ||
442 | * and | ||
443 | * do { | ||
444 | * buffer[buffer_pos++] = buffer[pos]; | ||
445 | * if (++pos == header.dict_size) | ||
446 | * pos = 0; | ||
447 | * } while (--cur_len != 0); | ||
448 | * Our code is slower (more checks per byte copy): | ||
449 | */ | ||
432 | IF_NOT_FEATURE_LZMA_FAST(string:) | 450 | IF_NOT_FEATURE_LZMA_FAST(string:) |
433 | do { | 451 | do { |
434 | uint32_t pos = buffer_pos - rep0; | 452 | uint32_t pos = buffer_pos - rep0; |
435 | while (pos >= header.dict_size) | 453 | if ((int32_t)pos < 0) |
436 | pos += header.dict_size; | 454 | pos += header.dict_size; |
437 | previous_byte = buffer[pos]; | 455 | previous_byte = buffer[pos]; |
438 | IF_NOT_FEATURE_LZMA_FAST(one_byte2:) | 456 | IF_NOT_FEATURE_LZMA_FAST(one_byte2:) |
@@ -448,6 +466,9 @@ unpack_lzma_stream(transformer_state_t *xstate) | |||
448 | } while (len != 0 && buffer_pos < header.dst_size); | 466 | } while (len != 0 && buffer_pos < header.dst_size); |
449 | /* FIXME: ...........^^^^^ | 467 | /* FIXME: ...........^^^^^ |
450 | * shouldn't it be "global_pos + buffer_pos < header.dst_size"? | 468 | * shouldn't it be "global_pos + buffer_pos < header.dst_size"? |
469 | * It probably should, but it is a "do we accidentally | ||
470 | * unpack more bytes than expected?" check - which | ||
471 | * never happens for well-formed compression data... | ||
451 | */ | 472 | */ |
452 | } | 473 | } |
453 | } | 474 | } |
diff --git a/archival/lzop.c b/archival/lzop.c index e0e90ac6c..ca61add3c 100644 --- a/archival/lzop.c +++ b/archival/lzop.c | |||
@@ -53,7 +53,8 @@ | |||
53 | //config: and take up 3.2K of code. | 53 | //config: and take up 3.2K of code. |
54 | 54 | ||
55 | //applet:IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP)) | 55 | //applet:IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP)) |
56 | //applet:IF_UNLZOP(APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop)) | 56 | // APPLET_ODDNAME:name main location suid_type help |
57 | //applet:IF_UNLZOP( APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop)) | ||
57 | //applet:IF_LZOPCAT(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat)) | 58 | //applet:IF_LZOPCAT(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat)) |
58 | //kbuild:lib-$(CONFIG_LZOP) += lzop.o | 59 | //kbuild:lib-$(CONFIG_LZOP) += lzop.o |
59 | //kbuild:lib-$(CONFIG_UNLZOP) += lzop.o | 60 | //kbuild:lib-$(CONFIG_UNLZOP) += lzop.o |
diff --git a/archival/tar.c b/archival/tar.c index c87d23597..34e3052ce 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -49,13 +49,15 @@ | |||
49 | //config: create compressed archives. It's probably the most widely used | 49 | //config: create compressed archives. It's probably the most widely used |
50 | //config: UNIX archive program. | 50 | //config: UNIX archive program. |
51 | //config: | 51 | //config: |
52 | //config:config FEATURE_TAR_LONG_OPTIONS | ||
53 | //config: bool "Enable long options" | ||
54 | //config: default y | ||
55 | //config: depends on TAR && LONG_OPTS | ||
56 | //config: | ||
52 | //config:config FEATURE_TAR_CREATE | 57 | //config:config FEATURE_TAR_CREATE |
53 | //config: bool "Enable archive creation" | 58 | //config: bool "Enable -c (archive creation)" |
54 | //config: default y | 59 | //config: default y |
55 | //config: depends on TAR | 60 | //config: depends on TAR |
56 | //config: help | ||
57 | //config: If you enable this option you'll be able to create | ||
58 | //config: tar archives using the `-c' option. | ||
59 | //config: | 61 | //config: |
60 | //config:config FEATURE_TAR_AUTODETECT | 62 | //config:config FEATURE_TAR_AUTODETECT |
61 | //config: bool "Autodetect compressed tarballs" | 63 | //config: bool "Autodetect compressed tarballs" |
@@ -74,7 +76,7 @@ | |||
74 | //config: a list of files to include or exclude from an archive. | 76 | //config: a list of files to include or exclude from an archive. |
75 | //config: | 77 | //config: |
76 | //config:config FEATURE_TAR_OLDGNU_COMPATIBILITY | 78 | //config:config FEATURE_TAR_OLDGNU_COMPATIBILITY |
77 | //config: bool "Support for old tar header format" | 79 | //config: bool "Support old tar header format" |
78 | //config: default y | 80 | //config: default y |
79 | //config: depends on TAR || DPKG | 81 | //config: depends on TAR || DPKG |
80 | //config: help | 82 | //config: help |
@@ -93,22 +95,12 @@ | |||
93 | //config: tarballs still exist. | 95 | //config: tarballs still exist. |
94 | //config: | 96 | //config: |
95 | //config:config FEATURE_TAR_GNU_EXTENSIONS | 97 | //config:config FEATURE_TAR_GNU_EXTENSIONS |
96 | //config: bool "Support for GNU tar extensions (long filenames)" | 98 | //config: bool "Support GNU tar extensions (long filenames)" |
97 | //config: default y | 99 | //config: default y |
98 | //config: depends on TAR || DPKG | 100 | //config: depends on TAR || DPKG |
99 | //config: help | ||
100 | //config: With this option busybox supports GNU long filenames and | ||
101 | //config: linknames. | ||
102 | //config: | ||
103 | //config:config FEATURE_TAR_LONG_OPTIONS | ||
104 | //config: bool "Enable long options" | ||
105 | //config: default y | ||
106 | //config: depends on TAR && LONG_OPTS | ||
107 | //config: help | ||
108 | //config: Enable use of long options, increases size by about 400 Bytes | ||
109 | //config: | 101 | //config: |
110 | //config:config FEATURE_TAR_TO_COMMAND | 102 | //config:config FEATURE_TAR_TO_COMMAND |
111 | //config: bool "Support for writing to an external program" | 103 | //config: bool "Support writing to an external program (--to-command)" |
112 | //config: default y | 104 | //config: default y |
113 | //config: depends on TAR && FEATURE_TAR_LONG_OPTIONS | 105 | //config: depends on TAR && FEATURE_TAR_LONG_OPTIONS |
114 | //config: help | 106 | //config: help |
@@ -121,20 +113,17 @@ | |||
121 | //config: default y | 113 | //config: default y |
122 | //config: depends on TAR | 114 | //config: depends on TAR |
123 | //config: help | 115 | //config: help |
124 | //config: Enables use of user and group names in tar. This affects contents | 116 | //config: Enable use of user and group names in tar. This affects contents |
125 | //config: listings (-t) and preserving permissions when unpacking (-p). | 117 | //config: listings (-t) and preserving permissions when unpacking (-p). |
126 | //config: +200 bytes. | 118 | //config: +200 bytes. |
127 | //config: | 119 | //config: |
128 | //config:config FEATURE_TAR_NOPRESERVE_TIME | 120 | //config:config FEATURE_TAR_NOPRESERVE_TIME |
129 | //config: bool "Enable -m (do not preserve time) option" | 121 | //config: bool "Enable -m (do not preserve time) GNU option" |
130 | //config: default y | 122 | //config: default y |
131 | //config: depends on TAR | 123 | //config: depends on TAR |
132 | //config: help | ||
133 | //config: With this option busybox supports GNU tar -m | ||
134 | //config: (do not preserve time) option. | ||
135 | //config: | 124 | //config: |
136 | //config:config FEATURE_TAR_SELINUX | 125 | //config:config FEATURE_TAR_SELINUX |
137 | //config: bool "Support for extracting SELinux labels" | 126 | //config: bool "Support extracting SELinux labels" |
138 | //config: default n | 127 | //config: default n |
139 | //config: depends on TAR && SELINUX | 128 | //config: depends on TAR && SELINUX |
140 | //config: help | 129 | //config: help |
diff --git a/archival/unzip.c b/archival/unzip.c index 9ad03d0e2..56989fa0b 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -34,6 +34,23 @@ | |||
34 | //config: ZIP files without deleted/updated files, SFX archives etc, | 34 | //config: ZIP files without deleted/updated files, SFX archives etc, |
35 | //config: you can reduce code size by unselecting this option. | 35 | //config: you can reduce code size by unselecting this option. |
36 | //config: To support less trivial ZIPs, say Y. | 36 | //config: To support less trivial ZIPs, say Y. |
37 | //config: | ||
38 | //config:config FEATURE_UNZIP_BZIP2 | ||
39 | //config: bool "Support compression method 12 (bzip2)" | ||
40 | //config: default y | ||
41 | //config: depends on FEATURE_UNZIP_CDF && DESKTOP | ||
42 | // FEATURE_UNZIP_CDF is needed, otherwise we can't find start of next file | ||
43 | // DESKTOP is needed to get back uncompressed length | ||
44 | //config: | ||
45 | //config:config FEATURE_UNZIP_LZMA | ||
46 | //config: bool "Support compression method 14 (lzma)" | ||
47 | //config: default y | ||
48 | //config: depends on FEATURE_UNZIP_CDF && DESKTOP | ||
49 | //config: | ||
50 | //config:config FEATURE_UNZIP_XZ | ||
51 | //config: bool "Support compression method 95 (xz)" | ||
52 | //config: default y | ||
53 | //config: depends on FEATURE_UNZIP_CDF && DESKTOP | ||
37 | 54 | ||
38 | //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) | 55 | //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) |
39 | //kbuild:lib-$(CONFIG_UNZIP) += unzip.o | 56 | //kbuild:lib-$(CONFIG_UNZIP) += unzip.o |
@@ -65,8 +82,8 @@ | |||
65 | enum { | 82 | enum { |
66 | #if BB_BIG_ENDIAN | 83 | #if BB_BIG_ENDIAN |
67 | ZIP_FILEHEADER_MAGIC = 0x504b0304, | 84 | ZIP_FILEHEADER_MAGIC = 0x504b0304, |
68 | ZIP_CDF_MAGIC = 0x504b0102, /* central directory's file header */ | 85 | ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */ |
69 | ZIP_CDE_MAGIC = 0x504b0506, /* "end of central directory" record */ | 86 | ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */ |
70 | ZIP_DD_MAGIC = 0x504b0708, | 87 | ZIP_DD_MAGIC = 0x504b0708, |
71 | #else | 88 | #else |
72 | ZIP_FILEHEADER_MAGIC = 0x04034b50, | 89 | ZIP_FILEHEADER_MAGIC = 0x04034b50, |
@@ -94,16 +111,16 @@ typedef union { | |||
94 | /* filename follows (not NUL terminated) */ | 111 | /* filename follows (not NUL terminated) */ |
95 | /* extra field follows */ | 112 | /* extra field follows */ |
96 | /* data follows */ | 113 | /* data follows */ |
97 | } formatted PACKED; | 114 | } fmt PACKED; |
98 | } zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ | 115 | } zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ |
99 | 116 | ||
100 | #define FIX_ENDIANNESS_ZIP(zip_header) \ | 117 | #define FIX_ENDIANNESS_ZIP(zip) \ |
101 | do { if (BB_BIG_ENDIAN) { \ | 118 | do { if (BB_BIG_ENDIAN) { \ |
102 | (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ | 119 | (zip).fmt.crc32 = SWAP_LE32((zip).fmt.crc32 ); \ |
103 | (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ | 120 | (zip).fmt.cmpsize = SWAP_LE32((zip).fmt.cmpsize ); \ |
104 | (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ | 121 | (zip).fmt.ucmpsize = SWAP_LE32((zip).fmt.ucmpsize ); \ |
105 | (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ | 122 | (zip).fmt.filename_len = SWAP_LE16((zip).fmt.filename_len); \ |
106 | (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ | 123 | (zip).fmt.extra_len = SWAP_LE16((zip).fmt.extra_len ); \ |
107 | }} while (0) | 124 | }} while (0) |
108 | 125 | ||
109 | #define CDF_HEADER_LEN 42 | 126 | #define CDF_HEADER_LEN 42 |
@@ -121,39 +138,39 @@ typedef union { | |||
121 | uint32_t crc32; /* 12-15 */ | 138 | uint32_t crc32; /* 12-15 */ |
122 | uint32_t cmpsize; /* 16-19 */ | 139 | uint32_t cmpsize; /* 16-19 */ |
123 | uint32_t ucmpsize; /* 20-23 */ | 140 | uint32_t ucmpsize; /* 20-23 */ |
124 | uint16_t file_name_length; /* 24-25 */ | 141 | uint16_t filename_len; /* 24-25 */ |
125 | uint16_t extra_field_length; /* 26-27 */ | 142 | uint16_t extra_len; /* 26-27 */ |
126 | uint16_t file_comment_length; /* 28-29 */ | 143 | uint16_t file_comment_length; /* 28-29 */ |
127 | uint16_t disk_number_start; /* 30-31 */ | 144 | uint16_t disk_number_start; /* 30-31 */ |
128 | uint16_t internal_file_attributes; /* 32-33 */ | 145 | uint16_t internal_attributes; /* 32-33 */ |
129 | uint32_t external_file_attributes PACKED; /* 34-37 */ | 146 | uint32_t external_attributes PACKED; /* 34-37 */ |
130 | uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ | 147 | uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ |
131 | /* filename follows (not NUL terminated) */ | 148 | /* filename follows (not NUL terminated) */ |
132 | /* extra field follows */ | 149 | /* extra field follows */ |
133 | /* comment follows */ | 150 | /* file comment follows */ |
134 | } formatted PACKED; | 151 | } fmt PACKED; |
135 | } cdf_header_t; | 152 | } cdf_header_t; |
136 | 153 | ||
137 | #define FIX_ENDIANNESS_CDF(cdf_header) \ | 154 | #define FIX_ENDIANNESS_CDF(cdf) \ |
138 | do { if (BB_BIG_ENDIAN) { \ | 155 | do { if (BB_BIG_ENDIAN) { \ |
139 | (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \ | 156 | (cdf).fmt.version_made_by = SWAP_LE16((cdf).fmt.version_made_by); \ |
140 | (cdf_header).formatted.version_needed = SWAP_LE16((cdf_header).formatted.version_needed); \ | 157 | (cdf).fmt.version_needed = SWAP_LE16((cdf).fmt.version_needed); \ |
141 | (cdf_header).formatted.method = SWAP_LE16((cdf_header).formatted.method ); \ | 158 | (cdf).fmt.method = SWAP_LE16((cdf).fmt.method ); \ |
142 | (cdf_header).formatted.modtime = SWAP_LE16((cdf_header).formatted.modtime ); \ | 159 | (cdf).fmt.modtime = SWAP_LE16((cdf).fmt.modtime ); \ |
143 | (cdf_header).formatted.moddate = SWAP_LE16((cdf_header).formatted.moddate ); \ | 160 | (cdf).fmt.moddate = SWAP_LE16((cdf).fmt.moddate ); \ |
144 | (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ | 161 | (cdf).fmt.crc32 = SWAP_LE32((cdf).fmt.crc32 ); \ |
145 | (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ | 162 | (cdf).fmt.cmpsize = SWAP_LE32((cdf).fmt.cmpsize ); \ |
146 | (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ | 163 | (cdf).fmt.ucmpsize = SWAP_LE32((cdf).fmt.ucmpsize ); \ |
147 | (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ | 164 | (cdf).fmt.filename_len = SWAP_LE16((cdf).fmt.filename_len); \ |
148 | (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ | 165 | (cdf).fmt.extra_len = SWAP_LE16((cdf).fmt.extra_len ); \ |
149 | (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ | 166 | (cdf).fmt.file_comment_length = SWAP_LE16((cdf).fmt.file_comment_length); \ |
150 | (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ | 167 | (cdf).fmt.external_attributes = SWAP_LE32((cdf).fmt.external_attributes); \ |
151 | }} while (0) | 168 | }} while (0) |
152 | 169 | ||
153 | #define CDE_HEADER_LEN 16 | 170 | #define CDE_LEN 16 |
154 | 171 | ||
155 | typedef union { | 172 | typedef union { |
156 | uint8_t raw[CDE_HEADER_LEN]; | 173 | uint8_t raw[CDE_LEN]; |
157 | struct { | 174 | struct { |
158 | /* uint32_t signature; 50 4b 05 06 */ | 175 | /* uint32_t signature; 50 4b 05 06 */ |
159 | uint16_t this_disk_no; | 176 | uint16_t this_disk_no; |
@@ -162,14 +179,14 @@ typedef union { | |||
162 | uint16_t cdf_entries_total; | 179 | uint16_t cdf_entries_total; |
163 | uint32_t cdf_size; | 180 | uint32_t cdf_size; |
164 | uint32_t cdf_offset; | 181 | uint32_t cdf_offset; |
165 | /* uint16_t file_comment_length; */ | 182 | /* uint16_t archive_comment_length; */ |
166 | /* .ZIP file comment (variable size) */ | 183 | /* archive comment follows */ |
167 | } formatted PACKED; | 184 | } fmt PACKED; |
168 | } cde_header_t; | 185 | } cde_t; |
169 | 186 | ||
170 | #define FIX_ENDIANNESS_CDE(cde_header) \ | 187 | #define FIX_ENDIANNESS_CDE(cde) \ |
171 | do { if (BB_BIG_ENDIAN) { \ | 188 | do { if (BB_BIG_ENDIAN) { \ |
172 | (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \ | 189 | (cde).fmt.cdf_offset = SWAP_LE32((cde).fmt.cdf_offset); \ |
173 | }} while (0) | 190 | }} while (0) |
174 | 191 | ||
175 | struct BUG { | 192 | struct BUG { |
@@ -178,13 +195,13 @@ struct BUG { | |||
178 | * even though the elements are all in the right place. | 195 | * even though the elements are all in the right place. |
179 | */ | 196 | */ |
180 | char BUG_zip_header_must_be_26_bytes[ | 197 | char BUG_zip_header_must_be_26_bytes[ |
181 | offsetof(zip_header_t, formatted.extra_len) + 2 | 198 | offsetof(zip_header_t, fmt.extra_len) + 2 |
182 | == ZIP_HEADER_LEN ? 1 : -1]; | 199 | == ZIP_HEADER_LEN ? 1 : -1]; |
183 | char BUG_cdf_header_must_be_42_bytes[ | 200 | char BUG_cdf_header_must_be_42_bytes[ |
184 | offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 | 201 | offsetof(cdf_header_t, fmt.relative_offset_of_local_header) + 4 |
185 | == CDF_HEADER_LEN ? 1 : -1]; | 202 | == CDF_HEADER_LEN ? 1 : -1]; |
186 | char BUG_cde_header_must_be_16_bytes[ | 203 | char BUG_cde_must_be_16_bytes[ |
187 | sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; | 204 | sizeof(cde_t) == CDE_LEN ? 1 : -1]; |
188 | }; | 205 | }; |
189 | 206 | ||
190 | 207 | ||
@@ -210,7 +227,7 @@ enum { zip_fd = 3 }; | |||
210 | /* NB: does not preserve file position! */ | 227 | /* NB: does not preserve file position! */ |
211 | static uint32_t find_cdf_offset(void) | 228 | static uint32_t find_cdf_offset(void) |
212 | { | 229 | { |
213 | cde_header_t cde_header; | 230 | cde_t cde; |
214 | unsigned char *buf; | 231 | unsigned char *buf; |
215 | unsigned char *p; | 232 | unsigned char *p; |
216 | off_t end; | 233 | off_t end; |
@@ -231,7 +248,7 @@ static uint32_t find_cdf_offset(void) | |||
231 | 248 | ||
232 | found = BAD_CDF_OFFSET; | 249 | found = BAD_CDF_OFFSET; |
233 | p = buf; | 250 | p = buf; |
234 | while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { | 251 | while (p <= buf + PEEK_FROM_END - CDE_LEN - 4) { |
235 | if (*p != 'P') { | 252 | if (*p != 'P') { |
236 | p++; | 253 | p++; |
237 | continue; | 254 | continue; |
@@ -243,19 +260,19 @@ static uint32_t find_cdf_offset(void) | |||
243 | if (*++p != 6) | 260 | if (*++p != 6) |
244 | continue; | 261 | continue; |
245 | /* we found CDE! */ | 262 | /* we found CDE! */ |
246 | memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN); | 263 | memcpy(cde.raw, p + 1, CDE_LEN); |
247 | FIX_ENDIANNESS_CDE(cde_header); | 264 | FIX_ENDIANNESS_CDE(cde); |
248 | /* | 265 | /* |
249 | * I've seen .ZIP files with seemingly valid CDEs | 266 | * I've seen .ZIP files with seemingly valid CDEs |
250 | * where cdf_offset points past EOF - ?? | 267 | * where cdf_offset points past EOF - ?? |
251 | * This check ignores such CDEs: | 268 | * This check ignores such CDEs: |
252 | */ | 269 | */ |
253 | if (cde_header.formatted.cdf_offset < end + (p - buf)) { | 270 | if (cde.fmt.cdf_offset < end + (p - buf)) { |
254 | found = cde_header.formatted.cdf_offset; | 271 | found = cde.fmt.cdf_offset; |
255 | dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x", | 272 | dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x", |
256 | (unsigned)found, end + (p-3 - buf)); | 273 | (unsigned)found, end + (p-3 - buf)); |
257 | dbg(" cdf_offset+cdf_size:0x%x", | 274 | dbg(" cdf_offset+cdf_size:0x%x", |
258 | (unsigned)(found + SWAP_LE32(cde_header.formatted.cdf_size))); | 275 | (unsigned)(found + SWAP_LE32(cde.fmt.cdf_size))); |
259 | /* | 276 | /* |
260 | * We do not "break" here because only the last CDE is valid. | 277 | * We do not "break" here because only the last CDE is valid. |
261 | * I've seen a .zip archive which contained a .zip file, | 278 | * I've seen a .zip archive which contained a .zip file, |
@@ -269,7 +286,7 @@ static uint32_t find_cdf_offset(void) | |||
269 | return found; | 286 | return found; |
270 | }; | 287 | }; |
271 | 288 | ||
272 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | 289 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf) |
273 | { | 290 | { |
274 | uint32_t magic; | 291 | uint32_t magic; |
275 | 292 | ||
@@ -279,23 +296,25 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | |||
279 | dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); | 296 | dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); |
280 | xlseek(zip_fd, cdf_offset, SEEK_SET); | 297 | xlseek(zip_fd, cdf_offset, SEEK_SET); |
281 | xread(zip_fd, &magic, 4); | 298 | xread(zip_fd, &magic, 4); |
282 | /* Central Directory End? */ | 299 | /* Central Directory End? Assume CDF has ended. |
300 | * (more correct method is to use cde.cdf_entries_total counter) | ||
301 | */ | ||
283 | if (magic == ZIP_CDE_MAGIC) { | 302 | if (magic == ZIP_CDE_MAGIC) { |
284 | dbg("got ZIP_CDE_MAGIC"); | 303 | dbg("got ZIP_CDE_MAGIC"); |
285 | return 0; /* EOF */ | 304 | return 0; /* EOF */ |
286 | } | 305 | } |
287 | xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); | 306 | xread(zip_fd, cdf->raw, CDF_HEADER_LEN); |
288 | 307 | ||
289 | FIX_ENDIANNESS_CDF(*cdf_ptr); | 308 | FIX_ENDIANNESS_CDF(*cdf); |
290 | dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u", | 309 | dbg(" filename_len:%u extra_len:%u file_comment_length:%u", |
291 | (unsigned)cdf_ptr->formatted.file_name_length, | 310 | (unsigned)cdf->fmt.filename_len, |
292 | (unsigned)cdf_ptr->formatted.extra_field_length, | 311 | (unsigned)cdf->fmt.extra_len, |
293 | (unsigned)cdf_ptr->formatted.file_comment_length | 312 | (unsigned)cdf->fmt.file_comment_length |
294 | ); | 313 | ); |
295 | cdf_offset += 4 + CDF_HEADER_LEN | 314 | cdf_offset += 4 + CDF_HEADER_LEN |
296 | + cdf_ptr->formatted.file_name_length | 315 | + cdf->fmt.filename_len |
297 | + cdf_ptr->formatted.extra_field_length | 316 | + cdf->fmt.extra_len |
298 | + cdf_ptr->formatted.file_comment_length; | 317 | + cdf->fmt.file_comment_length; |
299 | 318 | ||
300 | return cdf_offset; | 319 | return cdf_offset; |
301 | }; | 320 | }; |
@@ -318,34 +337,67 @@ static void unzip_create_leading_dirs(const char *fn) | |||
318 | free(name); | 337 | free(name); |
319 | } | 338 | } |
320 | 339 | ||
321 | static void unzip_extract(zip_header_t *zip_header, int dst_fd) | 340 | static void unzip_extract(zip_header_t *zip, int dst_fd) |
322 | { | 341 | { |
323 | if (zip_header->formatted.method == 0) { | 342 | transformer_state_t xstate; |
343 | |||
344 | if (zip->fmt.method == 0) { | ||
324 | /* Method 0 - stored (not compressed) */ | 345 | /* Method 0 - stored (not compressed) */ |
325 | off_t size = zip_header->formatted.ucmpsize; | 346 | off_t size = zip->fmt.ucmpsize; |
326 | if (size) | 347 | if (size) |
327 | bb_copyfd_exact_size(zip_fd, dst_fd, size); | 348 | bb_copyfd_exact_size(zip_fd, dst_fd, size); |
328 | } else { | 349 | return; |
350 | } | ||
351 | |||
352 | init_transformer_state(&xstate); | ||
353 | xstate.bytes_in = zip->fmt.cmpsize; | ||
354 | xstate.src_fd = zip_fd; | ||
355 | xstate.dst_fd = dst_fd; | ||
356 | if (zip->fmt.method == 8) { | ||
329 | /* Method 8 - inflate */ | 357 | /* Method 8 - inflate */ |
330 | transformer_state_t xstate; | ||
331 | init_transformer_state(&xstate); | ||
332 | xstate.bytes_in = zip_header->formatted.cmpsize; | ||
333 | xstate.src_fd = zip_fd; | ||
334 | xstate.dst_fd = dst_fd; | ||
335 | if (inflate_unzip(&xstate) < 0) | 358 | if (inflate_unzip(&xstate) < 0) |
336 | bb_error_msg_and_die("inflate error"); | 359 | bb_error_msg_and_die("inflate error"); |
337 | /* Validate decompression - crc */ | 360 | /* Validate decompression - crc */ |
338 | if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { | 361 | if (zip->fmt.crc32 != (xstate.crc32 ^ 0xffffffffL)) { |
339 | bb_error_msg_and_die("crc error"); | 362 | bb_error_msg_and_die("crc error"); |
340 | } | 363 | } |
341 | /* Validate decompression - size */ | ||
342 | if (zip_header->formatted.ucmpsize != xstate.bytes_out) { | ||
343 | /* Don't die. Who knows, maybe len calculation | ||
344 | * was botched somewhere. After all, crc matched! */ | ||
345 | bb_error_msg("bad length"); | ||
346 | } | ||
347 | } | 364 | } |
348 | /* TODO? method 12: bzip2, method 14: LZMA */ | 365 | #if ENABLE_FEATURE_UNZIP_BZIP2 |
366 | else if (zip->fmt.method == 12) { | ||
367 | /* Tested. Unpacker reads too much, but we use CDF | ||
368 | * and will seek to the correct beginning of next file. | ||
369 | */ | ||
370 | xstate.bytes_out = unpack_bz2_stream(&xstate); | ||
371 | if (xstate.bytes_out < 0) | ||
372 | bb_error_msg_and_die("inflate error"); | ||
373 | } | ||
374 | #endif | ||
375 | #if ENABLE_FEATURE_UNZIP_LZMA | ||
376 | else if (zip->fmt.method == 14) { | ||
377 | /* Not tested yet */ | ||
378 | xstate.bytes_out = unpack_lzma_stream(&xstate); | ||
379 | if (xstate.bytes_out < 0) | ||
380 | bb_error_msg_and_die("inflate error"); | ||
381 | } | ||
382 | #endif | ||
383 | #if ENABLE_FEATURE_UNZIP_XZ | ||
384 | else if (zip->fmt.method == 95) { | ||
385 | /* Not tested yet */ | ||
386 | xstate.bytes_out = unpack_xz_stream(&xstate); | ||
387 | if (xstate.bytes_out < 0) | ||
388 | bb_error_msg_and_die("inflate error"); | ||
389 | } | ||
390 | #endif | ||
391 | else { | ||
392 | bb_error_msg_and_die("unsupported method %u", zip->fmt.method); | ||
393 | } | ||
394 | |||
395 | /* Validate decompression - size */ | ||
396 | if (zip->fmt.ucmpsize != xstate.bytes_out) { | ||
397 | /* Don't die. Who knows, maybe len calculation | ||
398 | * was botched somewhere. After all, crc matched! */ | ||
399 | bb_error_msg("bad length"); | ||
400 | } | ||
349 | } | 401 | } |
350 | 402 | ||
351 | static void my_fgets80(char *buf80) | 403 | static void my_fgets80(char *buf80) |
@@ -566,7 +618,7 @@ int unzip_main(int argc, char **argv) | |||
566 | total_entries = 0; | 618 | total_entries = 0; |
567 | cdf_offset = find_cdf_offset(); /* try to seek to the end, find CDE and CDF start */ | 619 | cdf_offset = find_cdf_offset(); /* try to seek to the end, find CDE and CDF start */ |
568 | while (1) { | 620 | while (1) { |
569 | zip_header_t zip_header; | 621 | zip_header_t zip; |
570 | mode_t dir_mode = 0777; | 622 | mode_t dir_mode = 0777; |
571 | #if ENABLE_FEATURE_UNZIP_CDF | 623 | #if ENABLE_FEATURE_UNZIP_CDF |
572 | mode_t file_mode = 0666; | 624 | mode_t file_mode = 0666; |
@@ -592,7 +644,7 @@ int unzip_main(int argc, char **argv) | |||
592 | 644 | ||
593 | /* Check magic number */ | 645 | /* Check magic number */ |
594 | xread(zip_fd, &magic, 4); | 646 | xread(zip_fd, &magic, 4); |
595 | /* Central directory? It's at the end, so exit */ | 647 | /* CDF item? Assume there are no more files, exit */ |
596 | if (magic == ZIP_CDF_MAGIC) { | 648 | if (magic == ZIP_CDF_MAGIC) { |
597 | dbg("got ZIP_CDF_MAGIC"); | 649 | dbg("got ZIP_CDF_MAGIC"); |
598 | break; | 650 | break; |
@@ -608,71 +660,70 @@ int unzip_main(int argc, char **argv) | |||
608 | bb_error_msg_and_die("invalid zip magic %08X", (int)magic); | 660 | bb_error_msg_and_die("invalid zip magic %08X", (int)magic); |
609 | dbg("got ZIP_FILEHEADER_MAGIC"); | 661 | dbg("got ZIP_FILEHEADER_MAGIC"); |
610 | 662 | ||
611 | xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); | 663 | xread(zip_fd, zip.raw, ZIP_HEADER_LEN); |
612 | FIX_ENDIANNESS_ZIP(zip_header); | 664 | FIX_ENDIANNESS_ZIP(zip); |
613 | if ((zip_header.formatted.method != 0) | 665 | if (zip.fmt.zip_flags & SWAP_LE16(0x0008)) { |
614 | && (zip_header.formatted.method != 8) | 666 | bb_error_msg_and_die("zip flag %s is not supported", |
615 | ) { | 667 | "8 (streaming)"); |
616 | /* TODO? method 12: bzip2, method 14: LZMA */ | ||
617 | bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method); | ||
618 | } | ||
619 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) { | ||
620 | bb_error_msg_and_die("zip flags 1 and 8 are not supported"); | ||
621 | } | 668 | } |
622 | } | 669 | } |
623 | #if ENABLE_FEATURE_UNZIP_CDF | 670 | #if ENABLE_FEATURE_UNZIP_CDF |
624 | else { | 671 | else { |
625 | /* cdf_offset is valid (and we know the file is seekable) */ | 672 | /* cdf_offset is valid (and we know the file is seekable) */ |
626 | cdf_header_t cdf_header; | 673 | cdf_header_t cdf; |
627 | cdf_offset = read_next_cdf(cdf_offset, &cdf_header); | 674 | cdf_offset = read_next_cdf(cdf_offset, &cdf); |
628 | if (cdf_offset == 0) /* EOF? */ | 675 | if (cdf_offset == 0) /* EOF? */ |
629 | break; | 676 | break; |
630 | # if 1 | 677 | # if 1 |
631 | xlseek(zip_fd, | 678 | xlseek(zip_fd, |
632 | SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4, | 679 | SWAP_LE32(cdf.fmt.relative_offset_of_local_header) + 4, |
633 | SEEK_SET); | 680 | SEEK_SET); |
634 | xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); | 681 | xread(zip_fd, zip.raw, ZIP_HEADER_LEN); |
635 | FIX_ENDIANNESS_ZIP(zip_header); | 682 | FIX_ENDIANNESS_ZIP(zip); |
636 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { | 683 | if (zip.fmt.zip_flags & SWAP_LE16(0x0008)) { |
637 | /* 0x0008 - streaming. [u]cmpsize can be reliably gotten | 684 | /* 0x0008 - streaming. [u]cmpsize can be reliably gotten |
638 | * only from Central Directory. | 685 | * only from Central Directory. |
639 | */ | 686 | */ |
640 | zip_header.formatted.crc32 = cdf_header.formatted.crc32; | 687 | zip.fmt.crc32 = cdf.fmt.crc32; |
641 | zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; | 688 | zip.fmt.cmpsize = cdf.fmt.cmpsize; |
642 | zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; | 689 | zip.fmt.ucmpsize = cdf.fmt.ucmpsize; |
643 | } | 690 | } |
644 | # else | 691 | # else |
645 | /* CDF has the same data as local header, no need to read the latter */ | 692 | /* CDF has the same data as local header, no need to read the latter... |
646 | memcpy(&zip_header.formatted.version, | 693 | * ...not really. An archive was seen with cdf.extra_len == 6 but |
647 | &cdf_header.formatted.version_needed, ZIP_HEADER_LEN); | 694 | * zip.extra_len == 0. |
695 | */ | ||
696 | memcpy(&zip.fmt.version, | ||
697 | &cdf.fmt.version_needed, ZIP_HEADER_LEN); | ||
648 | xlseek(zip_fd, | 698 | xlseek(zip_fd, |
649 | SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN, | 699 | SWAP_LE32(cdf.fmt.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN, |
650 | SEEK_SET); | 700 | SEEK_SET); |
651 | # endif | 701 | # endif |
652 | if ((cdf_header.formatted.version_made_by >> 8) == 3) { | 702 | if ((cdf.fmt.version_made_by >> 8) == 3) { |
653 | /* This archive is created on Unix */ | 703 | /* This archive is created on Unix */ |
654 | dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); | 704 | dir_mode = file_mode = (cdf.fmt.external_attributes >> 16); |
655 | } | 705 | } |
656 | } | 706 | } |
657 | #endif | 707 | #endif |
658 | 708 | ||
659 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) { | 709 | if (zip.fmt.zip_flags & SWAP_LE16(0x0001)) { |
660 | /* 0x0001 - encrypted */ | 710 | /* 0x0001 - encrypted */ |
661 | bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); | 711 | bb_error_msg_and_die("zip flag %s is not supported", |
712 | "1 (encryption)"); | ||
662 | } | 713 | } |
663 | dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", | 714 | dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", |
664 | (unsigned)zip_header.formatted.cmpsize, | 715 | (unsigned)zip.fmt.cmpsize, |
665 | (unsigned)zip_header.formatted.extra_len, | 716 | (unsigned)zip.fmt.extra_len, |
666 | (unsigned)zip_header.formatted.ucmpsize | 717 | (unsigned)zip.fmt.ucmpsize |
667 | ); | 718 | ); |
668 | 719 | ||
669 | /* Read filename */ | 720 | /* Read filename */ |
670 | free(dst_fn); | 721 | free(dst_fn); |
671 | dst_fn = xzalloc(zip_header.formatted.filename_len + 1); | 722 | dst_fn = xzalloc(zip.fmt.filename_len + 1); |
672 | xread(zip_fd, dst_fn, zip_header.formatted.filename_len); | 723 | xread(zip_fd, dst_fn, zip.fmt.filename_len); |
673 | 724 | ||
674 | /* Skip extra header bytes */ | 725 | /* Skip extra header bytes */ |
675 | unzip_skip(zip_header.formatted.extra_len); | 726 | unzip_skip(zip.fmt.extra_len); |
676 | 727 | ||
677 | /* Guard against "/abspath", "/../" and similar attacks */ | 728 | /* Guard against "/abspath", "/../" and similar attacks */ |
678 | overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); | 729 | overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); |
@@ -681,129 +732,129 @@ int unzip_main(int argc, char **argv) | |||
681 | if (find_list_entry(zreject, dst_fn) | 732 | if (find_list_entry(zreject, dst_fn) |
682 | || (zaccept && !find_list_entry(zaccept, dst_fn)) | 733 | || (zaccept && !find_list_entry(zaccept, dst_fn)) |
683 | ) { /* Skip entry */ | 734 | ) { /* Skip entry */ |
684 | i = 'n'; | 735 | goto skip_cmpsize; |
685 | } else { | 736 | } |
686 | if (listing) { | 737 | |
687 | /* List entry */ | 738 | if (listing) { |
688 | char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; | 739 | /* List entry */ |
689 | sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", | 740 | char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; |
690 | (zip_header.formatted.moddate >> 5) & 0xf, // mm: 0x01e0 | 741 | sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", |
691 | (zip_header.formatted.moddate) & 0x1f, // dd: 0x001f | 742 | (zip.fmt.moddate >> 5) & 0xf, // mm: 0x01e0 |
692 | (zip_header.formatted.moddate >> 9) + 1980, // yy: 0xfe00 | 743 | (zip.fmt.moddate) & 0x1f, // dd: 0x001f |
693 | (zip_header.formatted.modtime >> 11), // hh: 0xf800 | 744 | (zip.fmt.moddate >> 9) + 1980, // yy: 0xfe00 |
694 | (zip_header.formatted.modtime >> 5) & 0x3f // mm: 0x07e0 | 745 | (zip.fmt.modtime >> 11), // hh: 0xf800 |
695 | // seconds/2 are not shown, encoded in ----------- 0x001f | 746 | (zip.fmt.modtime >> 5) & 0x3f // mm: 0x07e0 |
696 | ); | 747 | // seconds/2 not shown, encoded in -- 0x001f |
697 | if (!verbose) { | 748 | ); |
698 | // " Length Date Time Name\n" | 749 | if (!verbose) { |
699 | // "--------- ---------- ----- ----" | 750 | // " Length Date Time Name\n" |
700 | printf( "%9u " "%s " "%s\n", | 751 | // "--------- ---------- ----- ----" |
701 | (unsigned)zip_header.formatted.ucmpsize, | 752 | printf( "%9u " "%s " "%s\n", |
702 | dtbuf, | 753 | (unsigned)zip.fmt.ucmpsize, |
703 | dst_fn); | 754 | dtbuf, |
704 | } else { | 755 | dst_fn); |
705 | unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize; | 756 | } else { |
706 | if ((int32_t)percents < 0) | 757 | char method6[7]; |
707 | percents = 0; /* happens if ucmpsize < cmpsize */ | 758 | unsigned long percents; |
708 | percents = percents * 100; | 759 | |
709 | if (zip_header.formatted.ucmpsize) | 760 | sprintf(method6, "%6u", zip.fmt.method); |
710 | percents /= zip_header.formatted.ucmpsize; | 761 | if (zip.fmt.method == 0) { |
711 | // " Length Method Size Cmpr Date Time CRC-32 Name\n" | 762 | strcpy(method6, "Stored"); |
712 | // "-------- ------ ------- ---- ---------- ----- -------- ----" | 763 | } |
713 | printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", | 764 | if (zip.fmt.method == 8) { |
714 | (unsigned)zip_header.formatted.ucmpsize, | 765 | strcpy(method6, "Defl:N"); |
715 | zip_header.formatted.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */ | 766 | /* normal, maximum, fast, superfast */ |
716 | /* TODO: show other methods? | 767 | IF_DESKTOP(method6[5] = "NXFS"[(zip.fmt.zip_flags >> 1) & 3];) |
717 | * 1 - Shrunk | ||
718 | * 2 - Reduced with compression factor 1 | ||
719 | * 3 - Reduced with compression factor 2 | ||
720 | * 4 - Reduced with compression factor 3 | ||
721 | * 5 - Reduced with compression factor 4 | ||
722 | * 6 - Imploded | ||
723 | * 7 - Reserved for Tokenizing compression algorithm | ||
724 | * 9 - Deflate64 | ||
725 | * 10 - PKWARE Data Compression Library Imploding | ||
726 | * 11 - Reserved by PKWARE | ||
727 | * 12 - BZIP2 | ||
728 | */ | ||
729 | (unsigned)zip_header.formatted.cmpsize, | ||
730 | (unsigned)percents, | ||
731 | dtbuf, | ||
732 | zip_header.formatted.crc32, | ||
733 | dst_fn); | ||
734 | total_size += zip_header.formatted.cmpsize; | ||
735 | } | 768 | } |
736 | total_usize += zip_header.formatted.ucmpsize; | 769 | percents = zip.fmt.ucmpsize - zip.fmt.cmpsize; |
737 | i = 'n'; | 770 | if ((int32_t)percents < 0) |
738 | } else if (dst_fd == STDOUT_FILENO) { | 771 | percents = 0; /* happens if ucmpsize < cmpsize */ |
739 | /* Extracting to STDOUT */ | 772 | percents = percents * 100; |
740 | i = -1; | 773 | if (zip.fmt.ucmpsize) |
741 | } else if (last_char_is(dst_fn, '/')) { | 774 | percents /= zip.fmt.ucmpsize; |
742 | /* Extract directory */ | 775 | // " Length Method Size Cmpr Date Time CRC-32 Name\n" |
743 | if (stat(dst_fn, &stat_buf) == -1) { | 776 | // "-------- ------ ------- ---- ---------- ----- -------- ----" |
744 | if (errno != ENOENT) { | 777 | printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", |
745 | bb_perror_msg_and_die("can't stat '%s'", dst_fn); | 778 | (unsigned)zip.fmt.ucmpsize, |
746 | } | 779 | method6, |
747 | if (!quiet) { | 780 | (unsigned)zip.fmt.cmpsize, |
748 | printf(" creating: %s\n", dst_fn); | 781 | (unsigned)percents, |
749 | } | 782 | dtbuf, |
750 | unzip_create_leading_dirs(dst_fn); | 783 | zip.fmt.crc32, |
751 | if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) { | 784 | dst_fn); |
752 | xfunc_die(); | 785 | total_size += zip.fmt.cmpsize; |
753 | } | 786 | } |
754 | } else { | 787 | total_usize += zip.fmt.ucmpsize; |
755 | if (!S_ISDIR(stat_buf.st_mode)) { | 788 | goto skip_cmpsize; |
756 | bb_error_msg_and_die("'%s' exists but is not a %s", | 789 | } |
757 | dst_fn, "directory"); | 790 | |
758 | } | 791 | if (dst_fd == STDOUT_FILENO) { |
792 | /* Extracting to STDOUT */ | ||
793 | goto do_extract; | ||
794 | } | ||
795 | if (last_char_is(dst_fn, '/')) { | ||
796 | /* Extract directory */ | ||
797 | if (stat(dst_fn, &stat_buf) == -1) { | ||
798 | if (errno != ENOENT) { | ||
799 | bb_perror_msg_and_die("can't stat '%s'", dst_fn); | ||
800 | } | ||
801 | if (!quiet) { | ||
802 | printf(" creating: %s\n", dst_fn); | ||
803 | } | ||
804 | unzip_create_leading_dirs(dst_fn); | ||
805 | if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) { | ||
806 | xfunc_die(); | ||
759 | } | 807 | } |
760 | i = 'n'; | ||
761 | } else { | 808 | } else { |
762 | /* Extract file */ | 809 | if (!S_ISDIR(stat_buf.st_mode)) { |
763 | check_file: | 810 | bb_error_msg_and_die("'%s' exists but is not a %s", |
764 | if (stat(dst_fn, &stat_buf) == -1) { | 811 | dst_fn, "directory"); |
765 | /* File does not exist */ | ||
766 | if (errno != ENOENT) { | ||
767 | bb_perror_msg_and_die("can't stat '%s'", dst_fn); | ||
768 | } | ||
769 | i = 'y'; | ||
770 | } else { | ||
771 | /* File already exists */ | ||
772 | if (overwrite == O_NEVER) { | ||
773 | i = 'n'; | ||
774 | } else if (S_ISREG(stat_buf.st_mode)) { | ||
775 | /* File is regular file */ | ||
776 | if (overwrite == O_ALWAYS) { | ||
777 | i = 'y'; | ||
778 | } else { | ||
779 | printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); | ||
780 | my_fgets80(key_buf); | ||
781 | i = key_buf[0]; | ||
782 | } | ||
783 | } else { | ||
784 | /* File is not regular file */ | ||
785 | bb_error_msg_and_die("'%s' exists but is not a %s", | ||
786 | dst_fn, "regular file"); | ||
787 | } | ||
788 | } | 812 | } |
789 | } | 813 | } |
814 | goto skip_cmpsize; | ||
815 | } | ||
816 | check_file: | ||
817 | /* Extract file */ | ||
818 | if (stat(dst_fn, &stat_buf) == -1) { | ||
819 | /* File does not exist */ | ||
820 | if (errno != ENOENT) { | ||
821 | bb_perror_msg_and_die("can't stat '%s'", dst_fn); | ||
822 | } | ||
823 | goto do_open_and_extract; | ||
824 | } | ||
825 | /* File already exists */ | ||
826 | if (overwrite == O_NEVER) { | ||
827 | goto skip_cmpsize; | ||
828 | } | ||
829 | if (!S_ISREG(stat_buf.st_mode)) { | ||
830 | /* File is not regular file */ | ||
831 | bb_error_msg_and_die("'%s' exists but is not a %s", | ||
832 | dst_fn, "regular file"); | ||
790 | } | 833 | } |
834 | /* File is regular file */ | ||
835 | if (overwrite == O_ALWAYS) | ||
836 | goto do_open_and_extract; | ||
837 | printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); | ||
838 | my_fgets80(key_buf); | ||
791 | 839 | ||
792 | switch (i) { | 840 | switch (key_buf[0]) { |
793 | case 'A': | 841 | case 'A': |
794 | overwrite = O_ALWAYS; | 842 | overwrite = O_ALWAYS; |
795 | case 'y': /* Open file and fall into unzip */ | 843 | case 'y': /* Open file and fall into unzip */ |
844 | do_open_and_extract: | ||
796 | unzip_create_leading_dirs(dst_fn); | 845 | unzip_create_leading_dirs(dst_fn); |
797 | #if ENABLE_FEATURE_UNZIP_CDF | 846 | #if ENABLE_FEATURE_UNZIP_CDF |
798 | dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); | 847 | dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); |
799 | #else | 848 | #else |
800 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); | 849 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); |
801 | #endif | 850 | #endif |
802 | case -1: /* Unzip */ | 851 | do_extract: |
803 | if (!quiet) { | 852 | if (!quiet) { |
804 | printf(" inflating: %s\n", dst_fn); | 853 | printf(/* zip.fmt.method == 0 |
854 | ? " extracting: %s\n" | ||
855 | : */ " inflating: %s\n", dst_fn); | ||
805 | } | 856 | } |
806 | unzip_extract(&zip_header, dst_fd); | 857 | unzip_extract(&zip, dst_fd); |
807 | if (dst_fd != STDOUT_FILENO) { | 858 | if (dst_fd != STDOUT_FILENO) { |
808 | /* closing STDOUT is potentially bad for future business */ | 859 | /* closing STDOUT is potentially bad for future business */ |
809 | close(dst_fd); | 860 | close(dst_fd); |
@@ -812,9 +863,9 @@ int unzip_main(int argc, char **argv) | |||
812 | 863 | ||
813 | case 'N': | 864 | case 'N': |
814 | overwrite = O_NEVER; | 865 | overwrite = O_NEVER; |
815 | case 'n': | 866 | case 'n': /* Skip entry data */ |
816 | /* Skip entry data */ | 867 | skip_cmpsize: |
817 | unzip_skip(zip_header.formatted.cmpsize); | 868 | unzip_skip(zip.fmt.cmpsize); |
818 | break; | 869 | break; |
819 | 870 | ||
820 | case 'r': | 871 | case 'r': |
@@ -827,7 +878,7 @@ int unzip_main(int argc, char **argv) | |||
827 | goto check_file; | 878 | goto check_file; |
828 | 879 | ||
829 | default: | 880 | default: |
830 | printf("error: invalid response [%c]\n", (char)i); | 881 | printf("error: invalid response [%c]\n", (char)key_buf[0]); |
831 | goto check_file; | 882 | goto check_file; |
832 | } | 883 | } |
833 | 884 | ||