aboutsummaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
Diffstat (limited to 'archival')
-rw-r--r--archival/Config.src4
-rw-r--r--archival/bbunzip.c72
-rw-r--r--archival/bzip2.c2
-rw-r--r--archival/cpio.c1
-rw-r--r--archival/gzip.c2
-rw-r--r--archival/libarchive/Kbuild.src21
-rw-r--r--archival/libarchive/data_extract_all.c8
-rw-r--r--archival/libarchive/data_extract_to_command.c8
-rw-r--r--archival/libarchive/decompress_bunzip2.c18
-rw-r--r--archival/libarchive/decompress_gunzip.c (renamed from archival/libarchive/decompress_unzip.c)69
-rw-r--r--archival/libarchive/decompress_uncompress.c15
-rw-r--r--archival/libarchive/decompress_unlzma.c2
-rw-r--r--archival/libarchive/decompress_unxz.c12
-rw-r--r--archival/libarchive/get_header_tar.c100
-rw-r--r--archival/libarchive/get_header_tar_bz2.c2
-rw-r--r--archival/libarchive/get_header_tar_gz.c17
-rw-r--r--archival/libarchive/get_header_tar_lzma.c2
-rw-r--r--archival/libarchive/open_transformer.c193
-rw-r--r--archival/lzop.c13
-rw-r--r--archival/rpm.c2
-rw-r--r--archival/rpm2cpio.c54
-rw-r--r--archival/tar.c103
-rw-r--r--archival/unzip.c10
23 files changed, 393 insertions, 337 deletions
diff --git a/archival/Config.src b/archival/Config.src
index f1d6d3511..13c33c795 100644
--- a/archival/Config.src
+++ b/archival/Config.src
@@ -32,10 +32,10 @@ config FEATURE_SEAMLESS_GZ
32 Make tar, rpm, modprobe etc understand .gz data. 32 Make tar, rpm, modprobe etc understand .gz data.
33 33
34config FEATURE_SEAMLESS_Z 34config FEATURE_SEAMLESS_Z
35 bool "Make tar and gunzip understand .Z data" 35 bool "tar, rpm, modprobe etc understand .Z data"
36 default n 36 default n
37 help 37 help
38 Make tar and gunzip understand .Z data. 38 Make tar, rpm, modprobe etc understand .Z data.
39 39
40config AR 40config AR
41 bool "ar" 41 bool "ar"
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index c96e5396a..66a046052 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -33,7 +33,7 @@ char* FAST_FUNC append_ext(char *filename, const char *expected_ext)
33} 33}
34 34
35int FAST_FUNC bbunpack(char **argv, 35int FAST_FUNC bbunpack(char **argv,
36 IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(unpack_info_t *info), 36 IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux),
37 char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), 37 char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext),
38 const char *expected_ext 38 const char *expected_ext
39) 39)
@@ -42,7 +42,7 @@ int FAST_FUNC bbunpack(char **argv,
42 IF_DESKTOP(long long) int status; 42 IF_DESKTOP(long long) int status;
43 char *filename, *new_name; 43 char *filename, *new_name;
44 smallint exitcode = 0; 44 smallint exitcode = 0;
45 unpack_info_t info; 45 transformer_aux_data_t aux;
46 46
47 do { 47 do {
48 /* NB: new_name is *maybe* malloc'ed! */ 48 /* NB: new_name is *maybe* malloc'ed! */
@@ -98,9 +98,9 @@ int FAST_FUNC bbunpack(char **argv,
98 "use -f to force it"); 98 "use -f to force it");
99 } 99 }
100 100
101 /* memset(&info, 0, sizeof(info)); */ 101 init_transformer_aux_data(&aux);
102 info.mtime = 0; /* so far it has one member only */ 102 aux.check_signature = 1;
103 status = unpacker(&info); 103 status = unpacker(&aux);
104 if (status < 0) 104 if (status < 0)
105 exitcode = 1; 105 exitcode = 1;
106 106
@@ -111,10 +111,10 @@ int FAST_FUNC bbunpack(char **argv,
111 char *del = new_name; 111 char *del = new_name;
112 if (status >= 0) { 112 if (status >= 0) {
113 /* TODO: restore other things? */ 113 /* TODO: restore other things? */
114 if (info.mtime) { 114 if (aux.mtime != 0) {
115 struct timeval times[2]; 115 struct timeval times[2];
116 116
117 times[1].tv_sec = times[0].tv_sec = info.mtime; 117 times[1].tv_sec = times[0].tv_sec = aux.mtime;
118 times[1].tv_usec = times[0].tv_usec = 0; 118 times[1].tv_usec = times[0].tv_usec = 0;
119 /* Note: we closed it first. 119 /* Note: we closed it first.
120 * On some systems calling utimes 120 * On some systems calling utimes
@@ -184,16 +184,9 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
184 184
185#if ENABLE_UNCOMPRESS 185#if ENABLE_UNCOMPRESS
186static 186static
187IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(unpack_info_t *info UNUSED_PARAM) 187IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_aux_data_t *aux)
188{ 188{
189 IF_DESKTOP(long long) int status = -1; 189 return unpack_Z_stream(aux, STDIN_FILENO, STDOUT_FILENO);
190
191 if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 0x9d)) {
192 bb_error_msg("invalid magic");
193 } else {
194 status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO);
195 }
196 return status;
197} 190}
198int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 191int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
199int uncompress_main(int argc UNUSED_PARAM, char **argv) 192int uncompress_main(int argc UNUSED_PARAM, char **argv)
@@ -281,31 +274,9 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN
281 return filename; 274 return filename;
282} 275}
283static 276static
284IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(unpack_info_t *info) 277IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_aux_data_t *aux)
285{ 278{
286 IF_DESKTOP(long long) int status = -1; 279 return unpack_gz_stream(aux, STDIN_FILENO, STDOUT_FILENO);
287
288 /* do the decompression, and cleanup */
289 if (xread_char(STDIN_FILENO) == 0x1f) {
290 unsigned char magic2;
291
292 magic2 = xread_char(STDIN_FILENO);
293 if (ENABLE_FEATURE_SEAMLESS_Z && magic2 == 0x9d) {
294 status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO);
295 } else if (magic2 == 0x8b) {
296 status = unpack_gz_stream_with_info(STDIN_FILENO, STDOUT_FILENO, info);
297 } else {
298 goto bad_magic;
299 }
300 if (status < 0) {
301 bb_error_msg("error inflating");
302 }
303 } else {
304 bad_magic:
305 bb_error_msg("invalid magic");
306 /* status is still == -1 */
307 }
308 return status;
309} 280}
310/* 281/*
311 * Linux kernel build uses gzip -d -n. We accept and ignore it. 282 * Linux kernel build uses gzip -d -n. We accept and ignore it.
@@ -354,9 +325,9 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv)
354//applet:IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat)) 325//applet:IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat))
355#if ENABLE_BUNZIP2 326#if ENABLE_BUNZIP2
356static 327static
357IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(unpack_info_t *info UNUSED_PARAM) 328IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_aux_data_t *aux)
358{ 329{
359 return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO); 330 return unpack_bz2_stream(aux, STDIN_FILENO, STDOUT_FILENO);
360} 331}
361int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 332int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
362int bunzip2_main(int argc UNUSED_PARAM, char **argv) 333int bunzip2_main(int argc UNUSED_PARAM, char **argv)
@@ -422,9 +393,9 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
422 393
423#if ENABLE_UNLZMA 394#if ENABLE_UNLZMA
424static 395static
425IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(unpack_info_t *info UNUSED_PARAM) 396IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_aux_data_t *aux)
426{ 397{
427 return unpack_lzma_stream(STDIN_FILENO, STDOUT_FILENO); 398 return unpack_lzma_stream(aux, STDIN_FILENO, STDOUT_FILENO);
428} 399}
429int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 400int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
430int unlzma_main(int argc UNUSED_PARAM, char **argv) 401int unlzma_main(int argc UNUSED_PARAM, char **argv)
@@ -447,18 +418,9 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv)
447 418
448#if ENABLE_UNXZ 419#if ENABLE_UNXZ
449static 420static
450IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(unpack_info_t *info UNUSED_PARAM) 421IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_aux_data_t *aux)
451{ 422{
452 struct { 423 return unpack_xz_stream(aux, STDIN_FILENO, STDOUT_FILENO);
453 uint32_t v1;
454 uint16_t v2;
455 } magic;
456 xread(STDIN_FILENO, &magic, 6);
457 if (magic.v1 != XZ_MAGIC1a || magic.v2 != XZ_MAGIC2a) {
458 bb_error_msg("invalid magic");
459 return -1;
460 }
461 return unpack_xz_stream(STDIN_FILENO, STDOUT_FILENO);
462} 424}
463int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 425int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
464int unxz_main(int argc UNUSED_PARAM, char **argv) 426int unxz_main(int argc UNUSED_PARAM, char **argv)
diff --git a/archival/bzip2.c b/archival/bzip2.c
index 0716fa89b..dd77c8efc 100644
--- a/archival/bzip2.c
+++ b/archival/bzip2.c
@@ -111,7 +111,7 @@ IF_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, vo
111} 111}
112 112
113static 113static
114IF_DESKTOP(long long) int FAST_FUNC compressStream(unpack_info_t *info UNUSED_PARAM) 114IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_aux_data_t *aux UNUSED_PARAM)
115{ 115{
116 IF_DESKTOP(long long) int total; 116 IF_DESKTOP(long long) int total;
117 ssize_t count; 117 ssize_t count;
diff --git a/archival/cpio.c b/archival/cpio.c
index c2a5b8ab9..98cc18fa0 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -384,6 +384,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
384 goto dump; 384 goto dump;
385 } 385 }
386 /* parent */ 386 /* parent */
387 USE_FOR_NOMMU(argv[-optind][0] &= 0x7f); /* undo fork_or_rexec() damage */
387 xchdir(*argv++); 388 xchdir(*argv++);
388 close(pp.wr); 389 close(pp.wr);
389 xmove_fd(pp.rd, STDIN_FILENO); 390 xmove_fd(pp.rd, STDIN_FILENO);
diff --git a/archival/gzip.c b/archival/gzip.c
index f590fffa5..025e0a9f6 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -2015,7 +2015,7 @@ static void zip(ulg time_stamp)
2015 2015
2016/* ======================================================================== */ 2016/* ======================================================================== */
2017static 2017static
2018IF_DESKTOP(long long) int FAST_FUNC pack_gzip(unpack_info_t *info UNUSED_PARAM) 2018IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_aux_data_t *aux UNUSED_PARAM)
2019{ 2019{
2020 struct stat s; 2020 struct stat s;
2021 2021
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index b0bc4e5aa..39c18f264 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -28,10 +28,13 @@ COMMON_FILES:= \
28 init_handle.o 28 init_handle.o
29 29
30DPKG_FILES:= \ 30DPKG_FILES:= \
31 get_header_ar.o \
32 unpack_ar_archive.o \ 31 unpack_ar_archive.o \
32 filter_accept_list_reassign.o \
33 get_header_ar.o \
33 get_header_tar.o \ 34 get_header_tar.o \
34 filter_accept_list_reassign.o 35 get_header_tar_gz.o \
36 get_header_tar_bz2.o \
37 get_header_tar_lzma.o \
35 38
36INSERT 39INSERT
37 40
@@ -42,18 +45,18 @@ lib-$(CONFIG_UNXZ) += decompress_unxz.o
42lib-$(CONFIG_CPIO) += get_header_cpio.o 45lib-$(CONFIG_CPIO) += get_header_cpio.o
43lib-$(CONFIG_DPKG) += $(DPKG_FILES) 46lib-$(CONFIG_DPKG) += $(DPKG_FILES)
44lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) 47lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
45lib-$(CONFIG_GUNZIP) += decompress_unzip.o 48lib-$(CONFIG_GUNZIP) += decompress_gunzip.o
46lib-$(CONFIG_RPM2CPIO) += decompress_unzip.o get_header_cpio.o 49lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o
47lib-$(CONFIG_RPM) += open_transformer.o decompress_unzip.o get_header_cpio.o 50lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o
48lib-$(CONFIG_TAR) += get_header_tar.o 51lib-$(CONFIG_TAR) += get_header_tar.o
49lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o 52lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
50lib-$(CONFIG_UNZIP) += decompress_unzip.o 53lib-$(CONFIG_UNZIP) += decompress_gunzip.o
51lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o 54lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
52lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o 55lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
53lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o 56lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o
54lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_unzip.o get_header_tar_gz.o 57lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_gunzip.o
55lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o get_header_tar_bz2.o 58lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o
56lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o 59lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o
57lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o 60lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
58lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o 61lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
59lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += decompress_bunzip2.o 62lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += decompress_bunzip2.o
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index f565e5471..3f67b835f 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -13,13 +13,13 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
13 int res; 13 int res;
14 14
15#if ENABLE_FEATURE_TAR_SELINUX 15#if ENABLE_FEATURE_TAR_SELINUX
16 char *sctx = archive_handle->tar__next_file_sctx; 16 char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
17 if (!sctx) 17 if (!sctx)
18 sctx = archive_handle->tar__global_sctx; 18 sctx = archive_handle->tar__sctx[PAX_GLOBAL];
19 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ 19 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
20 setfscreatecon(sctx); 20 setfscreatecon(sctx);
21 free(archive_handle->tar__next_file_sctx); 21 free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
22 archive_handle->tar__next_file_sctx = NULL; 22 archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
23 } 23 }
24#endif 24#endif
25 25
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index cc2ff7798..a2ce33b51 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -64,13 +64,13 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
64 file_header_t *file_header = archive_handle->file_header; 64 file_header_t *file_header = archive_handle->file_header;
65 65
66#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */ 66#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
67 char *sctx = archive_handle->tar__next_file_sctx; 67 char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
68 if (!sctx) 68 if (!sctx)
69 sctx = archive_handle->tar__global_sctx; 69 sctx = archive_handle->tar__sctx[PAX_GLOBAL];
70 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ 70 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
71 setfscreatecon(sctx); 71 setfscreatecon(sctx);
72 free(archive_handle->tar__next_file_sctx); 72 free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
73 archive_handle->tar__next_file_sctx = NULL; 73 archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
74 } 74 }
75#endif 75#endif
76 76
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c
index c4640d489..dc252bb82 100644
--- a/archival/libarchive/decompress_bunzip2.c
+++ b/archival/libarchive/decompress_bunzip2.c
@@ -721,7 +721,7 @@ void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
721 721
722/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ 722/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */
723IF_DESKTOP(long long) int FAST_FUNC 723IF_DESKTOP(long long) int FAST_FUNC
724unpack_bz2_stream(int src_fd, int dst_fd) 724unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
725{ 725{
726 IF_DESKTOP(long long total_written = 0;) 726 IF_DESKTOP(long long total_written = 0;)
727 bunzip_data *bd; 727 bunzip_data *bd;
@@ -729,6 +729,9 @@ unpack_bz2_stream(int src_fd, int dst_fd)
729 int i; 729 int i;
730 unsigned len; 730 unsigned len;
731 731
732 if (check_signature16(aux, src_fd, BZIP2_MAGIC))
733 return -1;
734
732 outbuf = xmalloc(IOBUF_SIZE); 735 outbuf = xmalloc(IOBUF_SIZE);
733 len = 0; 736 len = 0;
734 while (1) { /* "Process one BZ... stream" loop */ 737 while (1) { /* "Process one BZ... stream" loop */
@@ -794,17 +797,6 @@ unpack_bz2_stream(int src_fd, int dst_fd)
794 return i ? i : IF_DESKTOP(total_written) + 0; 797 return i ? i : IF_DESKTOP(total_written) + 0;
795} 798}
796 799
797IF_DESKTOP(long long) int FAST_FUNC
798unpack_bz2_stream_prime(int src_fd, int dst_fd)
799{
800 uint16_t magic2;
801 xread(src_fd, &magic2, 2);
802 if (magic2 != BZIP2_MAGIC) {
803 bb_error_msg_and_die("invalid magic");
804 }
805 return unpack_bz2_stream(src_fd, dst_fd);
806}
807
808#ifdef TESTING 800#ifdef TESTING
809 801
810static char *const bunzip_errors[] = { 802static char *const bunzip_errors[] = {
@@ -819,7 +811,7 @@ int main(int argc, char **argv)
819 int i; 811 int i;
820 char c; 812 char c;
821 813
822 int i = unpack_bz2_stream_prime(0, 1); 814 int i = unpack_bz2_stream(0, 1);
823 if (i < 0) 815 if (i < 0)
824 fprintf(stderr, "%s\n", bunzip_errors[-i]); 816 fprintf(stderr, "%s\n", bunzip_errors[-i]);
825 else if (read(STDIN_FILENO, &c, 1)) 817 else if (read(STDIN_FILENO, &c, 1))
diff --git a/archival/libarchive/decompress_unzip.c b/archival/libarchive/decompress_gunzip.c
index aa5d22d0a..2d5ab3eb3 100644
--- a/archival/libarchive/decompress_unzip.c
+++ b/archival/libarchive/decompress_gunzip.c
@@ -1034,22 +1034,22 @@ inflate_unzip_internal(STATE_PARAM int in, int out)
1034/* For unzip */ 1034/* For unzip */
1035 1035
1036IF_DESKTOP(long long) int FAST_FUNC 1036IF_DESKTOP(long long) int FAST_FUNC
1037inflate_unzip(inflate_unzip_result *res, off_t compr_size, int in, int out) 1037inflate_unzip(transformer_aux_data_t *aux, int in, int out)
1038{ 1038{
1039 IF_DESKTOP(long long) int n; 1039 IF_DESKTOP(long long) int n;
1040 DECLARE_STATE; 1040 DECLARE_STATE;
1041 1041
1042 ALLOC_STATE; 1042 ALLOC_STATE;
1043 1043
1044 to_read = compr_size; 1044 to_read = aux->bytes_in;
1045// bytebuffer_max = 0x8000; 1045// bytebuffer_max = 0x8000;
1046 bytebuffer_offset = 4; 1046 bytebuffer_offset = 4;
1047 bytebuffer = xmalloc(bytebuffer_max); 1047 bytebuffer = xmalloc(bytebuffer_max);
1048 n = inflate_unzip_internal(PASS_STATE in, out); 1048 n = inflate_unzip_internal(PASS_STATE in, out);
1049 free(bytebuffer); 1049 free(bytebuffer);
1050 1050
1051 res->crc = gunzip_crc; 1051 aux->crc32 = gunzip_crc;
1052 res->bytes_out = gunzip_bytes_out; 1052 aux->bytes_out = gunzip_bytes_out;
1053 DEALLOC_STATE; 1053 DEALLOC_STATE;
1054 return n; 1054 return n;
1055} 1055}
@@ -1107,7 +1107,7 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY)
1107 return res; 1107 return res;
1108} 1108}
1109 1109
1110static int check_header_gzip(STATE_PARAM unpack_info_t *info) 1110static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux)
1111{ 1111{
1112 union { 1112 union {
1113 unsigned char raw[8]; 1113 unsigned char raw[8];
@@ -1169,8 +1169,8 @@ static int check_header_gzip(STATE_PARAM unpack_info_t *info)
1169 } 1169 }
1170 } 1170 }
1171 1171
1172 if (info) 1172 if (aux)
1173 info->mtime = SWAP_LE32(header.formatted.mtime); 1173 aux->mtime = SWAP_LE32(header.formatted.mtime);
1174 1174
1175 /* Read the header checksum */ 1175 /* Read the header checksum */
1176 if (header.formatted.flags & 0x02) { 1176 if (header.formatted.flags & 0x02) {
@@ -1182,33 +1182,58 @@ static int check_header_gzip(STATE_PARAM unpack_info_t *info)
1182} 1182}
1183 1183
1184IF_DESKTOP(long long) int FAST_FUNC 1184IF_DESKTOP(long long) int FAST_FUNC
1185unpack_gz_stream_with_info(int in, int out, unpack_info_t *info) 1185unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
1186{ 1186{
1187 uint32_t v32; 1187 uint32_t v32;
1188 IF_DESKTOP(long long) int n; 1188 IF_DESKTOP(long long) int total, n;
1189 DECLARE_STATE; 1189 DECLARE_STATE;
1190 1190
1191 n = 0; 1191#if !ENABLE_FEATURE_SEAMLESS_Z
1192 if (check_signature16(aux, src_fd, GZIP_MAGIC))
1193 return -1;
1194#else
1195 if (aux && aux->check_signature) {
1196 uint16_t magic2;
1197
1198 if (full_read(src_fd, &magic2, 2) != 2) {
1199 bad_magic:
1200 bb_error_msg("invalid magic");
1201 return -1;
1202 }
1203 if (magic2 == COMPRESS_MAGIC) {
1204 aux->check_signature = 0;
1205 return unpack_Z_stream(aux, src_fd, dst_fd);
1206 }
1207 if (magic2 != GZIP_MAGIC)
1208 goto bad_magic;
1209 }
1210#endif
1211
1212 total = 0;
1192 1213
1193 ALLOC_STATE; 1214 ALLOC_STATE;
1194 to_read = -1; 1215 to_read = -1;
1195// bytebuffer_max = 0x8000; 1216// bytebuffer_max = 0x8000;
1196 bytebuffer = xmalloc(bytebuffer_max); 1217 bytebuffer = xmalloc(bytebuffer_max);
1197 gunzip_src_fd = in; 1218 gunzip_src_fd = src_fd;
1198 1219
1199 again: 1220 again:
1200 if (!check_header_gzip(PASS_STATE info)) { 1221 if (!check_header_gzip(PASS_STATE aux)) {
1201 bb_error_msg("corrupted data"); 1222 bb_error_msg("corrupted data");
1202 n = -1; 1223 total = -1;
1203 goto ret; 1224 goto ret;
1204 } 1225 }
1205 n += inflate_unzip_internal(PASS_STATE in, out); 1226
1206 if (n < 0) 1227 n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd);
1228 if (n < 0) {
1229 total = -1;
1207 goto ret; 1230 goto ret;
1231 }
1232 total += n;
1208 1233
1209 if (!top_up(PASS_STATE 8)) { 1234 if (!top_up(PASS_STATE 8)) {
1210 bb_error_msg("corrupted data"); 1235 bb_error_msg("corrupted data");
1211 n = -1; 1236 total = -1;
1212 goto ret; 1237 goto ret;
1213 } 1238 }
1214 1239
@@ -1216,7 +1241,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1216 v32 = buffer_read_le_u32(PASS_STATE_ONLY); 1241 v32 = buffer_read_le_u32(PASS_STATE_ONLY);
1217 if ((~gunzip_crc) != v32) { 1242 if ((~gunzip_crc) != v32) {
1218 bb_error_msg("crc error"); 1243 bb_error_msg("crc error");
1219 n = -1; 1244 total = -1;
1220 goto ret; 1245 goto ret;
1221 } 1246 }
1222 1247
@@ -1224,7 +1249,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1224 v32 = buffer_read_le_u32(PASS_STATE_ONLY); 1249 v32 = buffer_read_le_u32(PASS_STATE_ONLY);
1225 if ((uint32_t)gunzip_bytes_out != v32) { 1250 if ((uint32_t)gunzip_bytes_out != v32) {
1226 bb_error_msg("incorrect length"); 1251 bb_error_msg("incorrect length");
1227 n = -1; 1252 total = -1;
1228 } 1253 }
1229 1254
1230 if (!top_up(PASS_STATE 2)) 1255 if (!top_up(PASS_STATE 2))
@@ -1242,11 +1267,5 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1242 ret: 1267 ret:
1243 free(bytebuffer); 1268 free(bytebuffer);
1244 DEALLOC_STATE; 1269 DEALLOC_STATE;
1245 return n; 1270 return total;
1246}
1247
1248IF_DESKTOP(long long) int FAST_FUNC
1249unpack_gz_stream(int in, int out)
1250{
1251 return unpack_gz_stream_with_info(in, out, NULL);
1252} 1271}
diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c
index c6040d04b..e9bbfb9bd 100644
--- a/archival/libarchive/decompress_uncompress.c
+++ b/archival/libarchive/decompress_uncompress.c
@@ -73,7 +73,7 @@
73 */ 73 */
74 74
75IF_DESKTOP(long long) int FAST_FUNC 75IF_DESKTOP(long long) int FAST_FUNC
76unpack_Z_stream(int fd_in, int fd_out) 76unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
77{ 77{
78 IF_DESKTOP(long long total_written = 0;) 78 IF_DESKTOP(long long total_written = 0;)
79 IF_DESKTOP(long long) int retval = -1; 79 IF_DESKTOP(long long) int retval = -1;
@@ -103,16 +103,19 @@ unpack_Z_stream(int fd_in, int fd_out)
103 /* block compress mode -C compatible with 2.0 */ 103 /* block compress mode -C compatible with 2.0 */
104 int block_mode; /* = BLOCK_MODE; */ 104 int block_mode; /* = BLOCK_MODE; */
105 105
106 if (check_signature16(aux, src_fd, COMPRESS_MAGIC))
107 return -1;
108
106 inbuf = xzalloc(IBUFSIZ + 64); 109 inbuf = xzalloc(IBUFSIZ + 64);
107 outbuf = xzalloc(OBUFSIZ + 2048); 110 outbuf = xzalloc(OBUFSIZ + 2048);
108 htab = xzalloc(HSIZE); /* wsn't zeroed out before, maybe can xmalloc? */ 111 htab = xzalloc(HSIZE); /* wasn't zeroed out before, maybe can xmalloc? */
109 codetab = xzalloc(HSIZE * sizeof(codetab[0])); 112 codetab = xzalloc(HSIZE * sizeof(codetab[0]));
110 113
111 insize = 0; 114 insize = 0;
112 115
113 /* xread isn't good here, we have to return - caller may want 116 /* xread isn't good here, we have to return - caller may want
114 * to do some cleanup (e.g. delete incomplete unpacked file etc) */ 117 * to do some cleanup (e.g. delete incomplete unpacked file etc) */
115 if (full_read(fd_in, inbuf, 1) != 1) { 118 if (full_read(src_fd, inbuf, 1) != 1) {
116 bb_error_msg("short read"); 119 bb_error_msg("short read");
117 goto err; 120 goto err;
118 } 121 }
@@ -162,7 +165,7 @@ unpack_Z_stream(int fd_in, int fd_out)
162 } 165 }
163 166
164 if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { 167 if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
165 rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ); 168 rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ);
166 if (rsize < 0) 169 if (rsize < 0)
167 bb_error_msg_and_die(bb_msg_read_error); 170 bb_error_msg_and_die(bb_msg_read_error);
168 insize += rsize; 171 insize += rsize;
@@ -268,7 +271,7 @@ unpack_Z_stream(int fd_in, int fd_out)
268 } 271 }
269 272
270 if (outpos >= OBUFSIZ) { 273 if (outpos >= OBUFSIZ) {
271 xwrite(fd_out, outbuf, outpos); 274 xwrite(dst_fd, outbuf, outpos);
272 IF_DESKTOP(total_written += outpos;) 275 IF_DESKTOP(total_written += outpos;)
273 outpos = 0; 276 outpos = 0;
274 } 277 }
@@ -296,7 +299,7 @@ unpack_Z_stream(int fd_in, int fd_out)
296 } while (rsize > 0); 299 } while (rsize > 0);
297 300
298 if (outpos > 0) { 301 if (outpos > 0) {
299 xwrite(fd_out, outbuf, outpos); 302 xwrite(dst_fd, outbuf, outpos);
300 IF_DESKTOP(total_written += outpos;) 303 IF_DESKTOP(total_written += outpos;)
301 } 304 }
302 305
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c
index 3631b50cc..cfde8ea56 100644
--- a/archival/libarchive/decompress_unlzma.c
+++ b/archival/libarchive/decompress_unlzma.c
@@ -213,7 +213,7 @@ enum {
213 213
214 214
215IF_DESKTOP(long long) int FAST_FUNC 215IF_DESKTOP(long long) int FAST_FUNC
216unpack_lzma_stream(int src_fd, int dst_fd) 216unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst_fd)
217{ 217{
218 IF_DESKTOP(long long total_written = 0;) 218 IF_DESKTOP(long long total_written = 0;)
219 lzma_header_t header; 219 lzma_header_t header;
diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c
index 3e5d4edca..79b48a152 100644
--- a/archival/libarchive/decompress_unxz.c
+++ b/archival/libarchive/decompress_unxz.c
@@ -38,7 +38,7 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
38#include "unxz/xz_dec_stream.c" 38#include "unxz/xz_dec_stream.c"
39 39
40IF_DESKTOP(long long) int FAST_FUNC 40IF_DESKTOP(long long) int FAST_FUNC
41unpack_xz_stream(int src_fd, int dst_fd) 41unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
42{ 42{
43 struct xz_buf iobuf; 43 struct xz_buf iobuf;
44 struct xz_dec *state; 44 struct xz_dec *state;
@@ -49,13 +49,17 @@ unpack_xz_stream(int src_fd, int dst_fd)
49 global_crc32_table = crc32_filltable(NULL, /*endian:*/ 0); 49 global_crc32_table = crc32_filltable(NULL, /*endian:*/ 0);
50 50
51 memset(&iobuf, 0, sizeof(iobuf)); 51 memset(&iobuf, 0, sizeof(iobuf));
52 /* Preload XZ file signature */ 52 membuf = xmalloc(2 * BUFSIZ);
53 membuf = (void*) strcpy(xmalloc(2 * BUFSIZ), HEADER_MAGIC);
54 iobuf.in = membuf; 53 iobuf.in = membuf;
55 iobuf.in_size = HEADER_MAGIC_SIZE;
56 iobuf.out = membuf + BUFSIZ; 54 iobuf.out = membuf + BUFSIZ;
57 iobuf.out_size = BUFSIZ; 55 iobuf.out_size = BUFSIZ;
58 56
57 if (!aux || aux->check_signature == 0) {
58 /* Preload XZ file signature */
59 strcpy((char*)membuf, HEADER_MAGIC);
60 iobuf.in_size = HEADER_MAGIC_SIZE;
61 } /* else: let xz code read & check it */
62
59 /* Limit memory usage to about 64 MiB. */ 63 /* Limit memory usage to about 64 MiB. */
60 state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024); 64 state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024);
61 65
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index a63c0fb01..80a709144 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -90,23 +90,20 @@ static unsigned long long getOctal(char *str, int len)
90} 90}
91#define GET_OCTAL(a) getOctal((a), sizeof(a)) 91#define GET_OCTAL(a) getOctal((a), sizeof(a))
92 92
93#if ENABLE_FEATURE_TAR_SELINUX 93/* "global" is 0 or 1 */
94/* Scan a PAX header for SELinux contexts, via "RHT.security.selinux" keyword. 94static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global)
95 * This is what Red Hat's patched version of tar uses.
96 */
97# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
98static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, unsigned sz)
99{ 95{
100 char *buf, *p; 96 char *buf, *p;
101 char *result; 97 unsigned blk_sz;
98
99 blk_sz = (sz + 511) & (~511);
100 p = buf = xmalloc(blk_sz + 1);
101 xread(archive_handle->src_fd, buf, blk_sz);
102 archive_handle->offset += blk_sz;
102 103
103 p = buf = xmalloc(sz + 1);
104 /* prevent bb_strtou from running off the buffer */ 104 /* prevent bb_strtou from running off the buffer */
105 buf[sz] = '\0'; 105 buf[sz] = '\0';
106 xread(archive_handle->src_fd, buf, sz);
107 archive_handle->offset += sz;
108 106
109 result = NULL;
110 while (sz != 0) { 107 while (sz != 0) {
111 char *end, *value; 108 char *end, *value;
112 unsigned len; 109 unsigned len;
@@ -133,19 +130,33 @@ static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, uns
133 * (we do not bother to check that it *was* a newline) 130 * (we do not bother to check that it *was* a newline)
134 */ 131 */
135 p[-1] = '\0'; 132 p[-1] = '\0';
136 /* Is it selinux security context? */
137 value = end + 1; 133 value = end + 1;
134
135#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
136 if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) {
137 value += sizeof("path=") - 1;
138 free(archive_handle->tar__longname);
139 archive_handle->tar__longname = xstrdup(value);
140 continue;
141 }
142#endif
143
144#if ENABLE_FEATURE_TAR_SELINUX
145 /* Scan for SELinux contexts, via "RHT.security.selinux" keyword.
146 * This is what Red Hat's patched version of tar uses.
147 */
148# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
138 if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) { 149 if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {
139 value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; 150 value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
140 result = xstrdup(value); 151 free(archive_handle->tar__sctx[global]);
141 break; 152 archive_handle->tar__sctx[global] = xstrdup(value);
153 continue;
142 } 154 }
155#endif
143 } 156 }
144 157
145 free(buf); 158 free(buf);
146 return result;
147} 159}
148#endif
149 160
150char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) 161char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
151{ 162{
@@ -224,43 +235,18 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
224 || memcmp(tar.magic, "\0\0\0\0", 5) != 0) 235 || memcmp(tar.magic, "\0\0\0\0", 5) != 0)
225 ) { 236 ) {
226#if ENABLE_FEATURE_TAR_AUTODETECT 237#if ENABLE_FEATURE_TAR_AUTODETECT
227 char FAST_FUNC (*get_header_ptr)(archive_handle_t *);
228 uint16_t magic2;
229
230 autodetect: 238 autodetect:
231 magic2 = *(bb__aliased_uint16_t*)tar.name;
232 /* tar gz/bz autodetect: check for gz/bz2 magic.
233 * If we see the magic, and it is the very first block,
234 * we can switch to get_header_tar_gz/bz2/lzma().
235 * Needs seekable fd. I wish recv(MSG_PEEK) works
236 * on any fd... */
237# if ENABLE_FEATURE_SEAMLESS_GZ
238 if (magic2 == GZIP_MAGIC) {
239 get_header_ptr = get_header_tar_gz;
240 } else
241# endif
242# if ENABLE_FEATURE_SEAMLESS_BZ2
243 if (magic2 == BZIP2_MAGIC
244 && tar.name[2] == 'h' && isdigit(tar.name[3])
245 ) { /* bzip2 */
246 get_header_ptr = get_header_tar_bz2;
247 } else
248# endif
249# if ENABLE_FEATURE_SEAMLESS_XZ
250 //TODO: if (magic2 == XZ_MAGIC1)...
251 //else
252# endif
253 goto err;
254 /* Two different causes for lseek() != 0: 239 /* Two different causes for lseek() != 0:
255 * unseekable fd (would like to support that too, but...), 240 * unseekable fd (would like to support that too, but...),
256 * or not first block (false positive, it's not .gz/.bz2!) */ 241 * or not first block (false positive, it's not .gz/.bz2!) */
257 if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0) 242 if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0)
258 goto err; 243 goto err;
259 while (get_header_ptr(archive_handle) == EXIT_SUCCESS) 244 if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_detected:*/ 0) != 0)
260 continue;
261 return EXIT_FAILURE;
262 err: 245 err:
263#endif /* FEATURE_TAR_AUTODETECT */ 246 bb_error_msg_and_die("invalid tar magic");
247 archive_handle->offset = 0;
248 goto again_after_align;
249#endif
264 bb_error_msg_and_die("invalid tar magic"); 250 bb_error_msg_and_die("invalid tar magic");
265 } 251 }
266 252
@@ -418,12 +404,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
418 case 'S': /* Sparse file */ 404 case 'S': /* Sparse file */
419 case 'V': /* Volume header */ 405 case 'V': /* Volume header */
420#endif 406#endif
421#if !ENABLE_FEATURE_TAR_SELINUX
422 case 'g': /* pax global header */ 407 case 'g': /* pax global header */
423 case 'x': /* pax extended header */ 408 case 'x': { /* pax extended header */
424#else 409 if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
410 goto skip_ext_hdr;
411 process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
412 goto again_after_align;
413 }
425 skip_ext_hdr: 414 skip_ext_hdr:
426#endif
427 { 415 {
428 off_t sz; 416 off_t sz;
429 bb_error_msg("warning: skipping header '%c'", tar.typeflag); 417 bb_error_msg("warning: skipping header '%c'", tar.typeflag);
@@ -435,18 +423,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
435 /* return get_header_tar(archive_handle); */ 423 /* return get_header_tar(archive_handle); */
436 goto again_after_align; 424 goto again_after_align;
437 } 425 }
438#if ENABLE_FEATURE_TAR_SELINUX
439 case 'g': /* pax global header */
440 case 'x': { /* pax extended header */
441 char **pp;
442 if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
443 goto skip_ext_hdr;
444 pp = (tar.typeflag == 'g') ? &archive_handle->tar__global_sctx : &archive_handle->tar__next_file_sctx;
445 free(*pp);
446 *pp = get_selinux_sctx_from_pax_hdr(archive_handle, file_header->size);
447 goto again;
448 }
449#endif
450 default: 426 default:
451 bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag); 427 bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
452 } 428 }
diff --git a/archival/libarchive/get_header_tar_bz2.c b/archival/libarchive/get_header_tar_bz2.c
index e012dec3b..0ee00df53 100644
--- a/archival/libarchive/get_header_tar_bz2.c
+++ b/archival/libarchive/get_header_tar_bz2.c
@@ -11,7 +11,7 @@ char FAST_FUNC get_header_tar_bz2(archive_handle_t *archive_handle)
11 /* Can't lseek over pipes */ 11 /* Can't lseek over pipes */
12 archive_handle->seek = seek_by_read; 12 archive_handle->seek = seek_by_read;
13 13
14 open_transformer(archive_handle->src_fd, unpack_bz2_stream_prime, "bunzip2"); 14 open_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2");
15 archive_handle->offset = 0; 15 archive_handle->offset = 0;
16 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 16 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
17 continue; 17 continue;
diff --git a/archival/libarchive/get_header_tar_gz.c b/archival/libarchive/get_header_tar_gz.c
index b9679b0bd..03284342b 100644
--- a/archival/libarchive/get_header_tar_gz.c
+++ b/archival/libarchive/get_header_tar_gz.c
@@ -8,25 +8,10 @@
8 8
9char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle) 9char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle)
10{ 10{
11#if BB_MMU
12 uint16_t magic;
13#endif
14
15 /* Can't lseek over pipes */ 11 /* Can't lseek over pipes */
16 archive_handle->seek = seek_by_read; 12 archive_handle->seek = seek_by_read;
17 13
18 /* Check gzip magic only if open_transformer will invoke unpack_gz_stream (MMU case). 14 open_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip");
19 * Otherwise, it will invoke an external helper "gunzip -cf" (NOMMU case) which will
20 * need the header. */
21#if BB_MMU
22 xread(archive_handle->src_fd, &magic, 2);
23 /* Can skip this check, but error message will be less clear */
24 if (magic != GZIP_MAGIC) {
25 bb_error_msg_and_die("invalid gzip magic");
26 }
27#endif
28
29 open_transformer(archive_handle->src_fd, unpack_gz_stream, "gunzip");
30 archive_handle->offset = 0; 15 archive_handle->offset = 0;
31 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 16 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
32 continue; 17 continue;
diff --git a/archival/libarchive/get_header_tar_lzma.c b/archival/libarchive/get_header_tar_lzma.c
index 666700729..d565a217d 100644
--- a/archival/libarchive/get_header_tar_lzma.c
+++ b/archival/libarchive/get_header_tar_lzma.c
@@ -14,7 +14,7 @@ char FAST_FUNC get_header_tar_lzma(archive_handle_t *archive_handle)
14 /* Can't lseek over pipes */ 14 /* Can't lseek over pipes */
15 archive_handle->seek = seek_by_read; 15 archive_handle->seek = seek_by_read;
16 16
17 open_transformer(archive_handle->src_fd, unpack_lzma_stream, "unlzma"); 17 open_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma");
18 archive_handle->offset = 0; 18 archive_handle->offset = 0;
19 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 19 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
20 continue; 20 continue;
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index aa8c1021c..f2edc2a2b 100644
--- a/archival/libarchive/open_transformer.c
+++ b/archival/libarchive/open_transformer.c
@@ -6,14 +6,64 @@
6#include "libbb.h" 6#include "libbb.h"
7#include "bb_archive.h" 7#include "bb_archive.h"
8 8
9void FAST_FUNC init_transformer_aux_data(transformer_aux_data_t *aux)
10{
11 memset(aux, 0, sizeof(*aux));
12}
13
14int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16)
15{
16 if (aux && aux->check_signature) {
17 uint16_t magic2;
18 if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) {
19 bb_error_msg("invalid magic");
20#if 0 /* possible future extension */
21 if (aux->check_signature > 1)
22 xfunc_die();
23#endif
24 return -1;
25 }
26 }
27 return 0;
28}
29
30#if !ENABLE_PLATFORM_MINGW32
31void check_errors_in_children(int signo)
32{
33 int status;
34
35 if (!signo) {
36 /* block waiting for any child */
37 if (wait(&status) < 0)
38 return; /* probably there are no children */
39 goto check_status;
40 }
41
42 /* Wait for any child without blocking */
43 for (;;) {
44 if (wait_any_nohang(&status) < 0)
45 /* wait failed?! I'm confused... */
46 return;
47 check_status:
48 if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
49 /* this child exited with 0 */
50 continue;
51 /* Cannot happen?
52 if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; */
53 bb_got_signal = 1;
54 }
55}
56#endif
57
9/* transformer(), more than meets the eye */ 58/* transformer(), more than meets the eye */
10/* 59#if BB_MMU
11 * On MMU machine, the transform_prog is removed by macro magic
12 * in include/archive.h. On NOMMU, transformer is removed.
13 */
14void FAST_FUNC open_transformer(int fd, 60void FAST_FUNC open_transformer(int fd,
15 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(int src_fd, int dst_fd), 61 int check_signature,
16 const char *transform_prog) 62 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd)
63)
64#else
65void FAST_FUNC open_transformer(int fd, const char *transform_prog)
66#endif
17{ 67{
18 struct fd_pair fd_pipe; 68 struct fd_pair fd_pipe;
19 int pid; 69 int pid;
@@ -25,13 +75,18 @@ void FAST_FUNC open_transformer(int fd,
25 close(fd_pipe.rd); /* we don't want to read from the parent */ 75 close(fd_pipe.rd); /* we don't want to read from the parent */
26 // FIXME: error check? 76 // FIXME: error check?
27#if BB_MMU 77#if BB_MMU
28 transformer(fd, fd_pipe.wr); 78 {
29 if (ENABLE_FEATURE_CLEAN_UP) { 79 transformer_aux_data_t aux;
30 close(fd_pipe.wr); /* send EOF */ 80 init_transformer_aux_data(&aux);
31 close(fd); 81 aux.check_signature = check_signature;
82 transformer(&aux, fd, fd_pipe.wr);
83 if (ENABLE_FEATURE_CLEAN_UP) {
84 close(fd_pipe.wr); /* send EOF */
85 close(fd);
86 }
87 /* must be _exit! bug was actually seen here */
88 _exit(EXIT_SUCCESS);
32 } 89 }
33 /* must be _exit! bug was actually seen here */
34 _exit(EXIT_SUCCESS);
35#else 90#else
36 { 91 {
37 char *argv[4]; 92 char *argv[4];
@@ -52,3 +107,117 @@ void FAST_FUNC open_transformer(int fd,
52 close(fd_pipe.wr); /* don't want to write to the child */ 107 close(fd_pipe.wr); /* don't want to write to the child */
53 xmove_fd(fd_pipe.rd, fd); 108 xmove_fd(fd_pipe.rd, fd);
54} 109}
110
111
112#if SEAMLESS_COMPRESSION
113
114/* Used by e.g. rpm which gives us a fd without filename,
115 * thus we can't guess the format from filename's extension.
116 */
117int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_detected)
118{
119 union {
120 uint8_t b[4];
121 uint16_t b16[2];
122 uint32_t b32[1];
123 } magic;
124 int offset = -2;
125 USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);)
126 USE_FOR_NOMMU(const char *xformer_prog;)
127
128 /* .gz and .bz2 both have 2-byte signature, and their
129 * unpack_XXX_stream wants this header skipped. */
130 xread(fd, magic.b16, sizeof(magic.b16[0]));
131 if (ENABLE_FEATURE_SEAMLESS_GZ
132 && magic.b16[0] == GZIP_MAGIC
133 ) {
134 USE_FOR_MMU(xformer = unpack_gz_stream;)
135 USE_FOR_NOMMU(xformer_prog = "gunzip";)
136 goto found_magic;
137 }
138 if (ENABLE_FEATURE_SEAMLESS_BZ2
139 && magic.b16[0] == BZIP2_MAGIC
140 ) {
141 USE_FOR_MMU(xformer = unpack_bz2_stream;)
142 USE_FOR_NOMMU(xformer_prog = "bunzip2";)
143 goto found_magic;
144 }
145 if (ENABLE_FEATURE_SEAMLESS_XZ
146 && magic.b16[0] == XZ_MAGIC1
147 ) {
148 offset = -6;
149 xread(fd, magic.b32, sizeof(magic.b32[0]));
150 if (magic.b32[0] == XZ_MAGIC2) {
151 USE_FOR_MMU(xformer = unpack_xz_stream;)
152 USE_FOR_NOMMU(xformer_prog = "unxz";)
153 goto found_magic;
154 }
155 }
156
157 /* No known magic seen */
158 if (fail_if_not_detected)
159 bb_error_msg_and_die("no gzip"
160 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
161 IF_FEATURE_SEAMLESS_XZ("/xz")
162 " magic");
163 xlseek(fd, offset, SEEK_CUR);
164 return 1;
165
166 found_magic:
167# if BB_MMU
168 open_transformer_with_no_sig(fd, xformer);
169# else
170 /* NOMMU version of open_transformer execs
171 * an external unzipper that wants
172 * file position at the start of the file */
173 xlseek(fd, offset, SEEK_CUR);
174 open_transformer_with_sig(fd, xformer, xformer_prog);
175# endif
176 return 0;
177}
178
179int FAST_FUNC open_zipped(const char *fname)
180{
181 char *sfx;
182 int fd;
183
184 fd = open(fname, O_RDONLY);
185 if (fd < 0)
186 return fd;
187
188 sfx = strrchr(fname, '.');
189 if (sfx) {
190 sfx++;
191 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
192 /* .lzma has no header/signature, just trust it */
193 open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma");
194 else
195 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
196 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
197 || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
198 ) {
199 setup_unzip_on_fd(fd, /*fail_if_not_detected:*/ 1);
200 }
201 }
202
203 return fd;
204}
205
206#endif /* SEAMLESS_COMPRESSION */
207
208void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
209{
210 int fd;
211 char *image;
212
213 fd = open_zipped(fname);
214 if (fd < 0)
215 return NULL;
216
217 image = xmalloc_read(fd, maxsz_p);
218 if (!image)
219 bb_perror_msg("read error from '%s'", fname);
220 close(fd);
221
222 return image;
223}
diff --git a/archival/lzop.c b/archival/lzop.c
index 7e30091d9..fbe08417d 100644
--- a/archival/lzop.c
+++ b/archival/lzop.c
@@ -201,7 +201,7 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
201 /* remove short run */ 201 /* remove short run */
202 *litp &= ~3; 202 *litp &= ~3;
203 /* copy over the 2 literals that replace the match */ 203 /* copy over the 2 literals that replace the match */
204 copy2(ip-3+1,m_pos,pd(op,m_pos)); 204 copy2(ip-3+1, m_pos, pd(op, m_pos));
205 /* move literals 1 byte ahead */ 205 /* move literals 1 byte ahead */
206 litp += 2; 206 litp += 2;
207 if (lit > 0) 207 if (lit > 0)
@@ -211,7 +211,8 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
211 *litp = (unsigned char)(lit - 3); 211 *litp = (unsigned char)(lit - 3);
212 212
213 o_m1_b++; 213 o_m1_b++;
214 *op++ = *m_pos++; *op++ = *m_pos++; 214 *op++ = *m_pos++;
215 *op++ = *m_pos++;
215 goto copy_literal_run; 216 goto copy_literal_run;
216 } 217 }
217 copy_m1: 218 copy_m1:
@@ -240,7 +241,7 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
240 ) { 241 ) {
241 t = *ip++; 242 t = *ip++;
242 /* copy over the 3 literals that replace the match */ 243 /* copy over the 3 literals that replace the match */
243 copy3(ip-1-2,m_pos,pd(op,m_pos)); 244 copy3(ip-1-2, m_pos, pd(op, m_pos));
244 /* set new length of previous literal run */ 245 /* set new length of previous literal run */
245 lit += 3 + t + 3; 246 lit += 3 + t + 3;
246 *litp = (unsigned char)(lit - 3); 247 *litp = (unsigned char)(lit - 3);
@@ -289,7 +290,7 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
289 lit += 3; 290 lit += 3;
290 *litp = (unsigned char)((*litp & ~3) | lit); 291 *litp = (unsigned char)((*litp & ~3) | lit);
291 /* copy over the 3 literals that replace the match */ 292 /* copy over the 3 literals that replace the match */
292 copy3(ip-3,m_pos,pd(op,m_pos)); 293 copy3(ip-3, m_pos, pd(op, m_pos));
293 o_m3_a++; 294 o_m3_a++;
294 } 295 }
295 /* test if a literal run follows */ 296 /* test if a literal run follows */
@@ -300,7 +301,7 @@ static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len,
300 /* remove short run */ 301 /* remove short run */
301 *litp &= ~3; 302 *litp &= ~3;
302 /* copy over the 3 literals that replace the match */ 303 /* copy over the 3 literals that replace the match */
303 copy3(ip-4+1,m_pos,pd(op,m_pos)); 304 copy3(ip-4+1, m_pos, pd(op, m_pos));
304 /* move literals 1 byte ahead */ 305 /* move literals 1 byte ahead */
305 litp += 2; 306 litp += 2;
306 if (lit > 0) 307 if (lit > 0)
@@ -1076,7 +1077,7 @@ static char* FAST_FUNC make_new_name_lzop(char *filename, const char *expected_e
1076 return xasprintf("%s.lzo", filename); 1077 return xasprintf("%s.lzo", filename);
1077} 1078}
1078 1079
1079static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(unpack_info_t *info UNUSED_PARAM) 1080static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_aux_data_t *aux UNUSED_PARAM)
1080{ 1081{
1081 if (option_mask32 & OPT_DECOMPRESS) 1082 if (option_mask32 & OPT_DECOMPRESS)
1082 return do_lzo_decompress(); 1083 return do_lzo_decompress();
diff --git a/archival/rpm.c b/archival/rpm.c
index 089b68983..6757a6ceb 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -236,7 +236,7 @@ static void extract_cpio(int fd, const char *source_rpm)
236 archive_handle->src_fd = fd; 236 archive_handle->src_fd = fd;
237 /*archive_handle->offset = 0; - init_handle() did it */ 237 /*archive_handle->offset = 0; - init_handle() did it */
238 238
239 setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/); 239 setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_detected:*/ 1);
240 while (get_header_cpio(archive_handle) == EXIT_SUCCESS) 240 while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
241 continue; 241 continue;
242} 242}
diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c
index 28b43a181..898d4aca4 100644
--- a/archival/rpm2cpio.c
+++ b/archival/rpm2cpio.c
@@ -66,54 +66,24 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
66 /* Skip the main header */ 66 /* Skip the main header */
67 skip_header(); 67 skip_header();
68 68
69#if 0 69 //if (SEAMLESS_COMPRESSION)
70 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */
71 // signal(SIGCHLD, check_errors_in_children);
72
70 /* This works, but doesn't report uncompress errors (they happen in child) */ 73 /* This works, but doesn't report uncompress errors (they happen in child) */
71 setup_unzip_on_fd(rpm_fd /*fail_if_not_detected: 1*/); 74 setup_unzip_on_fd(rpm_fd, /*fail_if_not_detected:*/ 1);
72 if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0) 75 if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0)
73 bb_error_msg_and_die("error unpacking"); 76 bb_error_msg_and_die("error unpacking");
74#else
75 /* BLOAT */
76 {
77 union {
78 uint8_t b[4];
79 uint16_t b16[2];
80 uint32_t b32[1];
81 } magic;
82 IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd);
83
84 xread(rpm_fd, magic.b16, sizeof(magic.b16[0]));
85 if (magic.b16[0] == GZIP_MAGIC) {
86 unpack = unpack_gz_stream;
87 } else
88 if (ENABLE_FEATURE_SEAMLESS_BZ2
89 && magic.b16[0] == BZIP2_MAGIC
90 ) {
91 unpack = unpack_bz2_stream;
92 } else
93 if (ENABLE_FEATURE_SEAMLESS_XZ
94 && magic.b16[0] == XZ_MAGIC1
95 ) {
96 xread(rpm_fd, magic.b32, sizeof(magic.b32[0]));
97 if (magic.b32[0] != XZ_MAGIC2)
98 goto no_magic;
99 /* unpack_xz_stream wants fd at position 6, no need to seek */
100 //xlseek(rpm_fd, -6, SEEK_CUR);
101 unpack = unpack_xz_stream;
102 } else {
103 no_magic:
104 bb_error_msg_and_die("no gzip"
105 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
106 IF_FEATURE_SEAMLESS_XZ("/xz")
107 " magic");
108 }
109 if (unpack(rpm_fd, STDOUT_FILENO) < 0)
110 bb_error_msg_and_die("error unpacking");
111 }
112#endif
113 77
114 if (ENABLE_FEATURE_CLEAN_UP) { 78 if (ENABLE_FEATURE_CLEAN_UP) {
115 close(rpm_fd); 79 close(rpm_fd);
116 } 80 }
117 81
118 return 0; 82#if !ENABLE_PLATFORM_MINGW32
83 if (SEAMLESS_COMPRESSION) {
84 check_errors_in_children(0);
85 return bb_got_signal;
86 }
87#endif
88 return EXIT_SUCCESS;
119} 89}
diff --git a/archival/tar.c b/archival/tar.c
index 2b752f640..fcd128a91 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -692,54 +692,6 @@ static llist_t *append_file_list_to_list(llist_t *list)
692# define append_file_list_to_list(x) 0 692# define append_file_list_to_list(x) 0
693#endif 693#endif
694 694
695#if ENABLE_FEATURE_SEAMLESS_Z
696static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle)
697{
698 /* Can't lseek over pipes */
699 archive_handle->seek = seek_by_read;
700
701 /* do the decompression, and cleanup */
702 if (xread_char(archive_handle->src_fd) != 0x1f
703 || xread_char(archive_handle->src_fd) != 0x9d
704 ) {
705 bb_error_msg_and_die("invalid magic");
706 }
707
708 open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress");
709 archive_handle->offset = 0;
710 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
711 continue;
712
713 /* Can only do one file at a time */
714 return EXIT_FAILURE;
715}
716#else
717# define get_header_tar_Z NULL
718#endif
719
720#ifdef CHECK_FOR_CHILD_EXITCODE
721/* Looks like it isn't needed - tar detects malformed (truncated)
722 * archive if e.g. bunzip2 fails */
723static int child_error;
724
725static void handle_SIGCHLD(int status)
726{
727 /* Actually, 'status' is a signo. We reuse it for other needs */
728
729 /* Wait for any child without blocking */
730 if (wait_any_nohang(&status) < 0)
731 /* wait failed?! I'm confused... */
732 return;
733
734 if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
735 /* child exited with 0 */
736 return;
737 /* Cannot happen?
738 if (!WIFSIGNALED(status) && !WIFEXITED(status)) return; */
739 child_error = 1;
740}
741#endif
742
743//usage:#define tar_trivial_usage 695//usage:#define tar_trivial_usage
744//usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" 696//usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt"
745//usage: IF_FEATURE_SEAMLESS_Z("Z") 697//usage: IF_FEATURE_SEAMLESS_Z("Z")
@@ -845,6 +797,8 @@ enum {
845 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner 797 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner
846 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions 798 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
847 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite 799 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
800
801 OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_COMPRESS),
848}; 802};
849#if ENABLE_FEATURE_TAR_LONG_OPTIONS 803#if ENABLE_FEATURE_TAR_LONG_OPTIONS
850static const char tar_longopts[] ALIGN1 = 804static const char tar_longopts[] ALIGN1 =
@@ -903,7 +857,6 @@ static const char tar_longopts[] ALIGN1 =
903int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 857int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
904int tar_main(int argc UNUSED_PARAM, char **argv) 858int tar_main(int argc UNUSED_PARAM, char **argv)
905{ 859{
906 char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar;
907 archive_handle_t *tar_handle; 860 archive_handle_t *tar_handle;
908 char *base_dir = NULL; 861 char *base_dir = NULL;
909 const char *tar_filename = "-"; 862 const char *tar_filename = "-";
@@ -1019,18 +972,6 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1019 tar_handle->ah_flags |= ARCHIVE_O_TRUNC; 972 tar_handle->ah_flags |= ARCHIVE_O_TRUNC;
1020 } 973 }
1021 974
1022 if (opt & OPT_GZIP)
1023 get_header_ptr = get_header_tar_gz;
1024
1025 if (opt & OPT_BZIP2)
1026 get_header_ptr = get_header_tar_bz2;
1027
1028 if (opt & OPT_LZMA)
1029 get_header_ptr = get_header_tar_lzma;
1030
1031 if (opt & OPT_COMPRESS)
1032 get_header_ptr = get_header_tar_Z;
1033
1034 if (opt & OPT_NOPRESERVE_TIME) 975 if (opt & OPT_NOPRESERVE_TIME)
1035 tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE; 976 tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE;
1036 977
@@ -1083,7 +1024,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1083 } else { 1024 } else {
1084 if (ENABLE_FEATURE_TAR_AUTODETECT 1025 if (ENABLE_FEATURE_TAR_AUTODETECT
1085 && flags == O_RDONLY 1026 && flags == O_RDONLY
1086 && get_header_ptr == get_header_tar 1027 && !(opt & OPT_ANY_COMPRESS)
1087 ) { 1028 ) {
1088 tar_handle->src_fd = open_zipped(tar_filename); 1029 tar_handle->src_fd = open_zipped(tar_filename);
1089 if (tar_handle->src_fd < 0) 1030 if (tar_handle->src_fd < 0)
@@ -1097,10 +1038,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1097 if (base_dir) 1038 if (base_dir)
1098 xchdir(base_dir); 1039 xchdir(base_dir);
1099 1040
1100#ifdef CHECK_FOR_CHILD_EXITCODE 1041 //if (SEAMLESS_COMPRESSION || OPT_COMPRESS)
1101 /* We need to know whether child (gzip/bzip/etc) exits abnormally */ 1042 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */
1102 signal(SIGCHLD, handle_SIGCHLD); 1043 // signal(SIGCHLD, check_errors_in_children);
1103#endif
1104 1044
1105 /* Create an archive */ 1045 /* Create an archive */
1106 if (opt & OPT_CREATE) { 1046 if (opt & OPT_CREATE) {
@@ -1117,7 +1057,30 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1117 tar_handle->reject, zipMode); 1057 tar_handle->reject, zipMode);
1118 } 1058 }
1119 1059
1120 while (get_header_ptr(tar_handle) == EXIT_SUCCESS) 1060 if (opt & OPT_ANY_COMPRESS) {
1061 USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);)
1062 USE_FOR_NOMMU(const char *xformer_prog;)
1063
1064 if (opt & OPT_COMPRESS)
1065 USE_FOR_MMU(xformer = unpack_Z_stream;)
1066 USE_FOR_NOMMU(xformer_prog = "uncompress";)
1067 if (opt & OPT_GZIP)
1068 USE_FOR_MMU(xformer = unpack_gz_stream;)
1069 USE_FOR_NOMMU(xformer_prog = "gunzip";)
1070 if (opt & OPT_BZIP2)
1071 USE_FOR_MMU(xformer = unpack_bz2_stream;)
1072 USE_FOR_NOMMU(xformer_prog = "bunzip2";)
1073 if (opt & OPT_LZMA)
1074 USE_FOR_MMU(xformer = unpack_lzma_stream;)
1075 USE_FOR_NOMMU(xformer_prog = "unlzma";)
1076
1077 open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog);
1078 /* Can't lseek over pipes */
1079 tar_handle->seek = seek_by_read;
1080 /*tar_handle->offset = 0; - already is */
1081 }
1082
1083 while (get_header_tar(tar_handle) == EXIT_SUCCESS)
1121 continue; 1084 continue;
1122 1085
1123 /* Check that every file that should have been extracted was */ 1086 /* Check that every file that should have been extracted was */
@@ -1133,5 +1096,11 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1133 if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */) 1096 if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */)
1134 close(tar_handle->src_fd); 1097 close(tar_handle->src_fd);
1135 1098
1099#if !ENABLE_PLATFORM_MINGW32
1100 if (SEAMLESS_COMPRESSION || OPT_COMPRESS) {
1101 check_errors_in_children(0);
1102 return bb_got_signal;
1103 }
1104#endif
1136 return EXIT_SUCCESS; 1105 return EXIT_SUCCESS;
1137} 1106}
diff --git a/archival/unzip.c b/archival/unzip.c
index 3a11f78a5..3c76cdafc 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -249,15 +249,17 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd)
249 bb_copyfd_exact_size(zip_fd, dst_fd, size); 249 bb_copyfd_exact_size(zip_fd, dst_fd, size);
250 } else { 250 } else {
251 /* Method 8 - inflate */ 251 /* Method 8 - inflate */
252 inflate_unzip_result res; 252 transformer_aux_data_t aux;
253 if (inflate_unzip(&res, zip_header->formatted.cmpsize, zip_fd, dst_fd) < 0) 253 init_transformer_aux_data(&aux);
254 aux.bytes_in = zip_header->formatted.cmpsize;
255 if (inflate_unzip(&aux, zip_fd, dst_fd) < 0)
254 bb_error_msg_and_die("inflate error"); 256 bb_error_msg_and_die("inflate error");
255 /* Validate decompression - crc */ 257 /* Validate decompression - crc */
256 if (zip_header->formatted.crc32 != (res.crc ^ 0xffffffffL)) { 258 if (zip_header->formatted.crc32 != (aux.crc32 ^ 0xffffffffL)) {
257 bb_error_msg_and_die("crc error"); 259 bb_error_msg_and_die("crc error");
258 } 260 }
259 /* Validate decompression - size */ 261 /* Validate decompression - size */
260 if (zip_header->formatted.ucmpsize != res.bytes_out) { 262 if (zip_header->formatted.ucmpsize != aux.bytes_out) {
261 /* Don't die. Who knows, maybe len calculation 263 /* Don't die. Who knows, maybe len calculation
262 * was botched somewhere. After all, crc matched! */ 264 * was botched somewhere. After all, crc matched! */
263 bb_error_msg("bad length"); 265 bb_error_msg("bad length");