diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-28 23:08:53 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-28 23:08:53 +0200 |
commit | caddfc83399ab783f032dbe23f3b10a5bd85414f (patch) | |
tree | 91dc667eaafc3846f4c7089d7393f47821df641d | |
parent | 8410ac1a073272affe8acdb0da67e5753ea051f8 (diff) | |
download | busybox-w32-caddfc83399ab783f032dbe23f3b10a5bd85414f.tar.gz busybox-w32-caddfc83399ab783f032dbe23f3b10a5bd85414f.tar.bz2 busybox-w32-caddfc83399ab783f032dbe23f3b10a5bd85414f.zip |
decompress_bunzip2: handle concatenated .bz2 files
function old new delta
unpack_bz2_stream 207 307 +100
start_bunzip 199 209 +10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 110/0) Total: 110 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/libunarchive/decompress_bunzip2.c | 74 | ||||
-rw-r--r-- | include/unarchive.h | 2 | ||||
-rw-r--r-- | libbb/appletlib.c | 2 | ||||
-rw-r--r-- | miscutils/bbconfig.c | 2 | ||||
-rwxr-xr-x | testsuite/bunzip2.tests | 31 |
5 files changed, 81 insertions, 30 deletions
diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c index 22015683c..549c8b19f 100644 --- a/archival/libunarchive/decompress_bunzip2.c +++ b/archival/libunarchive/decompress_bunzip2.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #define RETVAL_LAST_BLOCK (-1) | 44 | #define RETVAL_LAST_BLOCK (-1) |
45 | #define RETVAL_NOT_BZIP_DATA (-2) | 45 | #define RETVAL_NOT_BZIP_DATA (-2) |
46 | #define RETVAL_UNEXPECTED_INPUT_EOF (-3) | 46 | #define RETVAL_UNEXPECTED_INPUT_EOF (-3) |
47 | #define RETVAL_SHORT_WRITE (-4) | 47 | //#define RETVAL_SHORT_WRITE (-4) |
48 | #define RETVAL_DATA_ERROR (-5) | 48 | #define RETVAL_DATA_ERROR (-5) |
49 | #define RETVAL_OUT_OF_MEMORY (-6) | 49 | #define RETVAL_OUT_OF_MEMORY (-6) |
50 | #define RETVAL_OBSOLETE_INPUT (-7) | 50 | #define RETVAL_OBSOLETE_INPUT (-7) |
@@ -584,8 +584,8 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | |||
584 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() | 584 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() |
585 | should work for NOFORK applets too, we must be extremely careful to not leak | 585 | should work for NOFORK applets too, we must be extremely careful to not leak |
586 | any allocations! */ | 586 | any allocations! */ |
587 | int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, | 587 | int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, |
588 | int len) | 588 | const void *inbuf, int len) |
589 | { | 589 | { |
590 | bunzip_data *bd; | 590 | bunzip_data *bd; |
591 | unsigned i; | 591 | unsigned i; |
@@ -606,9 +606,11 @@ int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *in | |||
606 | if (-1 == in_fd) { | 606 | if (-1 == in_fd) { |
607 | /* in this case, bd->inbuf is read-only */ | 607 | /* in this case, bd->inbuf is read-only */ |
608 | bd->inbuf = (void*)inbuf; /* cast away const-ness */ | 608 | bd->inbuf = (void*)inbuf; /* cast away const-ness */ |
609 | bd->inbufCount = len; | 609 | } else { |
610 | } else | ||
611 | bd->inbuf = (unsigned char *)(bd + 1); | 610 | bd->inbuf = (unsigned char *)(bd + 1); |
611 | memcpy(bd->inbuf, inbuf, len); | ||
612 | } | ||
613 | bd->inbufCount = len; | ||
612 | 614 | ||
613 | /* Init the CRC32 table (big endian) */ | 615 | /* Init the CRC32 table (big endian) */ |
614 | crc32_filltable(bd->crc32Table, 1); | 616 | crc32_filltable(bd->crc32Table, 1); |
@@ -652,37 +654,59 @@ IF_DESKTOP(long long) int FAST_FUNC | |||
652 | unpack_bz2_stream(int src_fd, int dst_fd) | 654 | unpack_bz2_stream(int src_fd, int dst_fd) |
653 | { | 655 | { |
654 | IF_DESKTOP(long long total_written = 0;) | 656 | IF_DESKTOP(long long total_written = 0;) |
657 | bunzip_data *bd; | ||
655 | char *outbuf; | 658 | char *outbuf; |
656 | bunzip_data *bd; | ||
657 | int i; | 659 | int i; |
660 | unsigned len; | ||
658 | 661 | ||
659 | outbuf = xmalloc(IOBUF_SIZE); | 662 | outbuf = xmalloc(IOBUF_SIZE); |
660 | i = start_bunzip(&bd, src_fd, NULL, 0); | 663 | len = 0; |
661 | if (!i) { | 664 | while (1) { /* "Process one BZ... stream" loop */ |
662 | for (;;) { | 665 | |
663 | i = read_bunzip(bd, outbuf, IOBUF_SIZE); | 666 | i = start_bunzip(&bd, src_fd, outbuf + 2, len); |
664 | if (i <= 0) break; | 667 | |
665 | if (i != full_write(dst_fd, outbuf, i)) { | 668 | if (i == 0) { |
666 | i = RETVAL_SHORT_WRITE; | 669 | while (1) { /* "Produce some output bytes" loop */ |
667 | break; | 670 | i = read_bunzip(bd, outbuf, IOBUF_SIZE); |
671 | if (i <= 0) | ||
672 | break; | ||
673 | if (i != full_write(dst_fd, outbuf, i)) { | ||
674 | bb_error_msg("short write"); | ||
675 | goto release_mem; | ||
676 | } | ||
677 | IF_DESKTOP(total_written += i;) | ||
668 | } | 678 | } |
669 | IF_DESKTOP(total_written += i;) | ||
670 | } | 679 | } |
671 | } | ||
672 | 680 | ||
673 | /* Check CRC and release memory */ | 681 | if (i != RETVAL_LAST_BLOCK) { |
674 | 682 | bb_error_msg("bunzip error %d", i); | |
675 | if (i == RETVAL_LAST_BLOCK) { | 683 | break; |
684 | } | ||
676 | if (bd->headerCRC != bd->totalCRC) { | 685 | if (bd->headerCRC != bd->totalCRC) { |
677 | bb_error_msg("CRC error"); | 686 | bb_error_msg("CRC error"); |
678 | } else { | 687 | break; |
679 | i = RETVAL_OK; | ||
680 | } | 688 | } |
681 | } else if (i == RETVAL_SHORT_WRITE) { | 689 | |
682 | bb_error_msg("short write"); | 690 | /* Successfully unpacked one BZ stream */ |
683 | } else { | 691 | i = RETVAL_OK; |
684 | bb_error_msg("bunzip error %d", i); | 692 | |
693 | /* Do we have "BZ..." after last processed byte? | ||
694 | * pbzip2 (parallelized bzip2) produces such files. | ||
695 | */ | ||
696 | len = bd->inbufCount - bd->inbufPos; | ||
697 | memcpy(outbuf, &bd->inbuf[bd->inbufPos], len); | ||
698 | if (len < 2) { | ||
699 | if (safe_read(src_fd, outbuf + len, 2 - len) != 2 - len) | ||
700 | break; | ||
701 | len = 2; | ||
702 | } | ||
703 | if (*(uint16_t*)outbuf != BZIP2_MAGIC) /* "BZ"? */ | ||
704 | break; | ||
705 | dealloc_bunzip(bd); | ||
706 | len -= 2; | ||
685 | } | 707 | } |
708 | |||
709 | release_mem: | ||
686 | dealloc_bunzip(bd); | 710 | dealloc_bunzip(bd); |
687 | free(outbuf); | 711 | free(outbuf); |
688 | 712 | ||
diff --git a/include/unarchive.h b/include/unarchive.h index b55af6d9d..11d8c77a0 100644 --- a/include/unarchive.h +++ b/include/unarchive.h | |||
@@ -193,7 +193,7 @@ extern const llist_t *find_list_entry2(const llist_t *list, const char *filename | |||
193 | 193 | ||
194 | /* A bit of bunzip2 internals are exposed for compressed help support: */ | 194 | /* A bit of bunzip2 internals are exposed for compressed help support: */ |
195 | typedef struct bunzip_data bunzip_data; | 195 | typedef struct bunzip_data bunzip_data; |
196 | int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, int len) FAST_FUNC; | 196 | int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; |
197 | int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; | 197 | int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; |
198 | void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; | 198 | void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; |
199 | 199 | ||
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index b32ff8808..fab996ca0 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -75,7 +75,7 @@ static const char *unpack_usage_messages(void) | |||
75 | 75 | ||
76 | i = start_bunzip(&bd, | 76 | i = start_bunzip(&bd, |
77 | /* src_fd: */ -1, | 77 | /* src_fd: */ -1, |
78 | /* inbuf: */ (void *)packed_usage, | 78 | /* inbuf: */ packed_usage, |
79 | /* len: */ sizeof(packed_usage)); | 79 | /* len: */ sizeof(packed_usage)); |
80 | /* read_bunzip can longjmp to start_bunzip, and ultimately | 80 | /* read_bunzip can longjmp to start_bunzip, and ultimately |
81 | * end up here with i != 0 on read data errors! Not trivial */ | 81 | * end up here with i != 0 on read data errors! Not trivial */ |
diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c index 286077168..1cb42edeb 100644 --- a/miscutils/bbconfig.c +++ b/miscutils/bbconfig.c | |||
@@ -15,7 +15,7 @@ int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
15 | bunzip_data *bd; | 15 | bunzip_data *bd; |
16 | int i = start_bunzip(&bd, | 16 | int i = start_bunzip(&bd, |
17 | /* src_fd: */ -1, | 17 | /* src_fd: */ -1, |
18 | /* inbuf: */ (void *)bbconfig_config_bz2, | 18 | /* inbuf: */ bbconfig_config_bz2, |
19 | /* len: */ sizeof(bbconfig_config_bz2)); | 19 | /* len: */ sizeof(bbconfig_config_bz2)); |
20 | /* read_bunzip can longjmp to start_bunzip, and ultimately | 20 | /* read_bunzip can longjmp to start_bunzip, and ultimately |
21 | * end up here with i != 0 on read data errors! Not trivial */ | 21 | * end up here with i != 0 on read data errors! Not trivial */ |
diff --git a/testsuite/bunzip2.tests b/testsuite/bunzip2.tests index 827aee867..fcfce1a31 100755 --- a/testsuite/bunzip2.tests +++ b/testsuite/bunzip2.tests | |||
@@ -463,6 +463,24 @@ $ECHO -ne "\x40\xa0\x00\x8b\x12\xe8\xfb\xb7\x27\xaa\xd3\x36\x0c\xfc\xe1\x40" | |||
463 | $ECHO -ne "\x01\xff\x8b\xb9\x22\x9c\x28\x48\x5f\xa5\xca\xf3\x80" | 463 | $ECHO -ne "\x01\xff\x8b\xb9\x22\x9c\x28\x48\x5f\xa5\xca\xf3\x80" |
464 | } | 464 | } |
465 | 465 | ||
466 | pbzip_4m_zeros() { | ||
467 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
468 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
469 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
470 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
471 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
472 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
473 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
474 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
475 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
476 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\x63\xe3\xec\xa2\x00\x06" | ||
477 | $ECHO -ne "\xe4\xc1\x00\xc0\x00\x02\x00\x00\x08\x20\x00\x30\xcc\x09\xaa\x69" | ||
478 | $ECHO -ne "\x94\xa1\x36\xa9\x28\x4f\x17\x72\x45\x38\x50\x90\x63\xe3\xec\xa2" | ||
479 | $ECHO -ne "\x42\x5a\x68\x31\x31\x41\x59\x26\x53\x59\xc9\xb5\x21\xef\x00\x04" | ||
480 | $ECHO -ne "\x8d\x40\x20\xc0\x00\x01\x00\x00\x08\x20\x00\x30\xcc\x05\x29\xa6" | ||
481 | $ECHO -ne "\x4a\x11\xb1\x4a\x11\xe2\xee\x48\xa7\x0a\x12\x19\x36\xa4\x3d\xe0" | ||
482 | } | ||
483 | |||
466 | prep() { | 484 | prep() { |
467 | rm -f t* | 485 | rm -f t* |
468 | hello_$ext >t1.$ext | 486 | hello_$ext >t1.$ext |
@@ -520,9 +538,18 @@ if test "${0##*/}" = "bunzip2.tests"; then | |||
520 | if test1_bz2 | ${bb}bunzip2 >/dev/null \ | 538 | if test1_bz2 | ${bb}bunzip2 >/dev/null \ |
521 | && test "`test1_bz2 | ${bb}bunzip2 | md5sum`" = "61bbeee4be9c6f110a71447f584fda7b -" | 539 | && test "`test1_bz2 | ${bb}bunzip2 | md5sum`" = "61bbeee4be9c6f110a71447f584fda7b -" |
522 | then | 540 | then |
523 | echo "PASS: $unpack: test bz2 file" | 541 | echo "PASS: $unpack: test_bz2 file" |
542 | else | ||
543 | echo "FAIL: $unpack: test_bz2 file" | ||
544 | FAILCOUNT=$((FAILCOUNT + 1)) | ||
545 | fi | ||
546 | |||
547 | if pbzip_4m_zeros | ${bb}bunzip2 >/dev/null \ | ||
548 | && test "`pbzip_4m_zeros | ${bb}bunzip2 | md5sum`" = "b5cfa9d6c8febd618f91ac2843d50a1c -" | ||
549 | then | ||
550 | echo "PASS: $unpack: pbzip_4m_zeros file" | ||
524 | else | 551 | else |
525 | echo "FAIL: $unpack: test bz2 file" | 552 | echo "FAIL: $unpack: pbzip_4m_zeros file" |
526 | FAILCOUNT=$((FAILCOUNT + 1)) | 553 | FAILCOUNT=$((FAILCOUNT + 1)) |
527 | fi | 554 | fi |
528 | fi | 555 | fi |