X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Fbzip2.c;h=eb570c4349753c1b8e426792419e9798efe6dd74;hb=73132b9c1204500239032f4e36602d41051d29c2;hp=04478eecc746ad3ae9666fe1dcd5a22c9ded5b77;hpb=77f1ec1b9bf100e6c10aa0856c7156e321511785;p=oweals%2Fbusybox.git diff --git a/archival/bzip2.c b/archival/bzip2.c index 04478eecc..eb570c434 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c @@ -9,8 +9,28 @@ #include "libbb.h" -/* This buys 6% speed for nearly 4k code */ -/*#define FAST_GROUP6 1*/ +#define CONFIG_BZIP2_FEATURE_SPEED 1 + +/* Speed test: + * Compiled with gcc 4.2.1, run on Athlon 64 1800 MHz (512K L2 cache). + * Stock bzip2 is 26.4% slower than bbox bzip2 at SPEED 1 + * (time to compress gcc-4.2.1.tar is 126.4% compared to bbox). + * At SPEED 5 difference is 32.7%. + * + * Test run of all CONFIG_BZIP2_FEATURE_SPEED values on a 11Mb text file: + * Size Time (3 runs) + * 0: 10828 4.145 4.146 4.148 + * 1: 11097 3.845 3.860 3.861 + * 2: 11392 3.763 3.767 3.768 + * 3: 11892 3.722 3.724 3.727 + * 4: 12740 3.637 3.640 3.644 + * 5: 17273 3.497 3.509 3.509 + */ + + +#define BZ_DEBUG 0 +/* Takes ~300 bytes, detects corruption caused by bad RAM etc */ +#define BZ_LIGHT_DEBUG 0 #include "bz/bzlib.h" @@ -19,9 +39,7 @@ #include "bz/blocksort.c" #include "bz/bzlib.c" #include "bz/compress.c" -#include "bz/crctable.c" #include "bz/huffman.c" -#include "bz/randtable.c" /* No point in being shy and having very small buffer here. * bzip2 internal buffers are much bigger anyway, hundreds of kbytes. @@ -33,78 +51,55 @@ enum { IOBUF_SIZE = 8 * 1024 }; +static uint8_t level; + +/* NB: compressStream() has to return -1 on errors, not die. + * bbunpack() will correctly clean up in this case + * (delete incomplete .bz2 file) + */ + /* Returns: - * <0 on write errors (examine errno), - * >0 on short writes (errno == 0) - * 0 no error (entire input consume, gimme more) - * on "impossible" errors (internal bzip2 compressor bug) dies + * -1 on errors + * total written bytes so far otherwise */ static -ssize_t bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, void *wbuf) +USE_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, void *wbuf) { int n, n2, ret; - /* if (len == 0) return 0; */ - strm->avail_in = rlen; - strm->next_in = rbuf; + strm->next_in = rbuf; while (1) { strm->avail_out = IOBUF_SIZE; strm->next_out = wbuf; - ret = BZ2_bzCompress(strm, BZ_RUN); - if (ret != BZ_RUN_OK) + ret = BZ2_bzCompress(strm, rlen ? BZ_RUN : BZ_FINISH); + if (ret != BZ_RUN_OK /* BZ_RUNning */ + && ret != BZ_FINISH_OK /* BZ_FINISHing, but not done yet */ + && ret != BZ_STREAM_END /* BZ_FINISHed */ + ) { bb_error_msg_and_die("internal error %d", ret); - - n = IOBUF_SIZE - strm->avail_out; - if (n) { - /* short reads must have errno == 0 */ - errno = 0; - n2 = full_write(STDOUT_FILENO, wbuf, n); - if (n2 != n) - return n2 ? n2 : 1; } - if (strm->avail_in == 0) - return 0; - } -} - - -/*---------------------------------------------------*/ -static -USE_DESKTOP(long long) int bz_write_tail(bz_stream *strm, void *wbuf) -{ - int n, n2, ret; - USE_DESKTOP(long long) int total; - - total = -1; - while (1) { - strm->avail_out = IOBUF_SIZE; - strm->next_out = wbuf; - - ret = BZ2_bzCompress(strm, BZ_FINISH); - if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) - bb_error_msg_and_die("internal error %d", ret); - n = IOBUF_SIZE - strm->avail_out; if (n) { n2 = full_write(STDOUT_FILENO, wbuf, n); - if (n2 != n) - goto err; + if (n2 != n) { + if (n2 >= 0) + errno = 0; /* prevent bogus error message */ + bb_perror_msg(n2 >= 0 ? "short write" : "write error"); + return -1; + } } if (ret == BZ_STREAM_END) break; + if (rlen && strm->avail_in == 0) + break; } - - total = 0 USE_DESKTOP( + strm->total_out ); - err: - BZ2_bzCompressEnd(strm); - return total; + return 0 USE_DESKTOP( + strm->total_out ); } - static USE_DESKTOP(long long) int compressStream(void) { @@ -117,26 +112,26 @@ USE_DESKTOP(long long) int compressStream(void) #define wbuf (iobuf + IOBUF_SIZE) iobuf = xmalloc(2 * IOBUF_SIZE); - - BZ2_bzCompressInit(strm, 9 /*blockSize100k*/); + BZ2_bzCompressInit(strm, level); while (1) { count = full_read(STDIN_FILENO, rbuf, IOBUF_SIZE); - if (count < 0) + if (count < 0) { bb_perror_msg("read error"); - if (count <= 0) - break; - count = bz_write(strm, rbuf, count, wbuf); - if (count) { - bb_perror_msg(count < 0 ? "write error" : "short write"); + total = -1; break; } + /* if count == 0, bz_write finalizes compression */ + total = bz_write(strm, rbuf, count, wbuf); + if (count == 0 || total < 0) + break; } - total = bz_write_tail(strm, wbuf); +#if ENABLE_FEATURE_CLEAN_UP + BZ2_bzCompressEnd(strm); free(iobuf); - /* we had no error _only_ if count == 0 */ - return count == 0 ? total : -1; +#endif + return total; } static @@ -146,21 +141,44 @@ char* make_new_name_bzip2(char *filename) } int bzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int bzip2_main(int argc, char **argv) +int bzip2_main(int argc ATTRIBUTE_UNUSED, char **argv) { unsigned opt; + /* standard bzip2 flags + * -d --decompress force decompression + * -z --compress force compression + * -k --keep keep (don't delete) input files + * -f --force overwrite existing output files + * -t --test test compressed file integrity + * -c --stdout output to standard out + * -q --quiet suppress noncritical error messages + * -v --verbose be verbose (a 2nd -v gives more) + * -s --small use less memory (at most 2500k) + * -1 .. -9 set block size to 100k .. 900k + * --fast alias for -1 + * --best alias for -9 + */ + + opt_complementary = "s2"; /* -s means -2 (compatibility) */ /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ - opt = getopt32(argv, "cfv" USE_BUNZIP2("d") "q123456789" ); + opt = getopt32(argv, "cfv" USE_BUNZIP2("d") "123456789qzs" ); #if ENABLE_BUNZIP2 /* bunzip2_main may not be visible... */ if (opt & 0x8) // -d return bunzip2_main(argc, argv); + opt >>= 4; +#else + opt >>= 3; #endif - option_mask32 &= 0x7; /* ignore -q, -0..9 */ - //if (opt & 0x1) // -c - //if (opt & 0x2) // -f - //if (opt & 0x4) // -v - argv += optind; + opt = (uint8_t)opt; /* isolate bits for -1..-8 */ + opt |= 0x100; /* if nothing else, assume -9 */ + level = 1; + while (!(opt & 1)) { + level++; + opt >>= 1; + } + argv += optind; + option_mask32 &= 0x7; /* ignore all except -cfv */ return bbunpack(argv, make_new_name_bzip2, compressStream); }