diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2014-12-07 00:44:00 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-12-07 00:44:00 +0100 |
commit | b4c11c139717729b8257ee9382d4e5ed713d4dde (patch) | |
tree | 0b6c5edd491090c54b09657ef63c711a118a4e9d | |
parent | e7800f351ad9eca012fe27a1c9234692a04419e7 (diff) | |
download | busybox-w32-b4c11c139717729b8257ee9382d4e5ed713d4dde.tar.gz busybox-w32-b4c11c139717729b8257ee9382d4e5ed713d4dde.tar.bz2 busybox-w32-b4c11c139717729b8257ee9382d4e5ed713d4dde.zip |
libarchive: add capability to unpack to mem.buffer
The performance and number of processes for a "depmod -a" with gzipped
modules was abysmal. This patch adds a code path without fork,
benefiting all users of xmalloc_open_zipped_read_close.
"modinfo radeon.ko.gz", a single-file reader, got 30% faster.
"depmod -a", which used to fork over 800 times, got 20% faster.
Heavily based on a patch by Lauri Kasanen <curaga@operamail.com>
function old new delta
setup_transformer_on_fd - 159 +159
transformer_write - 122 +122
fork_transformer - 112 +112
xmalloc_open_zipped_read_close 63 118 +55
read_bunzip 1866 1896 +30
xtransformer_write - 19 +19
unzip_main 2449 2462 +13
bbunpack 755 766 +11
unpack_lzma_stream 2717 2723 +6
unpack_xz_stream 2393 2397 +4
unpack_Z_stream 1173 1175 +2
inflate_unzip 111 105 -6
check_signature16 70 63 -7
unpack_bz2_stream 359 349 -10
unpack_unxz 12 - -12
unpack_unlzma 12 - -12
unpack_uncompress 12 - -12
unpack_gunzip 12 - -12
unpack_bunzip2 12 - -12
open_transformer 106 92 -14
inflate_unzip_internal 1945 1916 -29
unpack_gz_stream 693 655 -38
open_zipped 89 47 -42
setup_unzip_on_fd 142 53 -89
------------------------------------------------------------------------------
(add/remove: 4/5 grow/shrink: 7/8 up/down: 533/-295) Total: 238 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/bbunzip.c | 37 | ||||
-rw-r--r-- | archival/libarchive/decompress_bunzip2.c | 11 | ||||
-rw-r--r-- | archival/libarchive/decompress_gunzip.c | 30 | ||||
-rw-r--r-- | archival/libarchive/decompress_uncompress.c | 12 | ||||
-rw-r--r-- | archival/libarchive/decompress_unlzma.c | 12 | ||||
-rw-r--r-- | archival/libarchive/decompress_unxz.c | 6 | ||||
-rw-r--r-- | archival/libarchive/get_header_tar_bz2.c | 2 | ||||
-rw-r--r-- | archival/libarchive/get_header_tar_gz.c | 2 | ||||
-rw-r--r-- | archival/libarchive/get_header_tar_lzma.c | 2 | ||||
-rw-r--r-- | archival/libarchive/open_transformer.c | 199 | ||||
-rw-r--r-- | archival/tar.c | 4 | ||||
-rw-r--r-- | archival/unzip.c | 4 | ||||
-rw-r--r-- | include/bb_archive.h | 42 | ||||
-rw-r--r-- | include/libbb.h | 3 |
14 files changed, 241 insertions, 125 deletions
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 84f58f138..90aac1427 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -122,6 +122,8 @@ int FAST_FUNC bbunpack(char **argv, | |||
122 | if (!(option_mask32 & SEAMLESS_MAGIC)) { | 122 | if (!(option_mask32 & SEAMLESS_MAGIC)) { |
123 | init_transformer_state(&xstate); | 123 | init_transformer_state(&xstate); |
124 | xstate.check_signature = 1; | 124 | xstate.check_signature = 1; |
125 | /*xstate.src_fd = STDIN_FILENO; - already is */ | ||
126 | xstate.dst_fd = STDOUT_FILENO; | ||
125 | status = unpacker(&xstate); | 127 | status = unpacker(&xstate); |
126 | if (status < 0) | 128 | if (status < 0) |
127 | exitcode = 1; | 129 | exitcode = 1; |
@@ -226,18 +228,13 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) | |||
226 | //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) | 228 | //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) |
227 | //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o | 229 | //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o |
228 | #if ENABLE_UNCOMPRESS | 230 | #if ENABLE_UNCOMPRESS |
229 | static | ||
230 | IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_state_t *xstate) | ||
231 | { | ||
232 | return unpack_Z_stream(xstate, STDIN_FILENO, STDOUT_FILENO); | ||
233 | } | ||
234 | int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 231 | int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
235 | int uncompress_main(int argc UNUSED_PARAM, char **argv) | 232 | int uncompress_main(int argc UNUSED_PARAM, char **argv) |
236 | { | 233 | { |
237 | getopt32(argv, "cf"); | 234 | getopt32(argv, "cf"); |
238 | argv += optind; | 235 | argv += optind; |
239 | 236 | ||
240 | return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z"); | 237 | return bbunpack(argv, unpack_Z_stream, make_new_name_generic, "Z"); |
241 | } | 238 | } |
242 | #endif | 239 | #endif |
243 | 240 | ||
@@ -324,11 +321,6 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN | |||
324 | } | 321 | } |
325 | return filename; | 322 | return filename; |
326 | } | 323 | } |
327 | static | ||
328 | IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_state_t *xstate) | ||
329 | { | ||
330 | return unpack_gz_stream(xstate, STDIN_FILENO, STDOUT_FILENO); | ||
331 | } | ||
332 | /* | 324 | /* |
333 | * Linux kernel build uses gzip -d -n. We accept and ignore it. | 325 | * Linux kernel build uses gzip -d -n. We accept and ignore it. |
334 | * Man page says: | 326 | * Man page says: |
@@ -355,7 +347,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
355 | if (applet_name[1] == 'c') | 347 | if (applet_name[1] == 'c') |
356 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; | 348 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; |
357 | 349 | ||
358 | return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); | 350 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); |
359 | } | 351 | } |
360 | #endif | 352 | #endif |
361 | 353 | ||
@@ -395,11 +387,6 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
395 | //kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o | 387 | //kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o |
396 | //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o | 388 | //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o |
397 | #if ENABLE_BUNZIP2 | 389 | #if ENABLE_BUNZIP2 |
398 | static | ||
399 | IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_state_t *xstate) | ||
400 | { | ||
401 | return unpack_bz2_stream(xstate, STDIN_FILENO, STDOUT_FILENO); | ||
402 | } | ||
403 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 390 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
404 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) | 391 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) |
405 | { | 392 | { |
@@ -408,7 +395,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
408 | if (applet_name[2] == 'c') /* bzcat */ | 395 | if (applet_name[2] == 'c') /* bzcat */ |
409 | option_mask32 |= OPT_STDOUT; | 396 | option_mask32 |= OPT_STDOUT; |
410 | 397 | ||
411 | return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2"); | 398 | return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2"); |
412 | } | 399 | } |
413 | #endif | 400 | #endif |
414 | 401 | ||
@@ -494,11 +481,6 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
494 | //applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) | 481 | //applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) |
495 | //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o | 482 | //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o |
496 | #if ENABLE_UNLZMA | 483 | #if ENABLE_UNLZMA |
497 | static | ||
498 | IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_state_t *xstate) | ||
499 | { | ||
500 | return unpack_lzma_stream(xstate, STDIN_FILENO, STDOUT_FILENO); | ||
501 | } | ||
502 | int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 484 | int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
503 | int unlzma_main(int argc UNUSED_PARAM, char **argv) | 485 | int unlzma_main(int argc UNUSED_PARAM, char **argv) |
504 | { | 486 | { |
@@ -513,7 +495,7 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
513 | option_mask32 |= OPT_STDOUT; | 495 | option_mask32 |= OPT_STDOUT; |
514 | 496 | ||
515 | argv += optind; | 497 | argv += optind; |
516 | return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma"); | 498 | return bbunpack(argv, unpack_lzma_stream, make_new_name_generic, "lzma"); |
517 | } | 499 | } |
518 | #endif | 500 | #endif |
519 | 501 | ||
@@ -537,11 +519,6 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
537 | //applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) | 519 | //applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) |
538 | //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o | 520 | //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o |
539 | #if ENABLE_UNXZ | 521 | #if ENABLE_UNXZ |
540 | static | ||
541 | IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_state_t *xstate) | ||
542 | { | ||
543 | return unpack_xz_stream(xstate, STDIN_FILENO, STDOUT_FILENO); | ||
544 | } | ||
545 | int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 522 | int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
546 | int unxz_main(int argc UNUSED_PARAM, char **argv) | 523 | int unxz_main(int argc UNUSED_PARAM, char **argv) |
547 | { | 524 | { |
@@ -556,6 +533,6 @@ int unxz_main(int argc UNUSED_PARAM, char **argv) | |||
556 | option_mask32 |= OPT_STDOUT; | 533 | option_mask32 |= OPT_STDOUT; |
557 | 534 | ||
558 | argv += optind; | 535 | argv += optind; |
559 | return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz"); | 536 | return bbunpack(argv, unpack_xz_stream, make_new_name_generic, "xz"); |
560 | } | 537 | } |
561 | #endif | 538 | #endif |
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 36237e221..fe5953da2 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c | |||
@@ -731,7 +731,7 @@ void FAST_FUNC dealloc_bunzip(bunzip_data *bd) | |||
731 | 731 | ||
732 | /* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ | 732 | /* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ |
733 | IF_DESKTOP(long long) int FAST_FUNC | 733 | IF_DESKTOP(long long) int FAST_FUNC |
734 | unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | 734 | unpack_bz2_stream(transformer_state_t *xstate) |
735 | { | 735 | { |
736 | IF_DESKTOP(long long total_written = 0;) | 736 | IF_DESKTOP(long long total_written = 0;) |
737 | bunzip_data *bd; | 737 | bunzip_data *bd; |
@@ -739,14 +739,14 @@ unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
739 | int i; | 739 | int i; |
740 | unsigned len; | 740 | unsigned len; |
741 | 741 | ||
742 | if (check_signature16(xstate, src_fd, BZIP2_MAGIC)) | 742 | if (check_signature16(xstate, BZIP2_MAGIC)) |
743 | return -1; | 743 | return -1; |
744 | 744 | ||
745 | outbuf = xmalloc(IOBUF_SIZE); | 745 | outbuf = xmalloc(IOBUF_SIZE); |
746 | len = 0; | 746 | len = 0; |
747 | while (1) { /* "Process one BZ... stream" loop */ | 747 | while (1) { /* "Process one BZ... stream" loop */ |
748 | 748 | ||
749 | i = start_bunzip(&bd, src_fd, outbuf + 2, len); | 749 | i = start_bunzip(&bd, xstate->src_fd, outbuf + 2, len); |
750 | 750 | ||
751 | if (i == 0) { | 751 | if (i == 0) { |
752 | while (1) { /* "Produce some output bytes" loop */ | 752 | while (1) { /* "Produce some output bytes" loop */ |
@@ -756,8 +756,7 @@ unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
756 | i = IOBUF_SIZE - i; /* number of bytes produced */ | 756 | i = IOBUF_SIZE - i; /* number of bytes produced */ |
757 | if (i == 0) /* EOF? */ | 757 | if (i == 0) /* EOF? */ |
758 | break; | 758 | break; |
759 | if (i != full_write(dst_fd, outbuf, i)) { | 759 | if (i != transformer_write(xstate, outbuf, i)) { |
760 | bb_error_msg("short write"); | ||
761 | i = RETVAL_SHORT_WRITE; | 760 | i = RETVAL_SHORT_WRITE; |
762 | goto release_mem; | 761 | goto release_mem; |
763 | } | 762 | } |
@@ -790,7 +789,7 @@ unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
790 | len = bd->inbufCount - bd->inbufPos; | 789 | len = bd->inbufCount - bd->inbufPos; |
791 | memcpy(outbuf, &bd->inbuf[bd->inbufPos], len); | 790 | memcpy(outbuf, &bd->inbuf[bd->inbufPos], len); |
792 | if (len < 2) { | 791 | if (len < 2) { |
793 | if (safe_read(src_fd, outbuf + len, 2 - len) != 2 - len) | 792 | if (safe_read(xstate->src_fd, outbuf + len, 2 - len) != 2 - len) |
794 | break; | 793 | break; |
795 | len = 2; | 794 | len = 2; |
796 | } | 795 | } |
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 62a3d78b6..1360abef7 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c | |||
@@ -971,7 +971,7 @@ static int inflate_get_next_window(STATE_PARAM_ONLY) | |||
971 | 971 | ||
972 | /* Called from unpack_gz_stream() and inflate_unzip() */ | 972 | /* Called from unpack_gz_stream() and inflate_unzip() */ |
973 | static IF_DESKTOP(long long) int | 973 | static IF_DESKTOP(long long) int |
974 | inflate_unzip_internal(STATE_PARAM int in, int out) | 974 | inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate) |
975 | { | 975 | { |
976 | IF_DESKTOP(long long) int n = 0; | 976 | IF_DESKTOP(long long) int n = 0; |
977 | ssize_t nwrote; | 977 | ssize_t nwrote; |
@@ -980,7 +980,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
980 | gunzip_window = xmalloc(GUNZIP_WSIZE); | 980 | gunzip_window = xmalloc(GUNZIP_WSIZE); |
981 | gunzip_outbuf_count = 0; | 981 | gunzip_outbuf_count = 0; |
982 | gunzip_bytes_out = 0; | 982 | gunzip_bytes_out = 0; |
983 | gunzip_src_fd = in; | 983 | gunzip_src_fd = xstate->src_fd; |
984 | 984 | ||
985 | /* (re) initialize state */ | 985 | /* (re) initialize state */ |
986 | method = -1; | 986 | method = -1; |
@@ -1002,9 +1002,8 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
1002 | 1002 | ||
1003 | while (1) { | 1003 | while (1) { |
1004 | int r = inflate_get_next_window(PASS_STATE_ONLY); | 1004 | int r = inflate_get_next_window(PASS_STATE_ONLY); |
1005 | nwrote = full_write(out, gunzip_window, gunzip_outbuf_count); | 1005 | nwrote = transformer_write(xstate, gunzip_window, gunzip_outbuf_count); |
1006 | if (nwrote != (ssize_t)gunzip_outbuf_count) { | 1006 | if (nwrote == (ssize_t)-1) { |
1007 | bb_perror_msg("write"); | ||
1008 | n = -1; | 1007 | n = -1; |
1009 | goto ret; | 1008 | goto ret; |
1010 | } | 1009 | } |
@@ -1034,7 +1033,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
1034 | /* For unzip */ | 1033 | /* For unzip */ |
1035 | 1034 | ||
1036 | IF_DESKTOP(long long) int FAST_FUNC | 1035 | IF_DESKTOP(long long) int FAST_FUNC |
1037 | inflate_unzip(transformer_state_t *xstate, int in, int out) | 1036 | inflate_unzip(transformer_state_t *xstate) |
1038 | { | 1037 | { |
1039 | IF_DESKTOP(long long) int n; | 1038 | IF_DESKTOP(long long) int n; |
1040 | DECLARE_STATE; | 1039 | DECLARE_STATE; |
@@ -1045,7 +1044,7 @@ inflate_unzip(transformer_state_t *xstate, int in, int out) | |||
1045 | // bytebuffer_max = 0x8000; | 1044 | // bytebuffer_max = 0x8000; |
1046 | bytebuffer_offset = 4; | 1045 | bytebuffer_offset = 4; |
1047 | bytebuffer = xmalloc(bytebuffer_max); | 1046 | bytebuffer = xmalloc(bytebuffer_max); |
1048 | n = inflate_unzip_internal(PASS_STATE in, out); | 1047 | n = inflate_unzip_internal(PASS_STATE xstate); |
1049 | free(bytebuffer); | 1048 | free(bytebuffer); |
1050 | 1049 | ||
1051 | xstate->crc32 = gunzip_crc; | 1050 | xstate->crc32 = gunzip_crc; |
@@ -1169,8 +1168,7 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) | |||
1169 | } | 1168 | } |
1170 | } | 1169 | } |
1171 | 1170 | ||
1172 | if (xstate) | 1171 | xstate->mtime = SWAP_LE32(header.formatted.mtime); |
1173 | xstate->mtime = SWAP_LE32(header.formatted.mtime); | ||
1174 | 1172 | ||
1175 | /* Read the header checksum */ | 1173 | /* Read the header checksum */ |
1176 | if (header.formatted.flags & 0x02) { | 1174 | if (header.formatted.flags & 0x02) { |
@@ -1182,27 +1180,27 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) | |||
1182 | } | 1180 | } |
1183 | 1181 | ||
1184 | IF_DESKTOP(long long) int FAST_FUNC | 1182 | IF_DESKTOP(long long) int FAST_FUNC |
1185 | unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | 1183 | unpack_gz_stream(transformer_state_t *xstate) |
1186 | { | 1184 | { |
1187 | uint32_t v32; | 1185 | uint32_t v32; |
1188 | IF_DESKTOP(long long) int total, n; | 1186 | IF_DESKTOP(long long) int total, n; |
1189 | DECLARE_STATE; | 1187 | DECLARE_STATE; |
1190 | 1188 | ||
1191 | #if !ENABLE_FEATURE_SEAMLESS_Z | 1189 | #if !ENABLE_FEATURE_SEAMLESS_Z |
1192 | if (check_signature16(xstate, src_fd, GZIP_MAGIC)) | 1190 | if (check_signature16(xstate, GZIP_MAGIC)) |
1193 | return -1; | 1191 | return -1; |
1194 | #else | 1192 | #else |
1195 | if (xstate && xstate->check_signature) { | 1193 | if (xstate->check_signature) { |
1196 | uint16_t magic2; | 1194 | uint16_t magic2; |
1197 | 1195 | ||
1198 | if (full_read(src_fd, &magic2, 2) != 2) { | 1196 | if (full_read(xstate->src_fd, &magic2, 2) != 2) { |
1199 | bad_magic: | 1197 | bad_magic: |
1200 | bb_error_msg("invalid magic"); | 1198 | bb_error_msg("invalid magic"); |
1201 | return -1; | 1199 | return -1; |
1202 | } | 1200 | } |
1203 | if (magic2 == COMPRESS_MAGIC) { | 1201 | if (magic2 == COMPRESS_MAGIC) { |
1204 | xstate->check_signature = 0; | 1202 | xstate->check_signature = 0; |
1205 | return unpack_Z_stream(xstate, src_fd, dst_fd); | 1203 | return unpack_Z_stream(xstate); |
1206 | } | 1204 | } |
1207 | if (magic2 != GZIP_MAGIC) | 1205 | if (magic2 != GZIP_MAGIC) |
1208 | goto bad_magic; | 1206 | goto bad_magic; |
@@ -1215,7 +1213,7 @@ unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
1215 | to_read = -1; | 1213 | to_read = -1; |
1216 | // bytebuffer_max = 0x8000; | 1214 | // bytebuffer_max = 0x8000; |
1217 | bytebuffer = xmalloc(bytebuffer_max); | 1215 | bytebuffer = xmalloc(bytebuffer_max); |
1218 | gunzip_src_fd = src_fd; | 1216 | gunzip_src_fd = xstate->src_fd; |
1219 | 1217 | ||
1220 | again: | 1218 | again: |
1221 | if (!check_header_gzip(PASS_STATE xstate)) { | 1219 | if (!check_header_gzip(PASS_STATE xstate)) { |
@@ -1224,7 +1222,7 @@ unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
1224 | goto ret; | 1222 | goto ret; |
1225 | } | 1223 | } |
1226 | 1224 | ||
1227 | n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd); | 1225 | n = inflate_unzip_internal(PASS_STATE xstate); |
1228 | if (n < 0) { | 1226 | if (n < 0) { |
1229 | total = -1; | 1227 | total = -1; |
1230 | goto ret; | 1228 | goto ret; |
diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c index cb3d55a88..496d864a7 100644 --- a/archival/libarchive/decompress_uncompress.c +++ b/archival/libarchive/decompress_uncompress.c | |||
@@ -73,7 +73,7 @@ | |||
73 | */ | 73 | */ |
74 | 74 | ||
75 | IF_DESKTOP(long long) int FAST_FUNC | 75 | IF_DESKTOP(long long) int FAST_FUNC |
76 | unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | 76 | unpack_Z_stream(transformer_state_t *xstate) |
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; |
@@ -102,7 +102,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
102 | /* block compress mode -C compatible with 2.0 */ | 102 | /* block compress mode -C compatible with 2.0 */ |
103 | int block_mode; /* = BLOCK_MODE; */ | 103 | int block_mode; /* = BLOCK_MODE; */ |
104 | 104 | ||
105 | if (check_signature16(xstate, src_fd, COMPRESS_MAGIC)) | 105 | if (check_signature16(xstate, COMPRESS_MAGIC)) |
106 | return -1; | 106 | return -1; |
107 | 107 | ||
108 | inbuf = xzalloc(IBUFSIZ + 64); | 108 | inbuf = xzalloc(IBUFSIZ + 64); |
@@ -114,7 +114,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
114 | 114 | ||
115 | /* xread isn't good here, we have to return - caller may want | 115 | /* xread isn't good here, we have to return - caller may want |
116 | * to do some cleanup (e.g. delete incomplete unpacked file etc) */ | 116 | * to do some cleanup (e.g. delete incomplete unpacked file etc) */ |
117 | if (full_read(src_fd, inbuf, 1) != 1) { | 117 | if (full_read(xstate->src_fd, inbuf, 1) != 1) { |
118 | bb_error_msg("short read"); | 118 | bb_error_msg("short read"); |
119 | goto err; | 119 | goto err; |
120 | } | 120 | } |
@@ -166,7 +166,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
166 | } | 166 | } |
167 | 167 | ||
168 | if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { | 168 | if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { |
169 | rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ); | 169 | rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ); |
170 | if (rsize < 0) | 170 | if (rsize < 0) |
171 | bb_error_msg_and_die(bb_msg_read_error); | 171 | bb_error_msg_and_die(bb_msg_read_error); |
172 | insize += rsize; | 172 | insize += rsize; |
@@ -274,7 +274,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
274 | } | 274 | } |
275 | 275 | ||
276 | if (outpos >= OBUFSIZ) { | 276 | if (outpos >= OBUFSIZ) { |
277 | xwrite(dst_fd, outbuf, outpos); | 277 | xtransformer_write(xstate, outbuf, outpos); |
278 | IF_DESKTOP(total_written += outpos;) | 278 | IF_DESKTOP(total_written += outpos;) |
279 | outpos = 0; | 279 | outpos = 0; |
280 | } | 280 | } |
@@ -301,7 +301,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
301 | } while (rsize > 0); | 301 | } while (rsize > 0); |
302 | 302 | ||
303 | if (outpos > 0) { | 303 | if (outpos > 0) { |
304 | xwrite(dst_fd, outbuf, outpos); | 304 | xtransformer_write(xstate, outbuf, outpos); |
305 | IF_DESKTOP(total_written += outpos;) | 305 | IF_DESKTOP(total_written += outpos;) |
306 | } | 306 | } |
307 | 307 | ||
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index ccedac49d..c8622f97b 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c | |||
@@ -206,7 +206,7 @@ enum { | |||
206 | 206 | ||
207 | 207 | ||
208 | IF_DESKTOP(long long) int FAST_FUNC | 208 | IF_DESKTOP(long long) int FAST_FUNC |
209 | unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst_fd) | 209 | unpack_lzma_stream(transformer_state_t *xstate) |
210 | { | 210 | { |
211 | IF_DESKTOP(long long total_written = 0;) | 211 | IF_DESKTOP(long long total_written = 0;) |
212 | lzma_header_t header; | 212 | lzma_header_t header; |
@@ -223,7 +223,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst | |||
223 | int state = 0; | 223 | int state = 0; |
224 | uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; | 224 | uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; |
225 | 225 | ||
226 | if (full_read(src_fd, &header, sizeof(header)) != sizeof(header) | 226 | if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header) |
227 | || header.pos >= (9 * 5 * 5) | 227 | || header.pos >= (9 * 5 * 5) |
228 | ) { | 228 | ) { |
229 | bb_error_msg("bad lzma header"); | 229 | bb_error_msg("bad lzma header"); |
@@ -258,7 +258,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst | |||
258 | p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; | 258 | p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; |
259 | } | 259 | } |
260 | 260 | ||
261 | rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */ | 261 | rc = rc_init(xstate->src_fd); /*, RC_BUFFER_SIZE); */ |
262 | 262 | ||
263 | while (global_pos + buffer_pos < header.dst_size) { | 263 | while (global_pos + buffer_pos < header.dst_size) { |
264 | int pos_state = (buffer_pos + global_pos) & pos_state_mask; | 264 | int pos_state = (buffer_pos + global_pos) & pos_state_mask; |
@@ -306,7 +306,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst | |||
306 | if (buffer_pos == header.dict_size) { | 306 | if (buffer_pos == header.dict_size) { |
307 | buffer_pos = 0; | 307 | buffer_pos = 0; |
308 | global_pos += header.dict_size; | 308 | global_pos += header.dict_size; |
309 | if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size) | 309 | if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size) |
310 | goto bad; | 310 | goto bad; |
311 | IF_DESKTOP(total_written += header.dict_size;) | 311 | IF_DESKTOP(total_written += header.dict_size;) |
312 | } | 312 | } |
@@ -440,7 +440,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst | |||
440 | if (buffer_pos == header.dict_size) { | 440 | if (buffer_pos == header.dict_size) { |
441 | buffer_pos = 0; | 441 | buffer_pos = 0; |
442 | global_pos += header.dict_size; | 442 | global_pos += header.dict_size; |
443 | if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size) | 443 | if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size) |
444 | goto bad; | 444 | goto bad; |
445 | IF_DESKTOP(total_written += header.dict_size;) | 445 | IF_DESKTOP(total_written += header.dict_size;) |
446 | } | 446 | } |
@@ -455,7 +455,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst | |||
455 | { | 455 | { |
456 | IF_NOT_DESKTOP(int total_written = 0; /* success */) | 456 | IF_NOT_DESKTOP(int total_written = 0; /* success */) |
457 | IF_DESKTOP(total_written += buffer_pos;) | 457 | IF_DESKTOP(total_written += buffer_pos;) |
458 | if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) { | 458 | if (transformer_write(xstate, buffer, buffer_pos) != (ssize_t)buffer_pos) { |
459 | bad: | 459 | bad: |
460 | total_written = -1; /* failure */ | 460 | total_written = -1; /* failure */ |
461 | } | 461 | } |
diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 6df54e131..1f408abfd 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 | ||
40 | IF_DESKTOP(long long) int FAST_FUNC | 40 | IF_DESKTOP(long long) int FAST_FUNC |
41 | unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | 41 | unpack_xz_stream(transformer_state_t *xstate) |
42 | { | 42 | { |
43 | enum xz_ret xz_result; | 43 | enum xz_ret xz_result; |
44 | struct xz_buf iobuf; | 44 | struct xz_buf iobuf; |
@@ -67,7 +67,7 @@ unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
67 | xz_result = X_OK; | 67 | xz_result = X_OK; |
68 | while (1) { | 68 | while (1) { |
69 | if (iobuf.in_pos == iobuf.in_size) { | 69 | if (iobuf.in_pos == iobuf.in_size) { |
70 | int rd = safe_read(src_fd, membuf, BUFSIZ); | 70 | int rd = safe_read(xstate->src_fd, membuf, BUFSIZ); |
71 | if (rd < 0) { | 71 | if (rd < 0) { |
72 | bb_error_msg(bb_msg_read_error); | 72 | bb_error_msg(bb_msg_read_error); |
73 | total = -1; | 73 | total = -1; |
@@ -104,7 +104,7 @@ unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) | |||
104 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", | 104 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", |
105 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, xz_result); | 105 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, xz_result); |
106 | if (iobuf.out_pos) { | 106 | if (iobuf.out_pos) { |
107 | xwrite(dst_fd, iobuf.out, iobuf.out_pos); | 107 | xtransformer_write(xstate, iobuf.out, iobuf.out_pos); |
108 | IF_DESKTOP(total += iobuf.out_pos;) | 108 | IF_DESKTOP(total += iobuf.out_pos;) |
109 | iobuf.out_pos = 0; | 109 | iobuf.out_pos = 0; |
110 | } | 110 | } |
diff --git a/archival/libarchive/get_header_tar_bz2.c b/archival/libarchive/get_header_tar_bz2.c index 0ee00df53..78f78a858 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_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2"); | 14 | fork_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 03284342b..b11f503dc 100644 --- a/archival/libarchive/get_header_tar_gz.c +++ b/archival/libarchive/get_header_tar_gz.c | |||
@@ -11,7 +11,7 @@ char FAST_FUNC get_header_tar_gz(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_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip"); | 14 | fork_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip"); |
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_lzma.c b/archival/libarchive/get_header_tar_lzma.c index d565a217d..d228cbc13 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_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma"); | 17 | fork_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 584b15de4..9d762a859 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -11,11 +11,11 @@ void FAST_FUNC init_transformer_state(transformer_state_t *xstate) | |||
11 | memset(xstate, 0, sizeof(*xstate)); | 11 | memset(xstate, 0, sizeof(*xstate)); |
12 | } | 12 | } |
13 | 13 | ||
14 | int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigned magic16) | 14 | int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) |
15 | { | 15 | { |
16 | if (xstate && xstate->check_signature) { | 16 | if (xstate->check_signature) { |
17 | uint16_t magic2; | 17 | uint16_t magic2; |
18 | if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) { | 18 | if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { |
19 | bb_error_msg("invalid magic"); | 19 | bb_error_msg("invalid magic"); |
20 | #if 0 /* possible future extension */ | 20 | #if 0 /* possible future extension */ |
21 | if (xstate->check_signature > 1) | 21 | if (xstate->check_signature > 1) |
@@ -27,6 +27,46 @@ int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigne | |||
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | 29 | ||
30 | ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) | ||
31 | { | ||
32 | ssize_t nwrote; | ||
33 | |||
34 | if (xstate->mem_output_size_max != 0) { | ||
35 | size_t pos = xstate->mem_output_size; | ||
36 | size_t size; | ||
37 | |||
38 | size = (xstate->mem_output_size += bufsize); | ||
39 | if (size > xstate->mem_output_size_max) { | ||
40 | free(xstate->mem_output_buf); | ||
41 | xstate->mem_output_buf = NULL; | ||
42 | bb_perror_msg("buffer %u too small", (unsigned)xstate->mem_output_size_max); | ||
43 | nwrote = -1; | ||
44 | goto ret; | ||
45 | } | ||
46 | xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size); | ||
47 | memcpy(xstate->mem_output_buf + pos, buf, bufsize); | ||
48 | nwrote = bufsize; | ||
49 | } else { | ||
50 | nwrote = full_write(xstate->dst_fd, buf, bufsize); | ||
51 | if (nwrote != (ssize_t)bufsize) { | ||
52 | bb_perror_msg("write"); | ||
53 | nwrote = -1; | ||
54 | goto ret; | ||
55 | } | ||
56 | } | ||
57 | ret: | ||
58 | return nwrote; | ||
59 | } | ||
60 | |||
61 | ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) | ||
62 | { | ||
63 | ssize_t nwrote = transformer_write(xstate, buf, bufsize); | ||
64 | if (nwrote != (ssize_t)bufsize) { | ||
65 | xfunc_die(); | ||
66 | } | ||
67 | return nwrote; | ||
68 | } | ||
69 | |||
30 | void check_errors_in_children(int signo) | 70 | void check_errors_in_children(int signo) |
31 | { | 71 | { |
32 | int status; | 72 | int status; |
@@ -60,12 +100,12 @@ void check_errors_in_children(int signo) | |||
60 | 100 | ||
61 | /* transformer(), more than meets the eye */ | 101 | /* transformer(), more than meets the eye */ |
62 | #if BB_MMU | 102 | #if BB_MMU |
63 | void FAST_FUNC open_transformer(int fd, | 103 | void FAST_FUNC fork_transformer(int fd, |
64 | int check_signature, | 104 | int check_signature, |
65 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate, int src_fd, int dst_fd) | 105 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) |
66 | ) | 106 | ) |
67 | #else | 107 | #else |
68 | void FAST_FUNC open_transformer(int fd, const char *transform_prog) | 108 | void FAST_FUNC fork_transformer(int fd, const char *transform_prog) |
69 | #endif | 109 | #endif |
70 | { | 110 | { |
71 | struct fd_pair fd_pipe; | 111 | struct fd_pair fd_pipe; |
@@ -83,7 +123,9 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog) | |||
83 | transformer_state_t xstate; | 123 | transformer_state_t xstate; |
84 | init_transformer_state(&xstate); | 124 | init_transformer_state(&xstate); |
85 | xstate.check_signature = check_signature; | 125 | xstate.check_signature = check_signature; |
86 | r = transformer(&xstate, fd, fd_pipe.wr); | 126 | xstate.src_fd = fd; |
127 | xstate.dst_fd = fd_pipe.wr; | ||
128 | r = transformer(&xstate); | ||
87 | if (ENABLE_FEATURE_CLEAN_UP) { | 129 | if (ENABLE_FEATURE_CLEAN_UP) { |
88 | close(fd_pipe.wr); /* send EOF */ | 130 | close(fd_pipe.wr); /* send EOF */ |
89 | close(fd); | 131 | close(fd); |
@@ -118,16 +160,19 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog) | |||
118 | /* Used by e.g. rpm which gives us a fd without filename, | 160 | /* Used by e.g. rpm which gives us a fd without filename, |
119 | * thus we can't guess the format from filename's extension. | 161 | * thus we can't guess the format from filename's extension. |
120 | */ | 162 | */ |
121 | int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | 163 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) |
122 | { | 164 | { |
123 | union { | 165 | union { |
124 | uint8_t b[4]; | 166 | uint8_t b[4]; |
125 | uint16_t b16[2]; | 167 | uint16_t b16[2]; |
126 | uint32_t b32[1]; | 168 | uint32_t b32[1]; |
127 | } magic; | 169 | } magic; |
128 | int offset = -2; | 170 | int offset; |
129 | USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate, int src_fd, int dst_fd);) | 171 | transformer_state_t *xstate; |
130 | USE_FOR_NOMMU(const char *xformer_prog;) | 172 | |
173 | offset = -2; | ||
174 | xstate = xzalloc(sizeof(*xstate)); | ||
175 | xstate->src_fd = fd; | ||
131 | 176 | ||
132 | /* .gz and .bz2 both have 2-byte signature, and their | 177 | /* .gz and .bz2 both have 2-byte signature, and their |
133 | * unpack_XXX_stream wants this header skipped. */ | 178 | * unpack_XXX_stream wants this header skipped. */ |
@@ -135,15 +180,15 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | |||
135 | if (ENABLE_FEATURE_SEAMLESS_GZ | 180 | if (ENABLE_FEATURE_SEAMLESS_GZ |
136 | && magic.b16[0] == GZIP_MAGIC | 181 | && magic.b16[0] == GZIP_MAGIC |
137 | ) { | 182 | ) { |
138 | USE_FOR_MMU(xformer = unpack_gz_stream;) | 183 | xstate->xformer = unpack_gz_stream; |
139 | USE_FOR_NOMMU(xformer_prog = "gunzip";) | 184 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) |
140 | goto found_magic; | 185 | goto found_magic; |
141 | } | 186 | } |
142 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | 187 | if (ENABLE_FEATURE_SEAMLESS_BZ2 |
143 | && magic.b16[0] == BZIP2_MAGIC | 188 | && magic.b16[0] == BZIP2_MAGIC |
144 | ) { | 189 | ) { |
145 | USE_FOR_MMU(xformer = unpack_bz2_stream;) | 190 | xstate->xformer = unpack_bz2_stream; |
146 | USE_FOR_NOMMU(xformer_prog = "bunzip2";) | 191 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) |
147 | goto found_magic; | 192 | goto found_magic; |
148 | } | 193 | } |
149 | if (ENABLE_FEATURE_SEAMLESS_XZ | 194 | if (ENABLE_FEATURE_SEAMLESS_XZ |
@@ -152,8 +197,8 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | |||
152 | offset = -6; | 197 | offset = -6; |
153 | xread(fd, magic.b32, sizeof(magic.b32[0])); | 198 | xread(fd, magic.b32, sizeof(magic.b32[0])); |
154 | if (magic.b32[0] == XZ_MAGIC2) { | 199 | if (magic.b32[0] == XZ_MAGIC2) { |
155 | USE_FOR_MMU(xformer = unpack_xz_stream;) | 200 | xstate->xformer = unpack_xz_stream; |
156 | USE_FOR_NOMMU(xformer_prog = "unxz";) | 201 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) |
157 | goto found_magic; | 202 | goto found_magic; |
158 | } | 203 | } |
159 | } | 204 | } |
@@ -164,52 +209,130 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | |||
164 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | 209 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") |
165 | IF_FEATURE_SEAMLESS_XZ("/xz") | 210 | IF_FEATURE_SEAMLESS_XZ("/xz") |
166 | " magic"); | 211 | " magic"); |
212 | |||
213 | /* Some callers expect this function to "consume" fd | ||
214 | * even if data is not compressed. In this case, | ||
215 | * we return a state with trivial transformer. | ||
216 | */ | ||
217 | // USE_FOR_MMU(xstate->xformer = copy_stream;) | ||
218 | // USE_FOR_NOMMU(xstate->xformer_prog = "cat";) | ||
219 | /* fall through to seeking bck over bytes we read earlier */ | ||
220 | |||
221 | USE_FOR_NOMMU(found_magic:) | ||
222 | /* NOMMU version of fork_transformer execs | ||
223 | * an external unzipper that wants | ||
224 | * file position at the start of the file. | ||
225 | */ | ||
167 | xlseek(fd, offset, SEEK_CUR); | 226 | xlseek(fd, offset, SEEK_CUR); |
168 | return 1; | ||
169 | 227 | ||
170 | found_magic: | 228 | USE_FOR_MMU(found_magic:) |
229 | /* In MMU case, if magic was found, seeking back is not necessary */ | ||
230 | |||
231 | return xstate; | ||
232 | } | ||
233 | |||
234 | /* Used by e.g. rpm which gives us a fd without filename, | ||
235 | * thus we can't guess the format from filename's extension. | ||
236 | */ | ||
237 | int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | ||
238 | { | ||
239 | transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); | ||
240 | |||
241 | if (!xstate || !xstate->xformer) { | ||
242 | free(xstate); | ||
243 | return 1; | ||
244 | } | ||
245 | |||
171 | # if BB_MMU | 246 | # if BB_MMU |
172 | open_transformer_with_no_sig(fd, xformer); | 247 | fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); |
173 | # else | 248 | # else |
174 | /* NOMMU version of open_transformer execs | 249 | fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); |
175 | * an external unzipper that wants | ||
176 | * file position at the start of the file */ | ||
177 | xlseek(fd, offset, SEEK_CUR); | ||
178 | open_transformer_with_sig(fd, xformer, xformer_prog); | ||
179 | # endif | 250 | # endif |
251 | free(xstate); | ||
180 | return 0; | 252 | return 0; |
181 | } | 253 | } |
182 | 254 | ||
183 | int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) | 255 | static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed) |
184 | { | 256 | { |
257 | transformer_state_t *xstate; | ||
185 | int fd; | 258 | int fd; |
186 | 259 | ||
187 | fd = open(fname, O_RDONLY); | 260 | fd = open(fname, O_RDONLY); |
188 | if (fd < 0) | 261 | if (fd < 0) |
189 | return fd; | 262 | return NULL; |
190 | 263 | ||
191 | if (ENABLE_FEATURE_SEAMLESS_LZMA) { | 264 | if (ENABLE_FEATURE_SEAMLESS_LZMA) { |
192 | /* .lzma has no header/signature, can only detect it by extension */ | 265 | /* .lzma has no header/signature, can only detect it by extension */ |
193 | char *sfx = strrchr(fname, '.'); | 266 | char *sfx = strrchr(fname, '.'); |
194 | if (sfx && strcmp(sfx+1, "lzma") == 0) { | 267 | if (sfx && strcmp(sfx+1, "lzma") == 0) { |
195 | open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma"); | 268 | xstate = xzalloc(sizeof(*xstate)); |
196 | return fd; | 269 | xstate->src_fd = fd; |
270 | xstate->xformer = unpack_lzma_stream; | ||
271 | USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";) | ||
272 | return xstate; | ||
197 | } | 273 | } |
198 | } | 274 | } |
199 | if ((ENABLE_FEATURE_SEAMLESS_GZ) | 275 | |
200 | || (ENABLE_FEATURE_SEAMLESS_BZ2) | 276 | xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); |
201 | || (ENABLE_FEATURE_SEAMLESS_XZ) | 277 | |
202 | ) { | 278 | return xstate; |
203 | setup_unzip_on_fd(fd, fail_if_not_compressed); | 279 | } |
280 | |||
281 | int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) | ||
282 | { | ||
283 | int fd; | ||
284 | transformer_state_t *xstate; | ||
285 | |||
286 | xstate = open_transformer(fname, fail_if_not_compressed); | ||
287 | if (!xstate) | ||
288 | return -1; | ||
289 | |||
290 | fd = xstate->src_fd; | ||
291 | if (xstate->xformer) { | ||
292 | # if BB_MMU | ||
293 | fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); | ||
294 | # else | ||
295 | fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); | ||
296 | # endif | ||
204 | } | 297 | } |
298 | /* else: the file is not compressed */ | ||
205 | 299 | ||
300 | free(xstate); | ||
206 | return fd; | 301 | return fd; |
207 | } | 302 | } |
208 | 303 | ||
209 | #endif /* SEAMLESS_COMPRESSION */ | ||
210 | |||
211 | void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) | 304 | void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) |
212 | { | 305 | { |
306 | # if 1 | ||
307 | transformer_state_t *xstate; | ||
308 | char *image; | ||
309 | |||
310 | xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0); | ||
311 | if (!xstate) /* file open error */ | ||
312 | return NULL; | ||
313 | |||
314 | image = NULL; | ||
315 | if (xstate->xformer) { | ||
316 | /* In-memory decompression */ | ||
317 | xstate->mem_output_size_max = maxsz_p ? *maxsz_p : (size_t)(INT_MAX - 4095); | ||
318 | xstate->xformer(xstate); | ||
319 | if (xstate->mem_output_buf) { | ||
320 | image = xstate->mem_output_buf; | ||
321 | if (maxsz_p) | ||
322 | *maxsz_p = xstate->mem_output_size; | ||
323 | } | ||
324 | } else { | ||
325 | /* File is not compressed */ | ||
326 | image = xmalloc_read(xstate->src_fd, maxsz_p); | ||
327 | } | ||
328 | |||
329 | if (!image) | ||
330 | bb_perror_msg("read error from '%s'", fname); | ||
331 | close(xstate->src_fd); | ||
332 | free(xstate); | ||
333 | return image; | ||
334 | # else | ||
335 | /* This version forks a subprocess - much more expensive */ | ||
213 | int fd; | 336 | int fd; |
214 | char *image; | 337 | char *image; |
215 | 338 | ||
@@ -221,6 +344,8 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ | |||
221 | if (!image) | 344 | if (!image) |
222 | bb_perror_msg("read error from '%s'", fname); | 345 | bb_perror_msg("read error from '%s'", fname); |
223 | close(fd); | 346 | close(fd); |
224 | |||
225 | return image; | 347 | return image; |
348 | # endif | ||
226 | } | 349 | } |
350 | |||
351 | #endif /* SEAMLESS_COMPRESSION */ | ||
diff --git a/archival/tar.c b/archival/tar.c index 7897a4af6..5bd473aac 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -1171,7 +1171,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | if (opt & OPT_ANY_COMPRESS) { | 1173 | if (opt & OPT_ANY_COMPRESS) { |
1174 | USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate, int src_fd, int dst_fd);) | 1174 | USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);) |
1175 | USE_FOR_NOMMU(const char *xformer_prog;) | 1175 | USE_FOR_NOMMU(const char *xformer_prog;) |
1176 | 1176 | ||
1177 | if (opt & OPT_COMPRESS) | 1177 | if (opt & OPT_COMPRESS) |
@@ -1190,7 +1190,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1190 | USE_FOR_MMU(xformer = unpack_xz_stream;) | 1190 | USE_FOR_MMU(xformer = unpack_xz_stream;) |
1191 | USE_FOR_NOMMU(xformer_prog = "unxz";) | 1191 | USE_FOR_NOMMU(xformer_prog = "unxz";) |
1192 | 1192 | ||
1193 | open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); | 1193 | fork_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); |
1194 | /* Can't lseek over pipes */ | 1194 | /* Can't lseek over pipes */ |
1195 | tar_handle->seek = seek_by_read; | 1195 | tar_handle->seek = seek_by_read; |
1196 | /*tar_handle->offset = 0; - already is */ | 1196 | /*tar_handle->offset = 0; - already is */ |
diff --git a/archival/unzip.c b/archival/unzip.c index c622bde57..38a07e212 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -283,7 +283,9 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd) | |||
283 | transformer_state_t xstate; | 283 | transformer_state_t xstate; |
284 | init_transformer_state(&xstate); | 284 | init_transformer_state(&xstate); |
285 | xstate.bytes_in = zip_header->formatted.cmpsize; | 285 | xstate.bytes_in = zip_header->formatted.cmpsize; |
286 | if (inflate_unzip(&xstate, zip_fd, dst_fd) < 0) | 286 | xstate.src_fd = zip_fd; |
287 | xstate.dst_fd = dst_fd; | ||
288 | if (inflate_unzip(&xstate) < 0) | ||
287 | bb_error_msg_and_die("inflate error"); | 289 | bb_error_msg_and_die("inflate error"); |
288 | /* Validate decompression - crc */ | 290 | /* Validate decompression - crc */ |
289 | if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { | 291 | if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { |
diff --git a/include/bb_archive.h b/include/bb_archive.h index 8a2dd2735..a6b166fe3 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h | |||
@@ -205,6 +205,18 @@ void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; | |||
205 | /* Meaning and direction (input/output) of the fields are transformer-specific */ | 205 | /* Meaning and direction (input/output) of the fields are transformer-specific */ |
206 | typedef struct transformer_state_t { | 206 | typedef struct transformer_state_t { |
207 | smallint check_signature; /* most often referenced member */ | 207 | smallint check_signature; /* most often referenced member */ |
208 | |||
209 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate); | ||
210 | USE_FOR_NOMMU(const char *xformer_prog;) | ||
211 | |||
212 | /* Source */ | ||
213 | int src_fd; | ||
214 | /* Output */ | ||
215 | int dst_fd; | ||
216 | size_t mem_output_size_max; /* if non-zero, decompress to RAM instead of fd */ | ||
217 | size_t mem_output_size; | ||
218 | char *mem_output_buf; | ||
219 | |||
208 | off_t bytes_out; | 220 | off_t bytes_out; |
209 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ | 221 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ |
210 | uint32_t crc32; | 222 | uint32_t crc32; |
@@ -212,14 +224,16 @@ typedef struct transformer_state_t { | |||
212 | } transformer_state_t; | 224 | } transformer_state_t; |
213 | 225 | ||
214 | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; | 226 | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; |
215 | int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigned magic16) FAST_FUNC; | 227 | ssize_t transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; |
228 | ssize_t xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; | ||
229 | int check_signature16(transformer_state_t *xstate, unsigned magic16) FAST_FUNC; | ||
216 | 230 | ||
217 | IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; | 231 | IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate) FAST_FUNC; |
218 | IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; | 232 | IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate) FAST_FUNC; |
219 | IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; | 233 | IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate) FAST_FUNC; |
220 | IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; | 234 | IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate) FAST_FUNC; |
221 | IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; | 235 | IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate) FAST_FUNC; |
222 | IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; | 236 | IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate) FAST_FUNC; |
223 | 237 | ||
224 | char* append_ext(char *filename, const char *expected_ext) FAST_FUNC; | 238 | char* append_ext(char *filename, const char *expected_ext) FAST_FUNC; |
225 | int bbunpack(char **argv, | 239 | int bbunpack(char **argv, |
@@ -230,16 +244,16 @@ int bbunpack(char **argv, | |||
230 | 244 | ||
231 | void check_errors_in_children(int signo); | 245 | void check_errors_in_children(int signo); |
232 | #if BB_MMU | 246 | #if BB_MMU |
233 | void open_transformer(int fd, | 247 | void fork_transformer(int fd, |
234 | int check_signature, | 248 | int check_signature, |
235 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate, int src_fd, int dst_fd) | 249 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) |
236 | ) FAST_FUNC; | 250 | ) FAST_FUNC; |
237 | #define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), 1, (transformer)) | 251 | #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer)) |
238 | #define open_transformer_with_no_sig(fd, transformer) open_transformer((fd), 0, (transformer)) | 252 | #define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer)) |
239 | #else | 253 | #else |
240 | void open_transformer(int fd, const char *transform_prog) FAST_FUNC; | 254 | void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; |
241 | #define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), (transform_prog)) | 255 | #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog)) |
242 | /* open_transformer_with_no_sig() does not exist on NOMMU */ | 256 | /* fork_transformer_with_no_sig() does not exist on NOMMU */ |
243 | #endif | 257 | #endif |
244 | 258 | ||
245 | 259 | ||
diff --git a/include/libbb.h b/include/libbb.h index 17a0089d8..8e8b9ca0e 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -755,11 +755,12 @@ unsigned bb_clk_tck(void) FAST_FUNC; | |||
755 | extern int setup_unzip_on_fd(int fd, int fail_if_not_compressed) FAST_FUNC; | 755 | extern int setup_unzip_on_fd(int fd, int fail_if_not_compressed) FAST_FUNC; |
756 | /* Autodetects .gz etc */ | 756 | /* Autodetects .gz etc */ |
757 | extern int open_zipped(const char *fname, int fail_if_not_compressed) FAST_FUNC; | 757 | extern int open_zipped(const char *fname, int fail_if_not_compressed) FAST_FUNC; |
758 | extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | ||
758 | #else | 759 | #else |
759 | # define setup_unzip_on_fd(...) (0) | 760 | # define setup_unzip_on_fd(...) (0) |
760 | # define open_zipped(fname, fail_if_not_compressed) open((fname), O_RDONLY); | 761 | # define open_zipped(fname, fail_if_not_compressed) open((fname), O_RDONLY); |
762 | # define xmalloc_open_zipped_read_close(fname, maxsz_p) xmalloc_open_read_close((fname), (maxsz_p)) | ||
761 | #endif | 763 | #endif |
762 | extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | ||
763 | 764 | ||
764 | extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC; | 765 | extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC; |
765 | // NB: will return short write on error, not -1, | 766 | // NB: will return short write on error, not -1, |