diff options
Diffstat (limited to 'rbutil/rbutilqt/mspack/mszipd.c')
-rw-r--r-- | rbutil/rbutilqt/mspack/mszipd.c | 268 |
1 files changed, 154 insertions, 114 deletions
diff --git a/rbutil/rbutilqt/mspack/mszipd.c b/rbutil/rbutilqt/mspack/mszipd.c index 3c158fbd4d..c1b02b1207 100644 --- a/rbutil/rbutilqt/mspack/mszipd.c +++ b/rbutil/rbutilqt/mspack/mszipd.c | |||
@@ -20,9 +20,9 @@ | |||
20 | #define BITS_VAR zip | 20 | #define BITS_VAR zip |
21 | #define BITS_ORDER_LSB | 21 | #define BITS_ORDER_LSB |
22 | #define BITS_LSB_TABLE | 22 | #define BITS_LSB_TABLE |
23 | #define READ_BYTES do { \ | 23 | #define READ_BYTES do { \ |
24 | READ_IF_NEEDED; \ | 24 | READ_IF_NEEDED; \ |
25 | INJECT_BITS(*i_ptr++, 8); \ | 25 | INJECT_BITS(*i_ptr++, 8); \ |
26 | } while (0) | 26 | } while (0) |
27 | #include "readbits.h" | 27 | #include "readbits.h" |
28 | 28 | ||
@@ -34,13 +34,13 @@ | |||
34 | #define HUFF_ERROR return INF_ERR_HUFFSYM | 34 | #define HUFF_ERROR return INF_ERR_HUFFSYM |
35 | #include "readhuff.h" | 35 | #include "readhuff.h" |
36 | 36 | ||
37 | #define FLUSH_IF_NEEDED do { \ | 37 | #define FLUSH_IF_NEEDED do { \ |
38 | if (zip->window_posn == MSZIP_FRAME_SIZE) { \ | 38 | if (zip->window_posn == MSZIP_FRAME_SIZE) { \ |
39 | if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) { \ | 39 | if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) { \ |
40 | return INF_ERR_FLUSH; \ | 40 | return INF_ERR_FLUSH; \ |
41 | } \ | 41 | } \ |
42 | zip->window_posn = 0; \ | 42 | zip->window_posn = 0; \ |
43 | } \ | 43 | } \ |
44 | } while (0) | 44 | } while (0) |
45 | 45 | ||
46 | /* match lengths for literal codes 257.. 285 */ | 46 | /* match lengths for literal codes 257.. 285 */ |
@@ -181,14 +181,14 @@ static int inflate(struct mszipd_stream *zip) { | |||
181 | 181 | ||
182 | /* read 4 bytes of data, emptying the bit-buffer if necessary */ | 182 | /* read 4 bytes of data, emptying the bit-buffer if necessary */ |
183 | for (i = 0; (bits_left >= 8); i++) { | 183 | for (i = 0; (bits_left >= 8); i++) { |
184 | if (i == 4) return INF_ERR_BITBUF; | 184 | if (i == 4) return INF_ERR_BITBUF; |
185 | lens_buf[i] = PEEK_BITS(8); | 185 | lens_buf[i] = PEEK_BITS(8); |
186 | REMOVE_BITS(8); | 186 | REMOVE_BITS(8); |
187 | } | 187 | } |
188 | if (bits_left != 0) return INF_ERR_BITBUF; | 188 | if (bits_left != 0) return INF_ERR_BITBUF; |
189 | while (i < 4) { | 189 | while (i < 4) { |
190 | READ_IF_NEEDED; | 190 | READ_IF_NEEDED; |
191 | lens_buf[i++] = *i_ptr++; | 191 | lens_buf[i++] = *i_ptr++; |
192 | } | 192 | } |
193 | 193 | ||
194 | /* get the length and its complement */ | 194 | /* get the length and its complement */ |
@@ -198,18 +198,18 @@ static int inflate(struct mszipd_stream *zip) { | |||
198 | 198 | ||
199 | /* read and copy the uncompressed data into the window */ | 199 | /* read and copy the uncompressed data into the window */ |
200 | while (length > 0) { | 200 | while (length > 0) { |
201 | READ_IF_NEEDED; | 201 | READ_IF_NEEDED; |
202 | 202 | ||
203 | this_run = length; | 203 | this_run = length; |
204 | if (this_run > (unsigned int)(i_end - i_ptr)) this_run = i_end - i_ptr; | 204 | if (this_run > (unsigned int)(i_end - i_ptr)) this_run = i_end - i_ptr; |
205 | if (this_run > (MSZIP_FRAME_SIZE - zip->window_posn)) | 205 | if (this_run > (MSZIP_FRAME_SIZE - zip->window_posn)) |
206 | this_run = MSZIP_FRAME_SIZE - zip->window_posn; | 206 | this_run = MSZIP_FRAME_SIZE - zip->window_posn; |
207 | 207 | ||
208 | zip->sys->copy(i_ptr, &zip->window[zip->window_posn], this_run); | 208 | zip->sys->copy(i_ptr, &zip->window[zip->window_posn], this_run); |
209 | zip->window_posn += this_run; | 209 | zip->window_posn += this_run; |
210 | i_ptr += this_run; | 210 | i_ptr += this_run; |
211 | length -= this_run; | 211 | length -= this_run; |
212 | FLUSH_IF_NEEDED; | 212 | FLUSH_IF_NEEDED; |
213 | } | 213 | } |
214 | } | 214 | } |
215 | else if ((block_type == 1) || (block_type == 2)) { | 215 | else if ((block_type == 1) || (block_type == 2)) { |
@@ -217,92 +217,92 @@ static int inflate(struct mszipd_stream *zip) { | |||
217 | unsigned int match_posn, code; | 217 | unsigned int match_posn, code; |
218 | 218 | ||
219 | if (block_type == 1) { | 219 | if (block_type == 1) { |
220 | /* block with fixed Huffman codes */ | 220 | /* block with fixed Huffman codes */ |
221 | i = 0; | 221 | i = 0; |
222 | while (i < 144) zip->LITERAL_len[i++] = 8; | 222 | while (i < 144) zip->LITERAL_len[i++] = 8; |
223 | while (i < 256) zip->LITERAL_len[i++] = 9; | 223 | while (i < 256) zip->LITERAL_len[i++] = 9; |
224 | while (i < 280) zip->LITERAL_len[i++] = 7; | 224 | while (i < 280) zip->LITERAL_len[i++] = 7; |
225 | while (i < 288) zip->LITERAL_len[i++] = 8; | 225 | while (i < 288) zip->LITERAL_len[i++] = 8; |
226 | for (i = 0; i < 32; i++) zip->DISTANCE_len[i] = 5; | 226 | for (i = 0; i < 32; i++) zip->DISTANCE_len[i] = 5; |
227 | } | 227 | } |
228 | else { | 228 | else { |
229 | /* block with dynamic Huffman codes */ | 229 | /* block with dynamic Huffman codes */ |
230 | STORE_BITS; | 230 | STORE_BITS; |
231 | if ((i = zip_read_lens(zip))) return i; | 231 | if ((i = zip_read_lens(zip))) return i; |
232 | RESTORE_BITS; | 232 | RESTORE_BITS; |
233 | } | 233 | } |
234 | 234 | ||
235 | /* now huffman lengths are read for either kind of block, | 235 | /* now huffman lengths are read for either kind of block, |
236 | * create huffman decoding tables */ | 236 | * create huffman decoding tables */ |
237 | if (make_decode_table(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, | 237 | if (make_decode_table(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, |
238 | &zip->LITERAL_len[0], &zip->LITERAL_table[0])) | 238 | &zip->LITERAL_len[0], &zip->LITERAL_table[0])) |
239 | { | 239 | { |
240 | return INF_ERR_LITERALTBL; | 240 | return INF_ERR_LITERALTBL; |
241 | } | 241 | } |
242 | 242 | ||
243 | if (make_decode_table(MSZIP_DISTANCE_MAXSYMBOLS,MSZIP_DISTANCE_TABLEBITS, | 243 | if (make_decode_table(MSZIP_DISTANCE_MAXSYMBOLS,MSZIP_DISTANCE_TABLEBITS, |
244 | &zip->DISTANCE_len[0], &zip->DISTANCE_table[0])) | 244 | &zip->DISTANCE_len[0], &zip->DISTANCE_table[0])) |
245 | { | 245 | { |
246 | return INF_ERR_DISTANCETBL; | 246 | return INF_ERR_DISTANCETBL; |
247 | } | 247 | } |
248 | 248 | ||
249 | /* decode forever until end of block code */ | 249 | /* decode forever until end of block code */ |
250 | for (;;) { | 250 | for (;;) { |
251 | READ_HUFFSYM(LITERAL, code); | 251 | READ_HUFFSYM(LITERAL, code); |
252 | if (code < 256) { | 252 | if (code < 256) { |
253 | zip->window[zip->window_posn++] = (unsigned char) code; | 253 | zip->window[zip->window_posn++] = (unsigned char) code; |
254 | FLUSH_IF_NEEDED; | 254 | FLUSH_IF_NEEDED; |
255 | } | 255 | } |
256 | else if (code == 256) { | 256 | else if (code == 256) { |
257 | /* END OF BLOCK CODE: loop break point */ | 257 | /* END OF BLOCK CODE: loop break point */ |
258 | break; | 258 | break; |
259 | } | 259 | } |
260 | else { | 260 | else { |
261 | code -= 257; /* codes 257-285 are matches */ | 261 | code -= 257; /* codes 257-285 are matches */ |
262 | if (code >= 29) return INF_ERR_LITCODE; /* codes 286-287 are illegal */ | 262 | if (code >= 29) return INF_ERR_LITCODE; /* codes 286-287 are illegal */ |
263 | READ_BITS_T(length, lit_extrabits[code]); | 263 | READ_BITS_T(length, lit_extrabits[code]); |
264 | length += lit_lengths[code]; | 264 | length += lit_lengths[code]; |
265 | 265 | ||
266 | READ_HUFFSYM(DISTANCE, code); | 266 | READ_HUFFSYM(DISTANCE, code); |
267 | if (code > 30) return INF_ERR_DISTCODE; | 267 | if (code >= 30) return INF_ERR_DISTCODE; |
268 | READ_BITS_T(distance, dist_extrabits[code]); | 268 | READ_BITS_T(distance, dist_extrabits[code]); |
269 | distance += dist_offsets[code]; | 269 | distance += dist_offsets[code]; |
270 | 270 | ||
271 | /* match position is window position minus distance. If distance | 271 | /* match position is window position minus distance. If distance |
272 | * is more than window position numerically, it must 'wrap | 272 | * is more than window position numerically, it must 'wrap |
273 | * around' the frame size. */ | 273 | * around' the frame size. */ |
274 | match_posn = ((distance > zip->window_posn) ? MSZIP_FRAME_SIZE : 0) | 274 | match_posn = ((distance > zip->window_posn) ? MSZIP_FRAME_SIZE : 0) |
275 | + zip->window_posn - distance; | 275 | + zip->window_posn - distance; |
276 | 276 | ||
277 | /* copy match */ | 277 | /* copy match */ |
278 | if (length < 12) { | 278 | if (length < 12) { |
279 | /* short match, use slower loop but no loop setup code */ | 279 | /* short match, use slower loop but no loop setup code */ |
280 | while (length--) { | 280 | while (length--) { |
281 | zip->window[zip->window_posn++] = zip->window[match_posn++]; | 281 | zip->window[zip->window_posn++] = zip->window[match_posn++]; |
282 | match_posn &= MSZIP_FRAME_SIZE - 1; | 282 | match_posn &= MSZIP_FRAME_SIZE - 1; |
283 | FLUSH_IF_NEEDED; | 283 | FLUSH_IF_NEEDED; |
284 | } | 284 | } |
285 | } | 285 | } |
286 | else { | 286 | else { |
287 | /* longer match, use faster loop but with setup expense */ | 287 | /* longer match, use faster loop but with setup expense */ |
288 | unsigned char *runsrc, *rundest; | 288 | unsigned char *runsrc, *rundest; |
289 | do { | 289 | do { |
290 | this_run = length; | 290 | this_run = length; |
291 | if ((match_posn + this_run) > MSZIP_FRAME_SIZE) | 291 | if ((match_posn + this_run) > MSZIP_FRAME_SIZE) |
292 | this_run = MSZIP_FRAME_SIZE - match_posn; | 292 | this_run = MSZIP_FRAME_SIZE - match_posn; |
293 | if ((zip->window_posn + this_run) > MSZIP_FRAME_SIZE) | 293 | if ((zip->window_posn + this_run) > MSZIP_FRAME_SIZE) |
294 | this_run = MSZIP_FRAME_SIZE - zip->window_posn; | 294 | this_run = MSZIP_FRAME_SIZE - zip->window_posn; |
295 | 295 | ||
296 | rundest = &zip->window[zip->window_posn]; zip->window_posn += this_run; | 296 | rundest = &zip->window[zip->window_posn]; zip->window_posn += this_run; |
297 | runsrc = &zip->window[match_posn]; match_posn += this_run; | 297 | runsrc = &zip->window[match_posn]; match_posn += this_run; |
298 | length -= this_run; | 298 | length -= this_run; |
299 | while (this_run--) *rundest++ = *runsrc++; | 299 | while (this_run--) *rundest++ = *runsrc++; |
300 | if (match_posn == MSZIP_FRAME_SIZE) match_posn = 0; | 300 | if (match_posn == MSZIP_FRAME_SIZE) match_posn = 0; |
301 | FLUSH_IF_NEEDED; | 301 | FLUSH_IF_NEEDED; |
302 | } while (length > 0); | 302 | } while (length > 0); |
303 | } | 303 | } |
304 | 304 | ||
305 | } /* else (code >= 257) */ | 305 | } /* else (code >= 257) */ |
306 | 306 | ||
307 | } /* for(;;) -- break point at 'code == 256' */ | 307 | } /* for(;;) -- break point at 'code == 256' */ |
308 | } | 308 | } |
@@ -328,7 +328,7 @@ static int inflate(struct mszipd_stream *zip) { | |||
328 | * is flushed, an error is raised. | 328 | * is flushed, an error is raised. |
329 | */ | 329 | */ |
330 | static int mszipd_flush_window(struct mszipd_stream *zip, | 330 | static int mszipd_flush_window(struct mszipd_stream *zip, |
331 | unsigned int data_flushed) | 331 | unsigned int data_flushed) |
332 | { | 332 | { |
333 | zip->bytes_output += data_flushed; | 333 | zip->bytes_output += data_flushed; |
334 | if (zip->bytes_output > MSZIP_FRAME_SIZE) { | 334 | if (zip->bytes_output > MSZIP_FRAME_SIZE) { |
@@ -340,17 +340,18 @@ static int mszipd_flush_window(struct mszipd_stream *zip, | |||
340 | } | 340 | } |
341 | 341 | ||
342 | struct mszipd_stream *mszipd_init(struct mspack_system *system, | 342 | struct mszipd_stream *mszipd_init(struct mspack_system *system, |
343 | struct mspack_file *input, | 343 | struct mspack_file *input, |
344 | struct mspack_file *output, | 344 | struct mspack_file *output, |
345 | int input_buffer_size, | 345 | int input_buffer_size, |
346 | int repair_mode) | 346 | int repair_mode) |
347 | { | 347 | { |
348 | struct mszipd_stream *zip; | 348 | struct mszipd_stream *zip; |
349 | 349 | ||
350 | if (!system) return NULL; | 350 | if (!system) return NULL; |
351 | 351 | ||
352 | /* round up input buffer size to multiple of two */ | ||
352 | input_buffer_size = (input_buffer_size + 1) & -2; | 353 | input_buffer_size = (input_buffer_size + 1) & -2; |
353 | if (!input_buffer_size) return NULL; | 354 | if (input_buffer_size < 2) return NULL; |
354 | 355 | ||
355 | /* allocate decompression state */ | 356 | /* allocate decompression state */ |
356 | if (!(zip = (struct mszipd_stream *) system->alloc(system, sizeof(struct mszipd_stream)))) { | 357 | if (!(zip = (struct mszipd_stream *) system->alloc(system, sizeof(struct mszipd_stream)))) { |
@@ -426,19 +427,19 @@ int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes) { | |||
426 | if ((error = inflate(zip))) { | 427 | if ((error = inflate(zip))) { |
427 | D(("inflate error %d", error)) | 428 | D(("inflate error %d", error)) |
428 | if (zip->repair_mode) { | 429 | if (zip->repair_mode) { |
429 | /* recover partially-inflated buffers */ | 430 | /* recover partially-inflated buffers */ |
430 | if (zip->bytes_output == 0 && zip->window_posn > 0) { | 431 | if (zip->bytes_output == 0 && zip->window_posn > 0) { |
431 | zip->flush_window(zip, zip->window_posn); | 432 | zip->flush_window(zip, zip->window_posn); |
432 | } | 433 | } |
433 | zip->sys->message(NULL, "MSZIP error, %u bytes of data lost.", | 434 | zip->sys->message(NULL, "MSZIP error, %u bytes of data lost.", |
434 | MSZIP_FRAME_SIZE - zip->bytes_output); | 435 | MSZIP_FRAME_SIZE - zip->bytes_output); |
435 | for (i = zip->bytes_output; i < MSZIP_FRAME_SIZE; i++) { | 436 | for (i = zip->bytes_output; i < MSZIP_FRAME_SIZE; i++) { |
436 | zip->window[i] = '\0'; | 437 | zip->window[i] = '\0'; |
437 | } | 438 | } |
438 | zip->bytes_output = MSZIP_FRAME_SIZE; | 439 | zip->bytes_output = MSZIP_FRAME_SIZE; |
439 | } | 440 | } |
440 | else { | 441 | else { |
441 | return zip->error = (error > 0) ? error : MSPACK_ERR_DECRUNCH; | 442 | return zip->error = (error > 0) ? error : MSPACK_ERR_DECRUNCH; |
442 | } | 443 | } |
443 | } | 444 | } |
444 | zip->o_ptr = &zip->window[0]; | 445 | zip->o_ptr = &zip->window[0]; |
@@ -465,6 +466,45 @@ int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes) { | |||
465 | return MSPACK_ERR_OK; | 466 | return MSPACK_ERR_OK; |
466 | } | 467 | } |
467 | 468 | ||
469 | int mszipd_decompress_kwaj(struct mszipd_stream *zip) { | ||
470 | /* for the bit buffer */ | ||
471 | register unsigned int bit_buffer; | ||
472 | register int bits_left; | ||
473 | unsigned char *i_ptr, *i_end; | ||
474 | |||
475 | int i, error, block_len; | ||
476 | |||
477 | /* unpack blocks until block_len == 0 */ | ||
478 | for (;;) { | ||
479 | RESTORE_BITS; | ||
480 | |||
481 | /* align to bytestream, read block_len */ | ||
482 | i = bits_left & 7; REMOVE_BITS(i); | ||
483 | READ_BITS(block_len, 8); | ||
484 | READ_BITS(i, 8); block_len |= i << 8; | ||
485 | |||
486 | if (block_len == 0) break; | ||
487 | |||
488 | /* read "CK" header */ | ||
489 | READ_BITS(i, 8); if (i != 'C') return MSPACK_ERR_DATAFORMAT; | ||
490 | READ_BITS(i, 8); if (i != 'K') return MSPACK_ERR_DATAFORMAT; | ||
491 | |||
492 | /* inflate block */ | ||
493 | zip->window_posn = 0; | ||
494 | zip->bytes_output = 0; | ||
495 | STORE_BITS; | ||
496 | if ((error = inflate(zip))) { | ||
497 | D(("inflate error %d", error)) | ||
498 | return zip->error = (error > 0) ? error : MSPACK_ERR_DECRUNCH; | ||
499 | } | ||
500 | |||
501 | /* write inflated block */ | ||
502 | if (zip->sys->write(zip->output, &zip->window[0], zip->bytes_output) | ||
503 | != zip->bytes_output) return zip->error = MSPACK_ERR_WRITE; | ||
504 | } | ||
505 | return MSPACK_ERR_OK; | ||
506 | } | ||
507 | |||
468 | void mszipd_free(struct mszipd_stream *zip) { | 508 | void mszipd_free(struct mszipd_stream *zip) { |
469 | struct mspack_system *sys; | 509 | struct mspack_system *sys; |
470 | if (zip) { | 510 | if (zip) { |