diff options
author | Ron Yorston <rmy@pobox.com> | 2017-07-24 11:40:28 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2017-07-24 12:03:28 +0100 |
commit | 60411636073cdc08e8005f0de00098e6dd00eaf5 (patch) | |
tree | 58673b64af1e663280be81f798c8f66ce116d1dd /archival | |
parent | eeceafbc5c4caf513c6d92b7d71ecb0ccd89a3f8 (diff) | |
parent | b72f1ef17b97802d33f0ac522f64bea0f65442c5 (diff) | |
download | busybox-w32-60411636073cdc08e8005f0de00098e6dd00eaf5.tar.gz busybox-w32-60411636073cdc08e8005f0de00098e6dd00eaf5.tar.bz2 busybox-w32-60411636073cdc08e8005f0de00098e6dd00eaf5.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'archival')
-rw-r--r-- | archival/Config.src | 8 | ||||
-rw-r--r-- | archival/ar.c | 24 | ||||
-rw-r--r-- | archival/bbunzip.c | 89 | ||||
-rw-r--r-- | archival/bzip2.c | 22 | ||||
-rw-r--r-- | archival/cpio.c | 22 | ||||
-rw-r--r-- | archival/dpkg.c | 10 | ||||
-rw-r--r-- | archival/dpkg_deb.c | 8 | ||||
-rw-r--r-- | archival/gzip.c | 30 | ||||
-rw-r--r-- | archival/lzop.c | 18 | ||||
-rw-r--r-- | archival/rpm.c | 4 | ||||
-rw-r--r-- | archival/rpm2cpio.c | 4 | ||||
-rw-r--r-- | archival/tar.c | 46 | ||||
-rw-r--r-- | archival/unzip.c | 205 |
13 files changed, 278 insertions, 212 deletions
diff --git a/archival/Config.src b/archival/Config.src index 0c97f3d7c..449914565 100644 --- a/archival/Config.src +++ b/archival/Config.src | |||
@@ -27,4 +27,12 @@ config FEATURE_SEAMLESS_Z | |||
27 | 27 | ||
28 | INSERT | 28 | INSERT |
29 | 29 | ||
30 | config FEATURE_LZMA_FAST | ||
31 | bool "Optimize lzma for speed" | ||
32 | default n | ||
33 | depends on UNLZMA || LZCAT || LZMA || FEATURE_SEAMLESS_LZMA | ||
34 | help | ||
35 | This option reduces decompression time by about 25% at the cost of | ||
36 | a 1K bigger binary. | ||
37 | |||
30 | endmenu | 38 | endmenu |
diff --git a/archival/ar.c b/archival/ar.c index f9f712fde..ea36bda88 100644 --- a/archival/ar.c +++ b/archival/ar.c | |||
@@ -18,34 +18,32 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | //config:config AR | 20 | //config:config AR |
21 | //config: bool "ar" | 21 | //config: bool "ar (9.5 kb)" |
22 | //config: default n # needs to be improved to be able to replace binutils ar | 22 | //config: default n # needs to be improved to be able to replace binutils ar |
23 | //config: help | 23 | //config: help |
24 | //config: ar is an archival utility program used to create, modify, and | 24 | //config: ar is an archival utility program used to create, modify, and |
25 | //config: extract contents from archives. In practice, it is used exclusively | 25 | //config: extract contents from archives. In practice, it is used exclusively |
26 | //config: for object module archives used by compilers. | 26 | //config: for object module archives used by compilers. |
27 | //config: | 27 | //config: |
28 | //config: On an x86 system, the ar applet adds about 1K. | 28 | //config: Unless you have a specific application which requires ar, you should |
29 | //config: | 29 | //config: probably say N here: most compilers come with their own ar utility. |
30 | //config: Unless you have a specific application which requires ar, you should | ||
31 | //config: probably say N here: most compilers come with their own ar utility. | ||
32 | //config: | 30 | //config: |
33 | //config:config FEATURE_AR_LONG_FILENAMES | 31 | //config:config FEATURE_AR_LONG_FILENAMES |
34 | //config: bool "Support long filenames (not needed for debs)" | 32 | //config: bool "Support long filenames (not needed for debs)" |
35 | //config: default y | 33 | //config: default y |
36 | //config: depends on AR | 34 | //config: depends on AR |
37 | //config: help | 35 | //config: help |
38 | //config: By default the ar format can only store the first 15 characters | 36 | //config: By default the ar format can only store the first 15 characters |
39 | //config: of the filename, this option removes that limitation. | 37 | //config: of the filename, this option removes that limitation. |
40 | //config: It supports the GNU ar long filename method which moves multiple long | 38 | //config: It supports the GNU ar long filename method which moves multiple long |
41 | //config: filenames into a the data section of a new ar entry. | 39 | //config: filenames into a the data section of a new ar entry. |
42 | //config: | 40 | //config: |
43 | //config:config FEATURE_AR_CREATE | 41 | //config:config FEATURE_AR_CREATE |
44 | //config: bool "Support archive creation" | 42 | //config: bool "Support archive creation" |
45 | //config: default y | 43 | //config: default y |
46 | //config: depends on AR | 44 | //config: depends on AR |
47 | //config: help | 45 | //config: help |
48 | //config: This enables archive creation (-c and -r) with busybox ar. | 46 | //config: This enables archive creation (-c and -r) with busybox ar. |
49 | 47 | ||
50 | //applet:IF_AR(APPLET(ar, BB_DIR_USR_BIN, BB_SUID_DROP)) | 48 | //applet:IF_AR(APPLET(ar, BB_DIR_USR_BIN, BB_SUID_DROP)) |
51 | //kbuild:lib-$(CONFIG_AR) += ar.o | 49 | //kbuild:lib-$(CONFIG_AR) += ar.o |
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 1e3d6e586..f91dd25eb 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -239,11 +239,11 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) | |||
239 | //usage: "\n -f Overwrite" | 239 | //usage: "\n -f Overwrite" |
240 | 240 | ||
241 | //config:config UNCOMPRESS | 241 | //config:config UNCOMPRESS |
242 | //config: bool "uncompress" | 242 | //config: bool "uncompress (7.1 kb)" |
243 | //config: default n # ancient | 243 | //config: default n # ancient |
244 | //config: help | 244 | //config: help |
245 | //config: uncompress is used to decompress archives created by compress. | 245 | //config: uncompress is used to decompress archives created by compress. |
246 | //config: Not much used anymore, replaced by gzip/gunzip. | 246 | //config: Not much used anymore, replaced by gzip/gunzip. |
247 | 247 | ||
248 | //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) | 248 | //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) |
249 | //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o | 249 | //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o |
@@ -314,20 +314,20 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) | |||
314 | //usage: "Decompress to stdout" | 314 | //usage: "Decompress to stdout" |
315 | 315 | ||
316 | //config:config GUNZIP | 316 | //config:config GUNZIP |
317 | //config: bool "gunzip" | 317 | //config: bool "gunzip (12 kb)" |
318 | //config: default y | 318 | //config: default y |
319 | //config: select FEATURE_GZIP_DECOMPRESS | 319 | //config: select FEATURE_GZIP_DECOMPRESS |
320 | //config: help | 320 | //config: help |
321 | //config: gunzip is used to decompress archives created by gzip. | 321 | //config: gunzip is used to decompress archives created by gzip. |
322 | //config: You can use the `-t' option to test the integrity of | 322 | //config: You can use the `-t' option to test the integrity of |
323 | //config: an archive, without decompressing it. | 323 | //config: an archive, without decompressing it. |
324 | //config: | 324 | //config: |
325 | //config:config ZCAT | 325 | //config:config ZCAT |
326 | //config: bool "zcat" | 326 | //config: bool "zcat (25 kb)" |
327 | //config: default y | 327 | //config: default y |
328 | //config: select FEATURE_GZIP_DECOMPRESS | 328 | //config: select FEATURE_GZIP_DECOMPRESS |
329 | //config: help | 329 | //config: help |
330 | //config: Alias to "gunzip -c". | 330 | //config: Alias to "gunzip -c". |
331 | //config: | 331 | //config: |
332 | //config:config FEATURE_GUNZIP_LONG_OPTIONS | 332 | //config:config FEATURE_GUNZIP_LONG_OPTIONS |
333 | //config: bool "Enable long options" | 333 | //config: bool "Enable long options" |
@@ -400,7 +400,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
400 | * Normally, "zcat" is just "gunzip -c". | 400 | * Normally, "zcat" is just "gunzip -c". |
401 | * But if seamless magic is enabled, then we are much more clever. | 401 | * But if seamless magic is enabled, then we are much more clever. |
402 | */ | 402 | */ |
403 | if (ENABLE_ZCAT && applet_name[1] == 'c') | 403 | if (ENABLE_ZCAT && (!ENABLE_GUNZIP || applet_name[1] == 'c')) |
404 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; | 404 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; |
405 | 405 | ||
406 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); | 406 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); |
@@ -427,25 +427,25 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
427 | //usage: "Decompress to stdout" | 427 | //usage: "Decompress to stdout" |
428 | 428 | ||
429 | //config:config BUNZIP2 | 429 | //config:config BUNZIP2 |
430 | //config: bool "bunzip2" | 430 | //config: bool "bunzip2 (8.8 kb)" |
431 | //config: default y | 431 | //config: default y |
432 | //config: select FEATURE_BZIP2_DECOMPRESS | 432 | //config: select FEATURE_BZIP2_DECOMPRESS |
433 | //config: help | 433 | //config: help |
434 | //config: bunzip2 is a compression utility using the Burrows-Wheeler block | 434 | //config: bunzip2 is a compression utility using the Burrows-Wheeler block |
435 | //config: sorting text compression algorithm, and Huffman coding. Compression | 435 | //config: sorting text compression algorithm, and Huffman coding. Compression |
436 | //config: is generally considerably better than that achieved by more | 436 | //config: is generally considerably better than that achieved by more |
437 | //config: conventional LZ77/LZ78-based compressors, and approaches the | 437 | //config: conventional LZ77/LZ78-based compressors, and approaches the |
438 | //config: performance of the PPM family of statistical compressors. | 438 | //config: performance of the PPM family of statistical compressors. |
439 | //config: | 439 | //config: |
440 | //config: Unless you have a specific application which requires bunzip2, you | 440 | //config: Unless you have a specific application which requires bunzip2, you |
441 | //config: should probably say N here. | 441 | //config: should probably say N here. |
442 | //config: | 442 | //config: |
443 | //config:config BZCAT | 443 | //config:config BZCAT |
444 | //config: bool "bzcat" | 444 | //config: bool "bzcat (8.8 kb)" |
445 | //config: default y | 445 | //config: default y |
446 | //config: select FEATURE_BZIP2_DECOMPRESS | 446 | //config: select FEATURE_BZIP2_DECOMPRESS |
447 | //config: help | 447 | //config: help |
448 | //config: Alias to "bunzip2 -c". | 448 | //config: Alias to "bunzip2 -c". |
449 | 449 | ||
450 | //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) | 450 | //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) |
451 | // APPLET_ODDNAME:name main location suid_type help | 451 | // APPLET_ODDNAME:name main location suid_type help |
@@ -456,7 +456,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
456 | { | 456 | { |
457 | getopt32(argv, "cfkvqdt"); | 457 | getopt32(argv, "cfkvqdt"); |
458 | argv += optind; | 458 | argv += optind; |
459 | if (ENABLE_BZCAT && applet_name[2] == 'c') /* bzcat */ | 459 | if (ENABLE_BZCAT && (!ENABLE_BUNZIP2 || applet_name[2] == 'c')) /* bzcat */ |
460 | option_mask32 |= OPT_STDOUT; | 460 | option_mask32 |= OPT_STDOUT; |
461 | 461 | ||
462 | return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2"); | 462 | return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2"); |
@@ -495,43 +495,26 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
495 | //usage: "Decompress to stdout" | 495 | //usage: "Decompress to stdout" |
496 | 496 | ||
497 | //config:config UNLZMA | 497 | //config:config UNLZMA |
498 | //config: bool "unlzma" | 498 | //config: bool "unlzma (8.6 kb)" |
499 | //config: default y | 499 | //config: default y |
500 | //config: help | 500 | //config: help |
501 | //config: unlzma is a compression utility using the Lempel-Ziv-Markov chain | 501 | //config: unlzma is a compression utility using the Lempel-Ziv-Markov chain |
502 | //config: compression algorithm, and range coding. Compression | 502 | //config: compression algorithm, and range coding. Compression |
503 | //config: is generally considerably better than that achieved by the bzip2 | 503 | //config: is generally considerably better than that achieved by the bzip2 |
504 | //config: compressors. | 504 | //config: compressors. |
505 | //config: | ||
506 | //config: The BusyBox unlzma applet is limited to decompression only. | ||
507 | //config: On an x86 system, this applet adds about 4K. | ||
508 | //config: | 505 | //config: |
509 | //config:config LZCAT | 506 | //config:config LZCAT |
510 | //config: bool "lzcat" | 507 | //config: bool "lzcat (8.5 kb)" |
511 | //config: default y | 508 | //config: default y |
512 | //config: help | 509 | //config: help |
513 | //config: unlzma is a compression utility using the Lempel-Ziv-Markov chain | 510 | //config: Alias to "unlzma -c". |
514 | //config: compression algorithm, and range coding. Compression | ||
515 | //config: is generally considerably better than that achieved by the bzip2 | ||
516 | //config: compressors. | ||
517 | //config: | ||
518 | //config: The BusyBox unlzma applet is limited to decompression only. | ||
519 | //config: On an x86 system, this applet adds about 4K. | ||
520 | //config: | 511 | //config: |
521 | //config:config LZMA | 512 | //config:config LZMA |
522 | //config: bool "lzma -d" | 513 | //config: bool "lzma -d" |
523 | //config: default y | 514 | //config: default y |
524 | //config: help | 515 | //config: help |
525 | //config: Enable this option if you want commands like "lzma -d" to work. | 516 | //config: Enable this option if you want commands like "lzma -d" to work. |
526 | //config: IOW: you'll get lzma applet, but it will always require -d option. | 517 | //config: IOW: you'll get lzma applet, but it will always require -d option. |
527 | //config: | ||
528 | //config:config FEATURE_LZMA_FAST | ||
529 | //config: bool "Optimize for speed" | ||
530 | //config: default n | ||
531 | //config: depends on UNLZMA || LZCAT || LZMA | ||
532 | //config: help | ||
533 | //config: This option reduces decompression time by about 25% at the cost of | ||
534 | //config: a 1K bigger binary. | ||
535 | 518 | ||
536 | //applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP)) | 519 | //applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP)) |
537 | // APPLET_ODDNAME:name main location suid_type help | 520 | // APPLET_ODDNAME:name main location suid_type help |
@@ -583,23 +566,23 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
583 | //usage: "Decompress to stdout" | 566 | //usage: "Decompress to stdout" |
584 | 567 | ||
585 | //config:config UNXZ | 568 | //config:config UNXZ |
586 | //config: bool "unxz" | 569 | //config: bool "unxz (13 kb)" |
587 | //config: default y | 570 | //config: default y |
588 | //config: help | 571 | //config: help |
589 | //config: unxz is a unlzma successor. | 572 | //config: unxz is a unlzma successor. |
590 | //config: | 573 | //config: |
591 | //config:config XZCAT | 574 | //config:config XZCAT |
592 | //config: bool "xzcat" | 575 | //config: bool "xzcat (13 kb)" |
593 | //config: default y | 576 | //config: default y |
594 | //config: help | 577 | //config: help |
595 | //config: Alias to "unxz -c". | 578 | //config: Alias to "unxz -c". |
596 | //config: | 579 | //config: |
597 | //config:config XZ | 580 | //config:config XZ |
598 | //config: bool "xz -d" | 581 | //config: bool "xz -d" |
599 | //config: default y | 582 | //config: default y |
600 | //config: help | 583 | //config: help |
601 | //config: Enable this option if you want commands like "xz -d" to work. | 584 | //config: Enable this option if you want commands like "xz -d" to work. |
602 | //config: IOW: you'll get xz applet, but it will always require -d option. | 585 | //config: IOW: you'll get xz applet, but it will always require -d option. |
603 | 586 | ||
604 | //applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP)) | 587 | //applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP)) |
605 | // APPLET_ODDNAME:name main location suid_type help | 588 | // APPLET_ODDNAME:name main location suid_type help |
diff --git a/archival/bzip2.c b/archival/bzip2.c index 8afa43802..0b9c508df 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c | |||
@@ -8,26 +8,26 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | //config:config BZIP2 | 10 | //config:config BZIP2 |
11 | //config: bool "bzip2" | 11 | //config: bool "bzip2 (18 kb)" |
12 | //config: default y | 12 | //config: default y |
13 | //config: help | 13 | //config: help |
14 | //config: bzip2 is a compression utility using the Burrows-Wheeler block | 14 | //config: bzip2 is a compression utility using the Burrows-Wheeler block |
15 | //config: sorting text compression algorithm, and Huffman coding. Compression | 15 | //config: sorting text compression algorithm, and Huffman coding. Compression |
16 | //config: is generally considerably better than that achieved by more | 16 | //config: is generally considerably better than that achieved by more |
17 | //config: conventional LZ77/LZ78-based compressors, and approaches the | 17 | //config: conventional LZ77/LZ78-based compressors, and approaches the |
18 | //config: performance of the PPM family of statistical compressors. | 18 | //config: performance of the PPM family of statistical compressors. |
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: | 22 | //config: |
23 | //config:config FEATURE_BZIP2_DECOMPRESS | 23 | //config:config FEATURE_BZIP2_DECOMPRESS |
24 | //config: bool "Enable decompression" | 24 | //config: bool "Enable decompression" |
25 | //config: default y | 25 | //config: default y |
26 | //config: depends on BZIP2 || BUNZIP2 || BZCAT | 26 | //config: depends on BZIP2 || BUNZIP2 || BZCAT |
27 | //config: help | 27 | //config: help |
28 | //config: Enable -d (--decompress) and -t (--test) options for bzip2. | 28 | //config: Enable -d (--decompress) and -t (--test) options for bzip2. |
29 | //config: This will be automatically selected if bunzip2 or bzcat is | 29 | //config: This will be automatically selected if bunzip2 or bzcat is |
30 | //config: enabled. | 30 | //config: enabled. |
31 | 31 | ||
32 | //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)) |
33 | //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o | 33 | //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o |
diff --git a/archival/cpio.c b/archival/cpio.c index 683f0bb1f..38bab8257 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -15,33 +15,33 @@ | |||
15 | #include "bb_archive.h" | 15 | #include "bb_archive.h" |
16 | 16 | ||
17 | //config:config CPIO | 17 | //config:config CPIO |
18 | //config: bool "cpio" | 18 | //config: bool "cpio (14 kb)" |
19 | //config: default y | 19 | //config: default y |
20 | //config: help | 20 | //config: help |
21 | //config: cpio is an archival utility program used to create, modify, and | 21 | //config: cpio is an archival utility program used to create, modify, and |
22 | //config: extract contents from archives. | 22 | //config: extract contents from archives. |
23 | //config: cpio has 110 bytes of overheads for every stored file. | 23 | //config: cpio has 110 bytes of overheads for every stored file. |
24 | //config: | 24 | //config: |
25 | //config: This implementation of cpio can extract cpio archives created in the | 25 | //config: This implementation of cpio can extract cpio archives created in the |
26 | //config: "newc" or "crc" format. | 26 | //config: "newc" or "crc" format. |
27 | //config: | 27 | //config: |
28 | //config: Unless you have a specific application which requires cpio, you | 28 | //config: Unless you have a specific application which requires cpio, you |
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 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 |
36 | //config: This implementation of cpio can create cpio archives in the "newc" | 36 | //config: This implementation of cpio can create cpio archives in the "newc" |
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 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 |
44 | //config: Passthrough mode. Rarely used. | 44 | //config: Passthrough mode. Rarely used. |
45 | 45 | ||
46 | //applet:IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP)) | 46 | //applet:IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP)) |
47 | //kbuild:lib-$(CONFIG_CPIO) += cpio.o | 47 | //kbuild:lib-$(CONFIG_CPIO) += cpio.o |
diff --git a/archival/dpkg.c b/archival/dpkg.c index da3b0864e..90ad8766c 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -27,15 +27,15 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | //config:config DPKG | 29 | //config:config DPKG |
30 | //config: bool "dpkg" | 30 | //config: bool "dpkg (44 kb)" |
31 | //config: default y | 31 | //config: default y |
32 | //config: select FEATURE_SEAMLESS_GZ | 32 | //config: select FEATURE_SEAMLESS_GZ |
33 | //config: help | 33 | //config: help |
34 | //config: dpkg is a medium-level tool to install, build, remove and manage | 34 | //config: dpkg is a medium-level tool to install, build, remove and manage |
35 | //config: Debian packages. | 35 | //config: Debian packages. |
36 | //config: | 36 | //config: |
37 | //config: This implementation of dpkg has a number of limitations, | 37 | //config: This implementation of dpkg has a number of limitations, |
38 | //config: you should use the official dpkg if possible. | 38 | //config: you should use the official dpkg if possible. |
39 | 39 | ||
40 | //applet:IF_DPKG(APPLET(dpkg, BB_DIR_USR_BIN, BB_SUID_DROP)) | 40 | //applet:IF_DPKG(APPLET(dpkg, BB_DIR_USR_BIN, BB_SUID_DROP)) |
41 | //kbuild:lib-$(CONFIG_DPKG) += dpkg.o | 41 | //kbuild:lib-$(CONFIG_DPKG) += dpkg.o |
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index ebbc7f035..029bc4af1 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
@@ -10,12 +10,12 @@ | |||
10 | //config: default y | 10 | //config: default y |
11 | //config: select FEATURE_SEAMLESS_GZ | 11 | //config: select FEATURE_SEAMLESS_GZ |
12 | //config: help | 12 | //config: help |
13 | //config: dpkg-deb unpacks and provides information about Debian archives. | 13 | //config: dpkg-deb unpacks and provides information about Debian archives. |
14 | //config: | 14 | //config: |
15 | //config: This implementation of dpkg-deb cannot pack archives. | 15 | //config: This implementation of dpkg-deb cannot pack archives. |
16 | //config: | 16 | //config: |
17 | //config: Unless you have a specific application which requires dpkg-deb, | 17 | //config: Unless you have a specific application which requires dpkg-deb, |
18 | //config: say N here. | 18 | //config: say N here. |
19 | 19 | ||
20 | //applet:IF_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, BB_DIR_USR_BIN, BB_SUID_DROP, dpkg_deb)) | 20 | //applet:IF_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, BB_DIR_USR_BIN, BB_SUID_DROP, dpkg_deb)) |
21 | 21 | ||
diff --git a/archival/gzip.c b/archival/gzip.c index c895de426..4cf34ac28 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -38,11 +38,11 @@ aa: 85.1% -- replaced with aa.gz | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | //config:config GZIP | 40 | //config:config GZIP |
41 | //config: bool "gzip" | 41 | //config: bool "gzip (19 kb)" |
42 | //config: default y | 42 | //config: default y |
43 | //config: help | 43 | //config: help |
44 | //config: gzip is used to compress files. | 44 | //config: gzip is used to compress files. |
45 | //config: It's probably the most widely used UNIX compression program. | 45 | //config: It's probably the most widely used UNIX compression program. |
46 | //config: | 46 | //config: |
47 | //config:config FEATURE_GZIP_LONG_OPTIONS | 47 | //config:config FEATURE_GZIP_LONG_OPTIONS |
48 | //config: bool "Enable long options" | 48 | //config: bool "Enable long options" |
@@ -55,30 +55,30 @@ aa: 85.1% -- replaced with aa.gz | |||
55 | //config: range 0 2 | 55 | //config: range 0 2 |
56 | //config: depends on GZIP | 56 | //config: depends on GZIP |
57 | //config: help | 57 | //config: help |
58 | //config: Enable big memory options for gzip. | 58 | //config: Enable big memory options for gzip. |
59 | //config: 0: small buffers, small hash-tables | 59 | //config: 0: small buffers, small hash-tables |
60 | //config: 1: larger buffers, larger hash-tables | 60 | //config: 1: larger buffers, larger hash-tables |
61 | //config: 2: larger buffers, largest hash-tables | 61 | //config: 2: larger buffers, largest hash-tables |
62 | //config: Larger models may give slightly better compression | 62 | //config: Larger models may give slightly better compression |
63 | //config: | 63 | //config: |
64 | //config:config FEATURE_GZIP_LEVELS | 64 | //config:config FEATURE_GZIP_LEVELS |
65 | //config: bool "Enable compression levels" | 65 | //config: bool "Enable compression levels" |
66 | //config: default n | 66 | //config: default n |
67 | //config: depends on GZIP | 67 | //config: depends on GZIP |
68 | //config: help | 68 | //config: help |
69 | //config: Enable support for compression levels 4-9. The default level | 69 | //config: Enable support for compression levels 4-9. The default level |
70 | //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. |
71 | //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 |
72 | //config: is used. | 72 | //config: is used. |
73 | //config: | 73 | //config: |
74 | //config:config FEATURE_GZIP_DECOMPRESS | 74 | //config:config FEATURE_GZIP_DECOMPRESS |
75 | //config: bool "Enable decompression" | 75 | //config: bool "Enable decompression" |
76 | //config: default y | 76 | //config: default y |
77 | //config: depends on GZIP || GUNZIP || ZCAT | 77 | //config: depends on GZIP || GUNZIP || ZCAT |
78 | //config: help | 78 | //config: help |
79 | //config: Enable -d (--decompress) and -t (--test) options for gzip. | 79 | //config: Enable -d (--decompress) and -t (--test) options for gzip. |
80 | //config: This will be automatically selected if gunzip or zcat is | 80 | //config: This will be automatically selected if gunzip or zcat is |
81 | //config: enabled. | 81 | //config: enabled. |
82 | 82 | ||
83 | //applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP)) | 83 | //applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP)) |
84 | //kbuild:lib-$(CONFIG_GZIP) += gzip.o | 84 | //kbuild:lib-$(CONFIG_GZIP) += gzip.o |
diff --git a/archival/lzop.c b/archival/lzop.c index 6ef82b749..df18ff170 100644 --- a/archival/lzop.c +++ b/archival/lzop.c | |||
@@ -26,31 +26,31 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | //config:config LZOP | 28 | //config:config LZOP |
29 | //config: bool "lzop" | 29 | //config: bool "lzop (13 kb)" |
30 | //config: default y | 30 | //config: default y |
31 | //config: help | 31 | //config: help |
32 | //config: Lzop compression/decompresion. | 32 | //config: Lzop compression/decompresion. |
33 | //config: | 33 | //config: |
34 | //config:config UNLZOP | 34 | //config:config UNLZOP |
35 | //config: bool "unlzop" | 35 | //config: bool "unlzop (13 kb)" |
36 | //config: default n # INCOMPAT: upstream lzop does not provide such tool | 36 | //config: default n # INCOMPAT: upstream lzop does not provide such tool |
37 | //config: help | 37 | //config: help |
38 | //config: Lzop decompresion. | 38 | //config: Lzop decompresion. |
39 | //config: | 39 | //config: |
40 | //config:config LZOPCAT | 40 | //config:config LZOPCAT |
41 | //config: bool "lzopcat" | 41 | //config: bool "lzopcat (13 kb)" |
42 | //config: default n # INCOMPAT: upstream lzop does not provide such tool | 42 | //config: default n # INCOMPAT: upstream lzop does not provide such tool |
43 | //config: help | 43 | //config: help |
44 | //config: Alias to "unlzop -c". | 44 | //config: Alias to "lzop -dc". |
45 | //config: | 45 | //config: |
46 | //config:config LZOP_COMPR_HIGH | 46 | //config:config LZOP_COMPR_HIGH |
47 | //config: bool "lzop compression levels 7,8,9 (not very useful)" | 47 | //config: bool "lzop compression levels 7,8,9 (not very useful)" |
48 | //config: default n | 48 | //config: default n |
49 | //config: depends on LZOP || UNLZOP || LZOPCAT | 49 | //config: depends on LZOP || UNLZOP || LZOPCAT |
50 | //config: help | 50 | //config: help |
51 | //config: High levels (7,8,9) of lzop compression. These levels | 51 | //config: High levels (7,8,9) of lzop compression. These levels |
52 | //config: are actually slower than gzip at equivalent compression ratios | 52 | //config: are actually slower than gzip at equivalent compression ratios |
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_ODDNAME:name main location suid_type help | 56 | // APPLET_ODDNAME:name main location suid_type help |
diff --git a/archival/rpm.c b/archival/rpm.c index 83160f975..98039d499 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -8,10 +8,10 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | //config:config RPM | 10 | //config:config RPM |
11 | //config: bool "rpm" | 11 | //config: bool "rpm (33 kb)" |
12 | //config: default y | 12 | //config: default y |
13 | //config: help | 13 | //config: help |
14 | //config: Mini RPM applet - queries and extracts RPM packages. | 14 | //config: Mini RPM applet - queries and extracts RPM packages. |
15 | 15 | ||
16 | //applet:IF_RPM(APPLET(rpm, BB_DIR_BIN, BB_SUID_DROP)) | 16 | //applet:IF_RPM(APPLET(rpm, BB_DIR_BIN, BB_SUID_DROP)) |
17 | //kbuild:lib-$(CONFIG_RPM) += rpm.o | 17 | //kbuild:lib-$(CONFIG_RPM) += rpm.o |
diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index 7057570f5..3e4a6a249 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c | |||
@@ -8,10 +8,10 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | //config:config RPM2CPIO | 10 | //config:config RPM2CPIO |
11 | //config: bool "rpm2cpio" | 11 | //config: bool "rpm2cpio (20 kb)" |
12 | //config: default y | 12 | //config: default y |
13 | //config: help | 13 | //config: help |
14 | //config: Converts a RPM file into a CPIO archive. | 14 | //config: Converts a RPM file into a CPIO archive. |
15 | 15 | ||
16 | //applet:IF_RPM2CPIO(APPLET(rpm2cpio, BB_DIR_USR_BIN, BB_SUID_DROP)) | 16 | //applet:IF_RPM2CPIO(APPLET(rpm2cpio, BB_DIR_USR_BIN, BB_SUID_DROP)) |
17 | //kbuild:lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o | 17 | //kbuild:lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o |
diff --git a/archival/tar.c b/archival/tar.c index c11b735d5..4d1db4934 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -42,12 +42,12 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | //config:config TAR | 44 | //config:config TAR |
45 | //config: bool "tar" | 45 | //config: bool "tar (40 kb)" |
46 | //config: default y | 46 | //config: default y |
47 | //config: help | 47 | //config: help |
48 | //config: tar is an archiving program. It's commonly used with gzip to | 48 | //config: tar is an archiving program. It's commonly used with gzip to |
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 | 52 | //config:config FEATURE_TAR_LONG_OPTIONS |
53 | //config: bool "Enable long options" | 53 | //config: bool "Enable long options" |
@@ -64,35 +64,35 @@ | |||
64 | //config: default y | 64 | //config: default y |
65 | //config: depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ) | 65 | //config: depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ) |
66 | //config: help | 66 | //config: help |
67 | //config: With this option tar can automatically detect compressed | 67 | //config: With this option tar can automatically detect compressed |
68 | //config: tarballs. Currently it works only on files (not pipes etc). | 68 | //config: tarballs. Currently it works only on files (not pipes etc). |
69 | //config: | 69 | //config: |
70 | //config:config FEATURE_TAR_FROM | 70 | //config:config FEATURE_TAR_FROM |
71 | //config: bool "Enable -X (exclude from) and -T (include from) options)" | 71 | //config: bool "Enable -X (exclude from) and -T (include from) options)" |
72 | //config: default y | 72 | //config: default y |
73 | //config: depends on TAR | 73 | //config: depends on TAR |
74 | //config: help | 74 | //config: help |
75 | //config: If you enable this option you'll be able to specify | 75 | //config: If you enable this option you'll be able to specify |
76 | //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. |
77 | //config: | 77 | //config: |
78 | //config:config FEATURE_TAR_OLDGNU_COMPATIBILITY | 78 | //config:config FEATURE_TAR_OLDGNU_COMPATIBILITY |
79 | //config: bool "Support old tar header format" | 79 | //config: bool "Support old tar header format" |
80 | //config: default y | 80 | //config: default y |
81 | //config: depends on TAR || DPKG | 81 | //config: depends on TAR || DPKG |
82 | //config: help | 82 | //config: help |
83 | //config: This option is required to unpack archives created in | 83 | //config: This option is required to unpack archives created in |
84 | //config: the old GNU format; help to kill this old format by | 84 | //config: the old GNU format; help to kill this old format by |
85 | //config: repacking your ancient archives with the new format. | 85 | //config: repacking your ancient archives with the new format. |
86 | //config: | 86 | //config: |
87 | //config:config FEATURE_TAR_OLDSUN_COMPATIBILITY | 87 | //config:config FEATURE_TAR_OLDSUN_COMPATIBILITY |
88 | //config: bool "Enable untarring of tarballs with checksums produced by buggy Sun tar" | 88 | //config: bool "Enable untarring of tarballs with checksums produced by buggy Sun tar" |
89 | //config: default y | 89 | //config: default y |
90 | //config: depends on TAR || DPKG | 90 | //config: depends on TAR || DPKG |
91 | //config: help | 91 | //config: help |
92 | //config: This option is required to unpack archives created by some old | 92 | //config: This option is required to unpack archives created by some old |
93 | //config: version of Sun's tar (it was calculating checksum using signed | 93 | //config: version of Sun's tar (it was calculating checksum using signed |
94 | //config: arithmetic). It is said to be fixed in newer Sun tar, but "old" | 94 | //config: arithmetic). It is said to be fixed in newer Sun tar, but "old" |
95 | //config: tarballs still exist. | 95 | //config: tarballs still exist. |
96 | //config: | 96 | //config: |
97 | //config:config FEATURE_TAR_GNU_EXTENSIONS | 97 | //config:config FEATURE_TAR_GNU_EXTENSIONS |
98 | //config: bool "Support GNU tar extensions (long filenames)" | 98 | //config: bool "Support GNU tar extensions (long filenames)" |
@@ -104,18 +104,18 @@ | |||
104 | //config: default y | 104 | //config: default y |
105 | //config: depends on TAR && FEATURE_TAR_LONG_OPTIONS | 105 | //config: depends on TAR && FEATURE_TAR_LONG_OPTIONS |
106 | //config: help | 106 | //config: help |
107 | //config: If you enable this option you'll be able to instruct tar to send | 107 | //config: If you enable this option you'll be able to instruct tar to send |
108 | //config: the contents of each extracted file to the standard input of an | 108 | //config: the contents of each extracted file to the standard input of an |
109 | //config: external program. | 109 | //config: external program. |
110 | //config: | 110 | //config: |
111 | //config:config FEATURE_TAR_UNAME_GNAME | 111 | //config:config FEATURE_TAR_UNAME_GNAME |
112 | //config: bool "Enable use of user and group names" | 112 | //config: bool "Enable use of user and group names" |
113 | //config: default y | 113 | //config: default y |
114 | //config: depends on TAR | 114 | //config: depends on TAR |
115 | //config: help | 115 | //config: help |
116 | //config: Enable 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 |
117 | //config: listings (-t) and preserving permissions when unpacking (-p). | 117 | //config: listings (-t) and preserving permissions when unpacking (-p). |
118 | //config: +200 bytes. | 118 | //config: +200 bytes. |
119 | //config: | 119 | //config: |
120 | //config:config FEATURE_TAR_NOPRESERVE_TIME | 120 | //config:config FEATURE_TAR_NOPRESERVE_TIME |
121 | //config: bool "Enable -m (do not preserve time) GNU option" | 121 | //config: bool "Enable -m (do not preserve time) GNU option" |
@@ -127,8 +127,8 @@ | |||
127 | //config: default n | 127 | //config: default n |
128 | //config: depends on TAR && SELINUX | 128 | //config: depends on TAR && SELINUX |
129 | //config: help | 129 | //config: help |
130 | //config: With this option busybox supports restoring SELinux labels | 130 | //config: With this option busybox supports restoring SELinux labels |
131 | //config: when extracting files from tar archives. | 131 | //config: when extracting files from tar archives. |
132 | 132 | ||
133 | //applet:IF_TAR(APPLET(tar, BB_DIR_BIN, BB_SUID_DROP)) | 133 | //applet:IF_TAR(APPLET(tar, BB_DIR_BIN, BB_SUID_DROP)) |
134 | //kbuild:lib-$(CONFIG_TAR) += tar.o | 134 | //kbuild:lib-$(CONFIG_TAR) += tar.o |
diff --git a/archival/unzip.c b/archival/unzip.c index 8dfc4e678..4c4feda82 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -17,23 +17,23 @@ | |||
17 | * Zip64 + other methods | 17 | * Zip64 + other methods |
18 | */ | 18 | */ |
19 | //config:config UNZIP | 19 | //config:config UNZIP |
20 | //config: bool "unzip" | 20 | //config: bool "unzip (24 kb)" |
21 | //config: default y | 21 | //config: default y |
22 | //config: help | 22 | //config: help |
23 | //config: unzip will list or extract files from a ZIP archive, | 23 | //config: unzip will list or extract files from a ZIP archive, |
24 | //config: commonly found on DOS/WIN systems. The default behavior | 24 | //config: commonly found on DOS/WIN systems. The default behavior |
25 | //config: (with no options) is to extract the archive into the | 25 | //config: (with no options) is to extract the archive into the |
26 | //config: current directory. | 26 | //config: current directory. |
27 | //config: | 27 | //config: |
28 | //config:config FEATURE_UNZIP_CDF | 28 | //config:config FEATURE_UNZIP_CDF |
29 | //config: bool "Read and use Central Directory data" | 29 | //config: bool "Read and use Central Directory data" |
30 | //config: default y | 30 | //config: default y |
31 | //config: depends on UNZIP | 31 | //config: depends on UNZIP |
32 | //config: help | 32 | //config: help |
33 | //config: If you know that you only need to deal with simple | 33 | //config: If you know that you only need to deal with simple |
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: | 37 | //config: |
38 | //config:config FEATURE_UNZIP_BZIP2 | 38 | //config:config FEATURE_UNZIP_BZIP2 |
39 | //config: bool "Support compression method 12 (bzip2)" | 39 | //config: bool "Support compression method 12 (bzip2)" |
@@ -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" |
@@ -320,6 +321,12 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf) | |||
320 | }; | 321 | }; |
321 | #endif | 322 | #endif |
322 | 323 | ||
324 | static void die_if_bad_fnamesize(unsigned sz) | ||
325 | { | ||
326 | if (sz > 0xfff) /* more than 4k?! no funny business please */ | ||
327 | bb_error_msg_and_die("bad archive"); | ||
328 | } | ||
329 | |||
323 | static void unzip_skip(off_t skip) | 330 | static void unzip_skip(off_t skip) |
324 | { | 331 | { |
325 | if (skip != 0) | 332 | if (skip != 0) |
@@ -337,6 +344,39 @@ static void unzip_create_leading_dirs(const char *fn) | |||
337 | free(name); | 344 | free(name); |
338 | } | 345 | } |
339 | 346 | ||
347 | #if ENABLE_FEATURE_UNZIP_CDF | ||
348 | static void unzip_extract_symlink(zip_header_t *zip, const char *dst_fn) | ||
349 | { | ||
350 | char *target; | ||
351 | |||
352 | die_if_bad_fnamesize(zip->fmt.ucmpsize); | ||
353 | |||
354 | if (zip->fmt.method == 0) { | ||
355 | /* Method 0 - stored (not compressed) */ | ||
356 | target = xzalloc(zip->fmt.ucmpsize + 1); | ||
357 | xread(zip_fd, target, zip->fmt.ucmpsize); | ||
358 | } else { | ||
359 | #if 1 | ||
360 | bb_error_msg_and_die("compressed symlink is not supported"); | ||
361 | #else | ||
362 | transformer_state_t xstate; | ||
363 | init_transformer_state(&xstate); | ||
364 | xstate.mem_output_size_max = zip->fmt.ucmpsize; | ||
365 | /* ...unpack... */ | ||
366 | if (!xstate.mem_output_buf) | ||
367 | WTF(); | ||
368 | target = xstate.mem_output_buf; | ||
369 | target = xrealloc(target, xstate.mem_output_size + 1); | ||
370 | target[xstate.mem_output_size] = '\0'; | ||
371 | #endif | ||
372 | } | ||
373 | //TODO: libbb candidate | ||
374 | if (symlink(target, dst_fn)) | ||
375 | bb_perror_msg_and_die("can't create symlink '%s'", dst_fn); | ||
376 | free(target); | ||
377 | } | ||
378 | #endif | ||
379 | |||
340 | static void unzip_extract(zip_header_t *zip, int dst_fd) | 380 | static void unzip_extract(zip_header_t *zip, int dst_fd) |
341 | { | 381 | { |
342 | transformer_state_t xstate; | 382 | transformer_state_t xstate; |
@@ -349,12 +389,6 @@ static void unzip_extract(zip_header_t *zip, int dst_fd) | |||
349 | return; | 389 | return; |
350 | } | 390 | } |
351 | 391 | ||
352 | // NB: to support symlinks, need to extract symlink target. A-la: | ||
353 | // xstate.mem_output_size_max = zip->fmt.ucmpsize; | ||
354 | // ...unpack... | ||
355 | // if (xstate.mem_output_buf) { success, xstate.mem_output_size is the size } | ||
356 | // Although archives I've seen have fmt.method == 0 for symlinks. | ||
357 | |||
358 | init_transformer_state(&xstate); | 392 | init_transformer_state(&xstate); |
359 | xstate.bytes_in = zip->fmt.cmpsize; | 393 | xstate.bytes_in = zip->fmt.cmpsize; |
360 | xstate.src_fd = zip_fd; | 394 | xstate.src_fd = zip_fd; |
@@ -414,16 +448,32 @@ static void my_fgets80(char *buf80) | |||
414 | } | 448 | } |
415 | } | 449 | } |
416 | 450 | ||
451 | static int get_lstat_mode(const char *dst_fn) | ||
452 | { | ||
453 | struct stat stat_buf; | ||
454 | if (lstat(dst_fn, &stat_buf) == -1) { | ||
455 | if (errno != ENOENT) { | ||
456 | bb_perror_msg_and_die("can't stat '%s'", dst_fn); | ||
457 | } | ||
458 | /* File does not exist */ | ||
459 | return -1; | ||
460 | } | ||
461 | return stat_buf.st_mode; | ||
462 | } | ||
463 | |||
417 | int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 464 | int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
418 | int unzip_main(int argc, char **argv) | 465 | int unzip_main(int argc, char **argv) |
419 | { | 466 | { |
420 | enum { O_PROMPT, O_NEVER, O_ALWAYS }; | 467 | enum { |
421 | 468 | OPT_l = (1 << 0), | |
469 | OPT_x = (1 << 1), | ||
470 | OPT_j = (1 << 2), | ||
471 | }; | ||
472 | unsigned opts; | ||
422 | smallint quiet = 0; | 473 | smallint quiet = 0; |
423 | IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0; | 474 | IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0; |
424 | smallint listing = 0; | 475 | enum { O_PROMPT, O_NEVER, O_ALWAYS }; |
425 | smallint overwrite = O_PROMPT; | 476 | smallint overwrite = O_PROMPT; |
426 | smallint x_opt_seen; | ||
427 | uint32_t cdf_offset; | 477 | uint32_t cdf_offset; |
428 | unsigned long total_usize; | 478 | unsigned long total_usize; |
429 | unsigned long total_size; | 479 | unsigned long total_size; |
@@ -434,9 +484,8 @@ int unzip_main(int argc, char **argv) | |||
434 | llist_t *zaccept = NULL; | 484 | llist_t *zaccept = NULL; |
435 | llist_t *zreject = NULL; | 485 | llist_t *zreject = NULL; |
436 | char *base_dir = NULL; | 486 | char *base_dir = NULL; |
437 | int i, opt; | 487 | int i; |
438 | char key_buf[80]; /* must match size used by my_fgets80 */ | 488 | char key_buf[80]; /* must match size used by my_fgets80 */ |
439 | struct stat stat_buf; | ||
440 | 489 | ||
441 | /* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP: | 490 | /* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP: |
442 | * | 491 | * |
@@ -479,16 +528,16 @@ int unzip_main(int argc, char **argv) | |||
479 | * 204372 1 file | 528 | * 204372 1 file |
480 | */ | 529 | */ |
481 | 530 | ||
482 | x_opt_seen = 0; | 531 | opts = 0; |
483 | /* '-' makes getopt return 1 for non-options */ | 532 | /* '-' makes getopt return 1 for non-options */ |
484 | while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { | 533 | while ((i = getopt(argc, argv, "-d:lnopqxjv")) != -1) { |
485 | switch (opt) { | 534 | switch (i) { |
486 | case 'd': /* Extract to base directory */ | 535 | case 'd': /* Extract to base directory */ |
487 | base_dir = optarg; | 536 | base_dir = optarg; |
488 | break; | 537 | break; |
489 | 538 | ||
490 | case 'l': /* List */ | 539 | case 'l': /* List */ |
491 | listing = 1; | 540 | opts |= OPT_l; |
492 | break; | 541 | break; |
493 | 542 | ||
494 | case 'n': /* Never overwrite existing files */ | 543 | case 'n': /* Never overwrite existing files */ |
@@ -508,11 +557,15 @@ int unzip_main(int argc, char **argv) | |||
508 | 557 | ||
509 | case 'v': /* Verbose list */ | 558 | case 'v': /* Verbose list */ |
510 | IF_FEATURE_UNZIP_CDF(verbose++;) | 559 | IF_FEATURE_UNZIP_CDF(verbose++;) |
511 | listing = 1; | 560 | opts |= OPT_l; |
512 | break; | 561 | break; |
513 | 562 | ||
514 | case 'x': | 563 | case 'x': |
515 | x_opt_seen = 1; | 564 | opts |= OPT_x; |
565 | break; | ||
566 | |||
567 | case 'j': | ||
568 | opts |= OPT_j; | ||
516 | break; | 569 | break; |
517 | 570 | ||
518 | case 1: | 571 | case 1: |
@@ -521,7 +574,7 @@ int unzip_main(int argc, char **argv) | |||
521 | /* +5: space for ".zip" and NUL */ | 574 | /* +5: space for ".zip" and NUL */ |
522 | src_fn = xmalloc(strlen(optarg) + 5); | 575 | src_fn = xmalloc(strlen(optarg) + 5); |
523 | strcpy(src_fn, optarg); | 576 | strcpy(src_fn, optarg); |
524 | } else if (!x_opt_seen) { | 577 | } else if (!(opts & OPT_x)) { |
525 | /* Include files */ | 578 | /* Include files */ |
526 | llist_add_to(&zaccept, optarg); | 579 | llist_add_to(&zaccept, optarg); |
527 | } else { | 580 | } else { |
@@ -589,7 +642,7 @@ int unzip_main(int argc, char **argv) | |||
589 | if (quiet <= 1) { /* not -qq */ | 642 | if (quiet <= 1) { /* not -qq */ |
590 | if (quiet == 0) | 643 | if (quiet == 0) |
591 | printf("Archive: %s\n", src_fn); | 644 | printf("Archive: %s\n", src_fn); |
592 | if (listing) { | 645 | if (opts & OPT_l) { |
593 | puts(verbose ? | 646 | puts(verbose ? |
594 | " Length Method Size Cmpr Date Time CRC-32 Name\n" | 647 | " Length Method Size Cmpr Date Time CRC-32 Name\n" |
595 | "-------- ------ ------- ---- ---------- ----- -------- ----" | 648 | "-------- ------ ------- ---- ---------- ----- -------- ----" |
@@ -722,7 +775,6 @@ int unzip_main(int argc, char **argv) | |||
722 | if ((cdf.fmt.version_made_by >> 8) == 3) { | 775 | if ((cdf.fmt.version_made_by >> 8) == 3) { |
723 | /* This archive is created on Unix */ | 776 | /* This archive is created on Unix */ |
724 | dir_mode = file_mode = (cdf.fmt.external_attributes >> 16); | 777 | dir_mode = file_mode = (cdf.fmt.external_attributes >> 16); |
725 | //TODO: if (S_ISLNK(file_mode)) this is a symlink | ||
726 | } | 778 | } |
727 | } | 779 | } |
728 | #endif | 780 | #endif |
@@ -740,15 +792,22 @@ int unzip_main(int argc, char **argv) | |||
740 | 792 | ||
741 | /* Read filename */ | 793 | /* Read filename */ |
742 | free(dst_fn); | 794 | free(dst_fn); |
795 | die_if_bad_fnamesize(zip.fmt.filename_len); | ||
743 | dst_fn = xzalloc(zip.fmt.filename_len + 1); | 796 | dst_fn = xzalloc(zip.fmt.filename_len + 1); |
744 | xread(zip_fd, dst_fn, zip.fmt.filename_len); | 797 | xread(zip_fd, dst_fn, zip.fmt.filename_len); |
745 | |||
746 | /* Skip extra header bytes */ | 798 | /* Skip extra header bytes */ |
747 | unzip_skip(zip.fmt.extra_len); | 799 | unzip_skip(zip.fmt.extra_len); |
748 | 800 | ||
749 | /* Guard against "/abspath", "/../" and similar attacks */ | 801 | /* Guard against "/abspath", "/../" and similar attacks */ |
750 | overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); | 802 | overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); |
751 | 803 | ||
804 | if (opts & OPT_j) /* Strip paths? */ | ||
805 | overlapping_strcpy(dst_fn, bb_basename(dst_fn)); | ||
806 | |||
807 | /* Did this strip everything ("DIR/" case)? Then skip */ | ||
808 | if (!dst_fn[0]) | ||
809 | goto skip_cmpsize; | ||
810 | |||
752 | /* Filter zip entries */ | 811 | /* Filter zip entries */ |
753 | if (find_list_entry(zreject, dst_fn) | 812 | if (find_list_entry(zreject, dst_fn) |
754 | || (zaccept && !find_list_entry(zaccept, dst_fn)) | 813 | || (zaccept && !find_list_entry(zaccept, dst_fn)) |
@@ -756,7 +815,7 @@ int unzip_main(int argc, char **argv) | |||
756 | goto skip_cmpsize; | 815 | goto skip_cmpsize; |
757 | } | 816 | } |
758 | 817 | ||
759 | if (listing) { | 818 | if (opts & OPT_l) { |
760 | /* List entry */ | 819 | /* List entry */ |
761 | char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; | 820 | char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; |
762 | sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", | 821 | sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", |
@@ -814,11 +873,11 @@ int unzip_main(int argc, char **argv) | |||
814 | goto do_extract; | 873 | goto do_extract; |
815 | } | 874 | } |
816 | if (last_char_is(dst_fn, '/')) { | 875 | if (last_char_is(dst_fn, '/')) { |
876 | int mode; | ||
877 | |||
817 | /* Extract directory */ | 878 | /* Extract directory */ |
818 | if (stat(dst_fn, &stat_buf) == -1) { | 879 | mode = get_lstat_mode(dst_fn); |
819 | if (errno != ENOENT) { | 880 | if (mode == -1) { /* ENOENT */ |
820 | bb_perror_msg_and_die("can't stat '%s'", dst_fn); | ||
821 | } | ||
822 | if (!quiet) { | 881 | if (!quiet) { |
823 | printf(" creating: %s\n", dst_fn); | 882 | printf(" creating: %s\n", dst_fn); |
824 | } | 883 | } |
@@ -827,7 +886,7 @@ int unzip_main(int argc, char **argv) | |||
827 | xfunc_die(); | 886 | xfunc_die(); |
828 | } | 887 | } |
829 | } else { | 888 | } else { |
830 | if (!S_ISDIR(stat_buf.st_mode)) { | 889 | if (!S_ISDIR(mode)) { |
831 | bb_error_msg_and_die("'%s' exists but is not a %s", | 890 | bb_error_msg_and_die("'%s' exists but is not a %s", |
832 | dst_fn, "directory"); | 891 | dst_fn, "directory"); |
833 | } | 892 | } |
@@ -835,29 +894,33 @@ int unzip_main(int argc, char **argv) | |||
835 | goto skip_cmpsize; | 894 | goto skip_cmpsize; |
836 | } | 895 | } |
837 | check_file: | 896 | check_file: |
838 | /* Extract file */ | 897 | /* Does target file already exist? */ |
839 | if (stat(dst_fn, &stat_buf) == -1) { | 898 | { |
840 | /* File does not exist */ | 899 | int mode = get_lstat_mode(dst_fn); |
841 | if (errno != ENOENT) { | 900 | if (mode == -1) { |
842 | bb_perror_msg_and_die("can't stat '%s'", dst_fn); | 901 | /* ENOENT: does not exist */ |
902 | goto do_open_and_extract; | ||
843 | } | 903 | } |
844 | goto do_open_and_extract; | 904 | if (overwrite == O_NEVER) { |
845 | } | 905 | goto skip_cmpsize; |
846 | /* File already exists */ | 906 | } |
847 | if (overwrite == O_NEVER) { | 907 | if (!S_ISREG(mode)) { |
848 | goto skip_cmpsize; | 908 | fishy: |
849 | } | 909 | bb_error_msg_and_die("'%s' exists but is not a %s", |
850 | if (!S_ISREG(stat_buf.st_mode)) { | 910 | dst_fn, "regular file"); |
851 | /* File is not regular file */ | 911 | } |
852 | bb_error_msg_and_die("'%s' exists but is not a %s", | 912 | if (overwrite == O_ALWAYS) { |
853 | dst_fn, "regular file"); | 913 | goto do_open_and_extract; |
914 | } | ||
915 | printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); | ||
916 | my_fgets80(key_buf); | ||
917 | /* User input could take a long time. Is it still a regular file? */ | ||
918 | mode = get_lstat_mode(dst_fn); | ||
919 | if (!S_ISREG(mode)) | ||
920 | goto fishy; | ||
854 | } | 921 | } |
855 | /* File is regular file */ | ||
856 | if (overwrite == O_ALWAYS) | ||
857 | goto do_open_and_extract; | ||
858 | printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); | ||
859 | my_fgets80(key_buf); | ||
860 | 922 | ||
923 | /* Extract (or skip) it */ | ||
861 | switch (key_buf[0]) { | 924 | switch (key_buf[0]) { |
862 | case 'A': | 925 | case 'A': |
863 | overwrite = O_ALWAYS; | 926 | overwrite = O_ALWAYS; |
@@ -865,9 +928,15 @@ int unzip_main(int argc, char **argv) | |||
865 | do_open_and_extract: | 928 | do_open_and_extract: |
866 | unzip_create_leading_dirs(dst_fn); | 929 | unzip_create_leading_dirs(dst_fn); |
867 | #if ENABLE_FEATURE_UNZIP_CDF | 930 | #if ENABLE_FEATURE_UNZIP_CDF |
868 | dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); | 931 | dst_fd = -1; |
932 | if (!S_ISLNK(file_mode)) { | ||
933 | dst_fd = xopen3(dst_fn, | ||
934 | O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, | ||
935 | file_mode); | ||
936 | } | ||
869 | #else | 937 | #else |
870 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); | 938 | /* O_NOFOLLOW defends against symlink attacks */ |
939 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW); | ||
871 | #endif | 940 | #endif |
872 | do_extract: | 941 | do_extract: |
873 | if (!quiet) { | 942 | if (!quiet) { |
@@ -875,10 +944,18 @@ int unzip_main(int argc, char **argv) | |||
875 | ? " extracting: %s\n" | 944 | ? " extracting: %s\n" |
876 | : */ " inflating: %s\n", dst_fn); | 945 | : */ " inflating: %s\n", dst_fn); |
877 | } | 946 | } |
878 | unzip_extract(&zip, dst_fd); | 947 | #if ENABLE_FEATURE_UNZIP_CDF |
879 | if (dst_fd != STDOUT_FILENO) { | 948 | if (S_ISLNK(file_mode)) { |
880 | /* closing STDOUT is potentially bad for future business */ | 949 | if (dst_fd != STDOUT_FILENO) /* not -p? */ |
881 | close(dst_fd); | 950 | unzip_extract_symlink(&zip, dst_fn); |
951 | } else | ||
952 | #endif | ||
953 | { | ||
954 | unzip_extract(&zip, dst_fd); | ||
955 | if (dst_fd != STDOUT_FILENO) { | ||
956 | /* closing STDOUT is potentially bad for future business */ | ||
957 | close(dst_fd); | ||
958 | } | ||
882 | } | 959 | } |
883 | break; | 960 | break; |
884 | 961 | ||
@@ -906,7 +983,7 @@ int unzip_main(int argc, char **argv) | |||
906 | total_entries++; | 983 | total_entries++; |
907 | } | 984 | } |
908 | 985 | ||
909 | if (listing && quiet <= 1) { | 986 | if ((opts & OPT_l) && quiet <= 1) { |
910 | if (!verbose) { | 987 | if (!verbose) { |
911 | // " Length Date Time Name\n" | 988 | // " Length Date Time Name\n" |
912 | // "--------- ---------- ----- ----" | 989 | // "--------- ---------- ----- ----" |