source: MondoRescue/branches/3.3/mindi-busybox/archival/bzip2.c@ 3626

Last change on this file since 3626 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 5.7 KB
RevLine 
[2725]1/*
2 * Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
3 *
4 * This file uses bzip2 library code which is written
5 * by Julian Seward <jseward@bzip.org>.
6 * See README and LICENSE files in bz/ directory for more information
7 * about bzip2 library code.
8 */
9
[3621]10//config:config BZIP2
11//config: bool "bzip2"
12//config: default y
13//config: help
14//config: bzip2 is a compression utility using the Burrows-Wheeler block
15//config: sorting text compression algorithm, and Huffman coding. Compression
16//config: is generally considerably better than that achieved by more
17//config: conventional LZ77/LZ78-based compressors, and approaches the
18//config: performance of the PPM family of statistical compressors.
19//config:
20//config: Unless you have a specific application which requires bzip2, you
21//config: should probably say N here.
22
23//applet:IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP))
24//kbuild:lib-$(CONFIG_BZIP2) += bzip2.o
25
[3232]26//usage:#define bzip2_trivial_usage
27//usage: "[OPTIONS] [FILE]..."
28//usage:#define bzip2_full_usage "\n\n"
29//usage: "Compress FILEs (or stdin) with bzip2 algorithm\n"
30//usage: "\n -1..9 Compression level"
31//usage: "\n -d Decompress"
32//usage: "\n -c Write to stdout"
33//usage: "\n -f Force"
34
[2725]35#include "libbb.h"
[3232]36#include "bb_archive.h"
[2725]37
[3232]38#define CONFIG_BZIP2_FAST 1
[2725]39
40/* Speed test:
41 * Compiled with gcc 4.2.1, run on Athlon 64 1800 MHz (512K L2 cache).
42 * Stock bzip2 is 26.4% slower than bbox bzip2 at SPEED 1
43 * (time to compress gcc-4.2.1.tar is 126.4% compared to bbox).
44 * At SPEED 5 difference is 32.7%.
45 *
[3232]46 * Test run of all CONFIG_BZIP2_FAST values on a 11Mb text file:
[2725]47 * Size Time (3 runs)
48 * 0: 10828 4.145 4.146 4.148
49 * 1: 11097 3.845 3.860 3.861
50 * 2: 11392 3.763 3.767 3.768
51 * 3: 11892 3.722 3.724 3.727
52 * 4: 12740 3.637 3.640 3.644
53 * 5: 17273 3.497 3.509 3.509
54 */
55
56
57#define BZ_DEBUG 0
58/* Takes ~300 bytes, detects corruption caused by bad RAM etc */
59#define BZ_LIGHT_DEBUG 0
60
61#include "libarchive/bz/bzlib.h"
62
63#include "libarchive/bz/bzlib_private.h"
64
65#include "libarchive/bz/blocksort.c"
66#include "libarchive/bz/bzlib.c"
67#include "libarchive/bz/compress.c"
68#include "libarchive/bz/huffman.c"
69
70/* No point in being shy and having very small buffer here.
71 * bzip2 internal buffers are much bigger anyway, hundreds of kbytes.
72 * If iobuf is several pages long, malloc() may use mmap,
73 * making iobuf is page aligned and thus (maybe) have one memcpy less
74 * if kernel is clever enough.
75 */
76enum {
77 IOBUF_SIZE = 8 * 1024
78};
79
80static uint8_t level;
81
82/* NB: compressStream() has to return -1 on errors, not die.
83 * bbunpack() will correctly clean up in this case
84 * (delete incomplete .bz2 file)
85 */
86
87/* Returns:
88 * -1 on errors
89 * total written bytes so far otherwise
90 */
91static
92IF_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, void *wbuf)
93{
94 int n, n2, ret;
95
96 strm->avail_in = rlen;
97 strm->next_in = rbuf;
98 while (1) {
99 strm->avail_out = IOBUF_SIZE;
100 strm->next_out = wbuf;
101
102 ret = BZ2_bzCompress(strm, rlen ? BZ_RUN : BZ_FINISH);
103 if (ret != BZ_RUN_OK /* BZ_RUNning */
104 && ret != BZ_FINISH_OK /* BZ_FINISHing, but not done yet */
105 && ret != BZ_STREAM_END /* BZ_FINISHed */
106 ) {
107 bb_error_msg_and_die("internal error %d", ret);
108 }
109
110 n = IOBUF_SIZE - strm->avail_out;
111 if (n) {
112 n2 = full_write(STDOUT_FILENO, wbuf, n);
113 if (n2 != n) {
114 if (n2 >= 0)
115 errno = 0; /* prevent bogus error message */
116 bb_perror_msg(n2 >= 0 ? "short write" : bb_msg_write_error);
117 return -1;
118 }
119 }
120
121 if (ret == BZ_STREAM_END)
122 break;
123 if (rlen && strm->avail_in == 0)
124 break;
125 }
126 return 0 IF_DESKTOP( + strm->total_out );
127}
128
129static
[3621]130IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_state_t *xstate UNUSED_PARAM)
[2725]131{
132 IF_DESKTOP(long long) int total;
133 ssize_t count;
134 bz_stream bzs; /* it's small */
135#define strm (&bzs)
136 char *iobuf;
137#define rbuf iobuf
138#define wbuf (iobuf + IOBUF_SIZE)
139
140 iobuf = xmalloc(2 * IOBUF_SIZE);
141 BZ2_bzCompressInit(strm, level);
142
143 while (1) {
144 count = full_read(STDIN_FILENO, rbuf, IOBUF_SIZE);
145 if (count < 0) {
146 bb_perror_msg(bb_msg_read_error);
147 total = -1;
148 break;
149 }
150 /* if count == 0, bz_write finalizes compression */
151 total = bz_write(strm, rbuf, count, wbuf);
152 if (count == 0 || total < 0)
153 break;
154 }
155
156 /* Can't be conditional on ENABLE_FEATURE_CLEAN_UP -
157 * we are called repeatedly
158 */
159 BZ2_bzCompressEnd(strm);
160 free(iobuf);
161
162 return total;
163}
164
165int bzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
166int bzip2_main(int argc UNUSED_PARAM, char **argv)
167{
168 unsigned opt;
169
170 /* standard bzip2 flags
171 * -d --decompress force decompression
172 * -z --compress force compression
173 * -k --keep keep (don't delete) input files
174 * -f --force overwrite existing output files
175 * -t --test test compressed file integrity
176 * -c --stdout output to standard out
177 * -q --quiet suppress noncritical error messages
178 * -v --verbose be verbose (a 2nd -v gives more)
179 * -s --small use less memory (at most 2500k)
180 * -1 .. -9 set block size to 100k .. 900k
181 * --fast alias for -1
182 * --best alias for -9
183 */
184
185 opt_complementary = "s2"; /* -s means -2 (compatibility) */
186 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */
187 opt = getopt32(argv, "cfv" IF_BUNZIP2("dt") "123456789qzs");
188#if ENABLE_BUNZIP2 /* bunzip2_main may not be visible... */
189 if (opt & 0x18) // -d and/or -t
190 return bunzip2_main(argc, argv);
191 opt >>= 5;
192#else
193 opt >>= 3;
194#endif
195 opt = (uint8_t)opt; /* isolate bits for -1..-8 */
196 opt |= 0x100; /* if nothing else, assume -9 */
197 level = 1;
198 while (!(opt & 1)) {
199 level++;
200 opt >>= 1;
201 }
202
203 argv += optind;
204 option_mask32 &= 0x7; /* ignore all except -cfv */
205 return bbunpack(argv, compressStream, append_ext, "bz2");
206}
Note: See TracBrowser for help on using the repository browser.