Contents of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/decompress_uncompress.c
Parent Directory | Revision Log
Revision 1123 -
(show annotations)
(download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 10 months ago) by niro
File MIME type: text/plain
File size: 7861 byte(s)
Wed Aug 18 21:56:57 2010 UTC (13 years, 10 months ago) by niro
File MIME type: text/plain
File size: 7861 byte(s)
-updated to busybox-1.17.1
1 | /* vi: set sw=4 ts=4: */ |
2 | /* uncompress for busybox -- (c) 2002 Robert Griebl |
3 | * |
4 | * based on the original compress42.c source |
5 | * (see disclaimer below) |
6 | */ |
7 | |
8 | /* (N)compress42.c - File compression ala IEEE Computer, Mar 1992. |
9 | * |
10 | * Authors: |
11 | * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) |
12 | * Jim McKie (decvax!mcvax!jim) |
13 | * Steve Davies (decvax!vax135!petsd!peora!srd) |
14 | * Ken Turkowski (decvax!decwrl!turtlevax!ken) |
15 | * James A. Woods (decvax!ihnp4!ames!jaw) |
16 | * Joe Orost (decvax!vax135!petsd!joe) |
17 | * Dave Mack (csu@alembic.acs.com) |
18 | * Peter Jannesen, Network Communication Systems |
19 | * (peter@ncs.nl) |
20 | * |
21 | * marc@suse.de : a small security fix for a buffer overflow |
22 | * |
23 | * [... History snipped ...] |
24 | * |
25 | */ |
26 | |
27 | #include "libbb.h" |
28 | #include "unarchive.h" |
29 | |
30 | |
31 | /* Default input buffer size */ |
32 | #define IBUFSIZ 2048 |
33 | |
34 | /* Default output buffer size */ |
35 | #define OBUFSIZ 2048 |
36 | |
37 | /* Defines for third byte of header */ |
38 | #define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */ |
39 | /* Masks 0x20 and 0x40 are free. */ |
40 | /* I think 0x20 should mean that there is */ |
41 | /* a fourth header byte (for expansion). */ |
42 | #define BLOCK_MODE 0x80 /* Block compression if table is full and */ |
43 | /* compression rate is dropping flush tables */ |
44 | /* the next two codes should not be changed lightly, as they must not */ |
45 | /* lie within the contiguous general code space. */ |
46 | #define FIRST 257 /* first free entry */ |
47 | #define CLEAR 256 /* table clear output code */ |
48 | |
49 | #define INIT_BITS 9 /* initial number of bits/code */ |
50 | |
51 | |
52 | /* machine variants which require cc -Dmachine: pdp11, z8000, DOS */ |
53 | #define HBITS 17 /* 50% occupancy */ |
54 | #define HSIZE (1<<HBITS) |
55 | #define HMASK (HSIZE-1) /* unused */ |
56 | #define HPRIME 9941 /* unused */ |
57 | #define BITS 16 |
58 | #define BITS_STR "16" |
59 | #undef MAXSEG_64K /* unused */ |
60 | #define MAXCODE(n) (1L << (n)) |
61 | |
62 | #define htabof(i) htab[i] |
63 | #define codetabof(i) codetab[i] |
64 | #define tab_prefixof(i) codetabof(i) |
65 | #define tab_suffixof(i) ((unsigned char *)(htab))[i] |
66 | #define de_stack ((unsigned char *)&(htab[HSIZE-1])) |
67 | #define clear_tab_prefixof() memset(codetab, 0, 256) |
68 | |
69 | /* |
70 | * Decompress stdin to stdout. This routine adapts to the codes in the |
71 | * file building the "string" table on-the-fly; requiring no table to |
72 | * be stored in the compressed file. |
73 | */ |
74 | |
75 | IF_DESKTOP(long long) int FAST_FUNC |
76 | unpack_Z_stream(int fd_in, int fd_out) |
77 | { |
78 | IF_DESKTOP(long long total_written = 0;) |
79 | IF_DESKTOP(long long) int retval = -1; |
80 | unsigned char *stackp; |
81 | long code; |
82 | int finchar; |
83 | long oldcode; |
84 | long incode; |
85 | int inbits; |
86 | int posbits; |
87 | int outpos; |
88 | int insize; |
89 | int bitmask; |
90 | long free_ent; |
91 | long maxcode; |
92 | long maxmaxcode; |
93 | int n_bits; |
94 | int rsize = 0; |
95 | unsigned char *inbuf; /* were eating insane amounts of stack - */ |
96 | unsigned char *outbuf; /* bad for some embedded targets */ |
97 | unsigned char *htab; |
98 | unsigned short *codetab; |
99 | |
100 | /* Hmm, these were statics - why?! */ |
101 | /* user settable max # bits/code */ |
102 | int maxbits; /* = BITS; */ |
103 | /* block compress mode -C compatible with 2.0 */ |
104 | int block_mode; /* = BLOCK_MODE; */ |
105 | |
106 | inbuf = xzalloc(IBUFSIZ + 64); |
107 | outbuf = xzalloc(OBUFSIZ + 2048); |
108 | htab = xzalloc(HSIZE); /* wsn't zeroed out before, maybe can xmalloc? */ |
109 | codetab = xzalloc(HSIZE * sizeof(codetab[0])); |
110 | |
111 | insize = 0; |
112 | |
113 | /* xread isn't good here, we have to return - caller may want |
114 | * to do some cleanup (e.g. delete incomplete unpacked file etc) */ |
115 | if (full_read(fd_in, inbuf, 1) != 1) { |
116 | bb_error_msg("short read"); |
117 | goto err; |
118 | } |
119 | |
120 | maxbits = inbuf[0] & BIT_MASK; |
121 | block_mode = inbuf[0] & BLOCK_MODE; |
122 | maxmaxcode = MAXCODE(maxbits); |
123 | |
124 | if (maxbits > BITS) { |
125 | bb_error_msg("compressed with %d bits, can only handle " |
126 | BITS_STR" bits", maxbits); |
127 | goto err; |
128 | } |
129 | |
130 | n_bits = INIT_BITS; |
131 | maxcode = MAXCODE(INIT_BITS) - 1; |
132 | bitmask = (1 << INIT_BITS) - 1; |
133 | oldcode = -1; |
134 | finchar = 0; |
135 | outpos = 0; |
136 | posbits = 0 << 3; |
137 | |
138 | free_ent = ((block_mode) ? FIRST : 256); |
139 | |
140 | /* As above, initialize the first 256 entries in the table. */ |
141 | /*clear_tab_prefixof(); - done by xzalloc */ |
142 | |
143 | for (code = 255; code >= 0; --code) { |
144 | tab_suffixof(code) = (unsigned char) code; |
145 | } |
146 | |
147 | do { |
148 | resetbuf: |
149 | { |
150 | int i; |
151 | int e; |
152 | int o; |
153 | |
154 | o = posbits >> 3; |
155 | e = insize - o; |
156 | |
157 | for (i = 0; i < e; ++i) |
158 | inbuf[i] = inbuf[i + o]; |
159 | |
160 | insize = e; |
161 | posbits = 0; |
162 | } |
163 | |
164 | if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { |
165 | rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ); |
166 | //error check?? |
167 | insize += rsize; |
168 | } |
169 | |
170 | inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 : |
171 | (insize << 3) - (n_bits - 1)); |
172 | |
173 | while (inbits > posbits) { |
174 | if (free_ent > maxcode) { |
175 | posbits = |
176 | ((posbits - 1) + |
177 | ((n_bits << 3) - |
178 | (posbits - 1 + (n_bits << 3)) % (n_bits << 3))); |
179 | ++n_bits; |
180 | if (n_bits == maxbits) { |
181 | maxcode = maxmaxcode; |
182 | } else { |
183 | maxcode = MAXCODE(n_bits) - 1; |
184 | } |
185 | bitmask = (1 << n_bits) - 1; |
186 | goto resetbuf; |
187 | } |
188 | { |
189 | unsigned char *p = &inbuf[posbits >> 3]; |
190 | |
191 | code = ((((long) (p[0])) | ((long) (p[1]) << 8) | |
192 | ((long) (p[2]) << 16)) >> (posbits & 0x7)) & bitmask; |
193 | } |
194 | posbits += n_bits; |
195 | |
196 | |
197 | if (oldcode == -1) { |
198 | oldcode = code; |
199 | finchar = (int) oldcode; |
200 | outbuf[outpos++] = (unsigned char) finchar; |
201 | continue; |
202 | } |
203 | |
204 | if (code == CLEAR && block_mode) { |
205 | clear_tab_prefixof(); |
206 | free_ent = FIRST - 1; |
207 | posbits = |
208 | ((posbits - 1) + |
209 | ((n_bits << 3) - |
210 | (posbits - 1 + (n_bits << 3)) % (n_bits << 3))); |
211 | n_bits = INIT_BITS; |
212 | maxcode = MAXCODE(INIT_BITS) - 1; |
213 | bitmask = (1 << INIT_BITS) - 1; |
214 | goto resetbuf; |
215 | } |
216 | |
217 | incode = code; |
218 | stackp = de_stack; |
219 | |
220 | /* Special case for KwKwK string. */ |
221 | if (code >= free_ent) { |
222 | if (code > free_ent) { |
223 | unsigned char *p; |
224 | |
225 | posbits -= n_bits; |
226 | p = &inbuf[posbits >> 3]; |
227 | |
228 | bb_error_msg |
229 | ("insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)", |
230 | insize, posbits, p[-1], p[0], p[1], p[2], p[3], |
231 | (posbits & 07)); |
232 | bb_error_msg("corrupted data"); |
233 | goto err; |
234 | } |
235 | |
236 | *--stackp = (unsigned char) finchar; |
237 | code = oldcode; |
238 | } |
239 | |
240 | /* Generate output characters in reverse order */ |
241 | while ((long) code >= (long) 256) { |
242 | *--stackp = tab_suffixof(code); |
243 | code = tab_prefixof(code); |
244 | } |
245 | |
246 | finchar = tab_suffixof(code); |
247 | *--stackp = (unsigned char) finchar; |
248 | |
249 | /* And put them out in forward order */ |
250 | { |
251 | int i; |
252 | |
253 | i = de_stack - stackp; |
254 | if (outpos + i >= OBUFSIZ) { |
255 | do { |
256 | if (i > OBUFSIZ - outpos) { |
257 | i = OBUFSIZ - outpos; |
258 | } |
259 | |
260 | if (i > 0) { |
261 | memcpy(outbuf + outpos, stackp, i); |
262 | outpos += i; |
263 | } |
264 | |
265 | if (outpos >= OBUFSIZ) { |
266 | full_write(fd_out, outbuf, outpos); |
267 | //error check?? |
268 | IF_DESKTOP(total_written += outpos;) |
269 | outpos = 0; |
270 | } |
271 | stackp += i; |
272 | i = de_stack - stackp; |
273 | } while (i > 0); |
274 | } else { |
275 | memcpy(outbuf + outpos, stackp, i); |
276 | outpos += i; |
277 | } |
278 | } |
279 | |
280 | /* Generate the new entry. */ |
281 | code = free_ent; |
282 | if (code < maxmaxcode) { |
283 | tab_prefixof(code) = (unsigned short) oldcode; |
284 | tab_suffixof(code) = (unsigned char) finchar; |
285 | free_ent = code + 1; |
286 | } |
287 | |
288 | /* Remember previous code. */ |
289 | oldcode = incode; |
290 | } |
291 | |
292 | } while (rsize > 0); |
293 | |
294 | if (outpos > 0) { |
295 | full_write(fd_out, outbuf, outpos); |
296 | //error check?? |
297 | IF_DESKTOP(total_written += outpos;) |
298 | } |
299 | |
300 | retval = IF_DESKTOP(total_written) + 0; |
301 | err: |
302 | free(inbuf); |
303 | free(outbuf); |
304 | free(htab); |
305 | free(codetab); |
306 | return retval; |
307 | } |