Annotation of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/decompress_uncompress.c
Parent Directory | Revision Log
Revision 1123 -
(hide annotations)
(download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 7861 byte(s)
Wed Aug 18 21:56:57 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 7861 byte(s)
-updated to busybox-1.17.1
1 | niro | 532 | /* 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 | niro | 816 | #include "libbb.h" |
28 | #include "unarchive.h" | ||
29 | |||
30 | |||
31 | niro | 532 | /* 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 | niro | 816 | #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 | niro | 532 | |
49 | niro | 816 | #define INIT_BITS 9 /* initial number of bits/code */ |
50 | niro | 532 | |
51 | |||
52 | /* machine variants which require cc -Dmachine: pdp11, z8000, DOS */ | ||
53 | niro | 816 | #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 | niro | 532 | |
62 | niro | 816 | #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 | niro | 532 | |
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 | niro | 816 | * be stored in the compressed file. |
73 | niro | 532 | */ |
74 | |||
75 | niro | 984 | IF_DESKTOP(long long) int FAST_FUNC |
76 | niro | 816 | unpack_Z_stream(int fd_in, int fd_out) |
77 | niro | 532 | { |
78 | niro | 984 | IF_DESKTOP(long long total_written = 0;) |
79 | IF_DESKTOP(long long) int retval = -1; | ||
80 | niro | 532 | unsigned char *stackp; |
81 | niro | 816 | long code; |
82 | niro | 532 | int finchar; |
83 | niro | 816 | long oldcode; |
84 | long incode; | ||
85 | niro | 532 | int inbits; |
86 | int posbits; | ||
87 | int outpos; | ||
88 | int insize; | ||
89 | int bitmask; | ||
90 | niro | 816 | long free_ent; |
91 | long maxcode; | ||
92 | long maxmaxcode; | ||
93 | niro | 532 | int n_bits; |
94 | int rsize = 0; | ||
95 | niro | 816 | 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 | niro | 532 | |
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 | niro | 816 | 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 | niro | 532 | |
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 | niro | 816 | goto err; |
118 | niro | 532 | } |
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 | niro | 816 | BITS_STR" bits", maxbits); |
127 | goto err; | ||
128 | niro | 532 | } |
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 | niro | 816 | /*clear_tab_prefixof(); - done by xzalloc */ |
142 | niro | 532 | |
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 | niro | 1123 | bb_error_msg("corrupted data"); |
233 | niro | 816 | goto err; |
234 | niro | 532 | } |
235 | |||
236 | *--stackp = (unsigned char) finchar; | ||
237 | code = oldcode; | ||
238 | } | ||
239 | |||
240 | /* Generate output characters in reverse order */ | ||
241 | niro | 816 | while ((long) code >= (long) 256) { |
242 | niro | 532 | *--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 | niro | 984 | IF_DESKTOP(total_written += outpos;) |
269 | niro | 532 | 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 | niro | 984 | IF_DESKTOP(total_written += outpos;) |
298 | niro | 532 | } |
299 | |||
300 | niro | 984 | retval = IF_DESKTOP(total_written) + 0; |
301 | niro | 816 | err: |
302 | free(inbuf); | ||
303 | free(outbuf); | ||
304 | free(htab); | ||
305 | free(codetab); | ||
306 | return retval; | ||
307 | niro | 532 | } |