aboutsummaryrefslogtreecommitdiff
path: root/archival/bzip2.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-10-13 03:36:03 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-10-13 03:36:03 +0000
commit77f1ec1b9bf100e6c10aa0856c7156e321511785 (patch)
treef20e5a9062ecad82a43bde81e3041a19c4292733 /archival/bzip2.c
parent11c23d7b990eae27357e5a41a97d62b9a214f7db (diff)
downloadbusybox-w32-77f1ec1b9bf100e6c10aa0856c7156e321511785.tar.gz
busybox-w32-77f1ec1b9bf100e6c10aa0856c7156e321511785.tar.bz2
busybox-w32-77f1ec1b9bf100e6c10aa0856c7156e321511785.zip
bzip2: port bzip2 1.0.4 to busybox. note: bzip2 code resides
in separate directory (archival/bz/*) and is covered by BSD-style license. code size: 13k
Diffstat (limited to 'archival/bzip2.c')
-rw-r--r--archival/bzip2.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/archival/bzip2.c b/archival/bzip2.c
new file mode 100644
index 000000000..04478eecc
--- /dev/null
+++ b/archival/bzip2.c
@@ -0,0 +1,166 @@
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
10#include "libbb.h"
11
12/* This buys 6% speed for nearly 4k code */
13/*#define FAST_GROUP6 1*/
14
15#include "bz/bzlib.h"
16
17#include "bz/bzlib_private.h"
18
19#include "bz/blocksort.c"
20#include "bz/bzlib.c"
21#include "bz/compress.c"
22#include "bz/crctable.c"
23#include "bz/huffman.c"
24#include "bz/randtable.c"
25
26/* No point in being shy and having very small buffer here.
27 * bzip2 internal buffers are much bigger anyway, hundreds of kbytes.
28 * If iobuf is several pages long, malloc() may use mmap,
29 * making iobuf is page aligned and thus (maybe) have one memcpy less
30 * if kernel is clever enough.
31 */
32enum {
33 IOBUF_SIZE = 8 * 1024
34};
35
36/* Returns:
37 * <0 on write errors (examine errno),
38 * >0 on short writes (errno == 0)
39 * 0 no error (entire input consume, gimme more)
40 * on "impossible" errors (internal bzip2 compressor bug) dies
41 */
42static
43ssize_t bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, void *wbuf)
44{
45 int n, n2, ret;
46
47 /* if (len == 0) return 0; */
48
49 strm->avail_in = rlen;
50 strm->next_in = rbuf;
51 while (1) {
52 strm->avail_out = IOBUF_SIZE;
53 strm->next_out = wbuf;
54
55 ret = BZ2_bzCompress(strm, BZ_RUN);
56 if (ret != BZ_RUN_OK)
57 bb_error_msg_and_die("internal error %d", ret);
58
59 n = IOBUF_SIZE - strm->avail_out;
60 if (n) {
61 /* short reads must have errno == 0 */
62 errno = 0;
63 n2 = full_write(STDOUT_FILENO, wbuf, n);
64 if (n2 != n)
65 return n2 ? n2 : 1;
66 }
67
68 if (strm->avail_in == 0)
69 return 0;
70 }
71}
72
73
74/*---------------------------------------------------*/
75static
76USE_DESKTOP(long long) int bz_write_tail(bz_stream *strm, void *wbuf)
77{
78 int n, n2, ret;
79 USE_DESKTOP(long long) int total;
80
81 total = -1;
82 while (1) {
83 strm->avail_out = IOBUF_SIZE;
84 strm->next_out = wbuf;
85
86 ret = BZ2_bzCompress(strm, BZ_FINISH);
87 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
88 bb_error_msg_and_die("internal error %d", ret);
89
90 n = IOBUF_SIZE - strm->avail_out;
91 if (n) {
92 n2 = full_write(STDOUT_FILENO, wbuf, n);
93 if (n2 != n)
94 goto err;
95 }
96
97 if (ret == BZ_STREAM_END)
98 break;
99 }
100
101 total = 0 USE_DESKTOP( + strm->total_out );
102 err:
103 BZ2_bzCompressEnd(strm);
104 return total;
105}
106
107
108static
109USE_DESKTOP(long long) int compressStream(void)
110{
111 USE_DESKTOP(long long) int total;
112 ssize_t count;
113 bz_stream bzs; /* it's small */
114#define strm (&bzs)
115 char *iobuf;
116#define rbuf iobuf
117#define wbuf (iobuf + IOBUF_SIZE)
118
119 iobuf = xmalloc(2 * IOBUF_SIZE);
120
121 BZ2_bzCompressInit(strm, 9 /*blockSize100k*/);
122
123 while (1) {
124 count = full_read(STDIN_FILENO, rbuf, IOBUF_SIZE);
125 if (count < 0)
126 bb_perror_msg("read error");
127 if (count <= 0)
128 break;
129 count = bz_write(strm, rbuf, count, wbuf);
130 if (count) {
131 bb_perror_msg(count < 0 ? "write error" : "short write");
132 break;
133 }
134 }
135
136 total = bz_write_tail(strm, wbuf);
137 free(iobuf);
138 /* we had no error _only_ if count == 0 */
139 return count == 0 ? total : -1;
140}
141
142static
143char* make_new_name_bzip2(char *filename)
144{
145 return xasprintf("%s.bz2", filename);
146}
147
148int bzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
149int bzip2_main(int argc, char **argv)
150{
151 unsigned opt;
152
153 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */
154 opt = getopt32(argv, "cfv" USE_BUNZIP2("d") "q123456789" );
155#if ENABLE_BUNZIP2 /* bunzip2_main may not be visible... */
156 if (opt & 0x8) // -d
157 return bunzip2_main(argc, argv);
158#endif
159 option_mask32 &= 0x7; /* ignore -q, -0..9 */
160 //if (opt & 0x1) // -c
161 //if (opt & 0x2) // -f
162 //if (opt & 0x4) // -v
163 argv += optind;
164
165 return bbunpack(argv, make_new_name_bzip2, compressStream);
166}