aboutsummaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-07-24 11:40:28 +0100
committerRon Yorston <rmy@pobox.com>2017-07-24 12:03:28 +0100
commit60411636073cdc08e8005f0de00098e6dd00eaf5 (patch)
tree58673b64af1e663280be81f798c8f66ce116d1dd /archival
parenteeceafbc5c4caf513c6d92b7d71ecb0ccd89a3f8 (diff)
parentb72f1ef17b97802d33f0ac522f64bea0f65442c5 (diff)
downloadbusybox-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.src8
-rw-r--r--archival/ar.c24
-rw-r--r--archival/bbunzip.c89
-rw-r--r--archival/bzip2.c22
-rw-r--r--archival/cpio.c22
-rw-r--r--archival/dpkg.c10
-rw-r--r--archival/dpkg_deb.c8
-rw-r--r--archival/gzip.c30
-rw-r--r--archival/lzop.c18
-rw-r--r--archival/rpm.c4
-rw-r--r--archival/rpm2cpio.c4
-rw-r--r--archival/tar.c46
-rw-r--r--archival/unzip.c205
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
28INSERT 28INSERT
29 29
30config 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
30endmenu 38endmenu
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
324static 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
323static void unzip_skip(off_t skip) 330static 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
348static 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
340static void unzip_extract(zip_header_t *zip, int dst_fd) 380static 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
451static 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
417int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 464int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
418int unzip_main(int argc, char **argv) 465int 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 // "--------- ---------- ----- ----"