OLD | NEW |
| (Empty) |
1 | |
2 /*-------------------------------------------------------------*/ | |
3 /*--- Library top-level functions. ---*/ | |
4 /*--- bzlib.c ---*/ | |
5 /*-------------------------------------------------------------*/ | |
6 | |
7 /* ------------------------------------------------------------------ | |
8 This file is part of bzip2/libbzip2, a program and library for | |
9 lossless, block-sorting data compression. | |
10 | |
11 bzip2/libbzip2 version 1.0.6 of 6 September 2010 | |
12 Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org> | |
13 | |
14 Please read the WARNING, DISCLAIMER and PATENTS sections in the | |
15 README file. | |
16 | |
17 This program is released under the terms of the license contained | |
18 in the file LICENSE. | |
19 ------------------------------------------------------------------ */ | |
20 | |
21 /* CHANGES | |
22 0.9.0 -- original version. | |
23 0.9.0a/b -- no changes in this file. | |
24 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). | |
25 fixed bzWrite/bzRead to ignore zero-length requests. | |
26 fixed bzread to correctly handle read requests after EOF. | |
27 wrong parameter order in call to bzDecompressInit in | |
28 bzBuffToBuffDecompress. Fixed. | |
29 */ | |
30 | |
31 #include "bzlib_private.h" | |
32 | |
33 | |
34 /*---------------------------------------------------*/ | |
35 /*--- Compression stuff ---*/ | |
36 /*---------------------------------------------------*/ | |
37 | |
38 | |
39 /*---------------------------------------------------*/ | |
40 #ifndef BZ_NO_STDIO | |
41 void BZ2_bz__AssertH__fail ( int errcode ) | |
42 { | |
43 fprintf(stderr, | |
44 "\n\nbzip2/libbzip2: internal error number %d.\n" | |
45 "This is a bug in bzip2/libbzip2, %s.\n" | |
46 "Please report it to me at: jseward@bzip.org. If this happened\n" | |
47 "when you were using some program which uses libbzip2 as a\n" | |
48 "component, you should also report this bug to the author(s)\n" | |
49 "of that program. Please make an effort to report this bug;\n" | |
50 "timely and accurate bug reports eventually lead to higher\n" | |
51 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n", | |
52 errcode, | |
53 BZ2_bzlibVersion() | |
54 ); | |
55 | |
56 if (errcode == 1007) { | |
57 fprintf(stderr, | |
58 "\n*** A special note about internal error number 1007 ***\n" | |
59 "\n" | |
60 "Experience suggests that a common cause of i.e. 1007\n" | |
61 "is unreliable memory or other hardware. The 1007 assertion\n" | |
62 "just happens to cross-check the results of huge numbers of\n" | |
63 "memory reads/writes, and so acts (unintendedly) as a stress\n" | |
64 "test of your memory system.\n" | |
65 "\n" | |
66 "I suggest the following: try compressing the file again,\n" | |
67 "possibly monitoring progress in detail with the -vv flag.\n" | |
68 "\n" | |
69 "* If the error cannot be reproduced, and/or happens at different\n" | |
70 " points in compression, you may have a flaky memory system.\n" | |
71 " Try a memory-test program. I have used Memtest86\n" | |
72 " (www.memtest86.com). At the time of writing it is free (GPLd).\n" | |
73 " Memtest86 tests memory much more thorougly than your BIOSs\n" | |
74 " power-on test, and may find failures that the BIOS doesn't.\n" | |
75 "\n" | |
76 "* If the error can be repeatably reproduced, this is a bug in\n" | |
77 " bzip2, and I would very much like to hear about it. Please\n" | |
78 " let me know, and, ideally, save a copy of the file causing the\n" | |
79 " problem -- without which I will be unable to investigate it.\n" | |
80 "\n" | |
81 ); | |
82 } | |
83 | |
84 exit(3); | |
85 } | |
86 #endif | |
87 | |
88 | |
89 /*---------------------------------------------------*/ | |
90 static | |
91 int bz_config_ok ( void ) | |
92 { | |
93 if (sizeof(int) != 4) return 0; | |
94 if (sizeof(short) != 2) return 0; | |
95 if (sizeof(char) != 1) return 0; | |
96 return 1; | |
97 } | |
98 | |
99 | |
100 /*---------------------------------------------------*/ | |
101 static | |
102 void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) | |
103 { | |
104 void* v = malloc ( items * size ); | |
105 return v; | |
106 } | |
107 | |
108 static | |
109 void default_bzfree ( void* opaque, void* addr ) | |
110 { | |
111 if (addr != NULL) free ( addr ); | |
112 } | |
113 | |
114 | |
115 /*---------------------------------------------------*/ | |
116 static | |
117 void prepare_new_block ( EState* s ) | |
118 { | |
119 Int32 i; | |
120 s->nblock = 0; | |
121 s->numZ = 0; | |
122 s->state_out_pos = 0; | |
123 BZ_INITIALISE_CRC ( s->blockCRC ); | |
124 for (i = 0; i < 256; i++) s->inUse[i] = False; | |
125 s->blockNo++; | |
126 } | |
127 | |
128 | |
129 /*---------------------------------------------------*/ | |
130 static | |
131 void init_RL ( EState* s ) | |
132 { | |
133 s->state_in_ch = 256; | |
134 s->state_in_len = 0; | |
135 } | |
136 | |
137 | |
138 static | |
139 Bool isempty_RL ( EState* s ) | |
140 { | |
141 if (s->state_in_ch < 256 && s->state_in_len > 0) | |
142 return False; else | |
143 return True; | |
144 } | |
145 | |
146 | |
147 /*---------------------------------------------------*/ | |
148 int BZ_API(BZ2_bzCompressInit) | |
149 ( bz_stream* strm, | |
150 int blockSize100k, | |
151 int verbosity, | |
152 int workFactor ) | |
153 { | |
154 Int32 n; | |
155 EState* s; | |
156 | |
157 if (!bz_config_ok()) return BZ_CONFIG_ERROR; | |
158 | |
159 if (strm == NULL || | |
160 blockSize100k < 1 || blockSize100k > 9 || | |
161 workFactor < 0 || workFactor > 250) | |
162 return BZ_PARAM_ERROR; | |
163 | |
164 if (workFactor == 0) workFactor = 30; | |
165 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; | |
166 if (strm->bzfree == NULL) strm->bzfree = default_bzfree; | |
167 | |
168 s = BZALLOC( sizeof(EState) ); | |
169 if (s == NULL) return BZ_MEM_ERROR; | |
170 s->strm = strm; | |
171 | |
172 s->arr1 = NULL; | |
173 s->arr2 = NULL; | |
174 s->ftab = NULL; | |
175 | |
176 n = 100000 * blockSize100k; | |
177 s->arr1 = BZALLOC( n * sizeof(UInt32) ); | |
178 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); | |
179 s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); | |
180 | |
181 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { | |
182 if (s->arr1 != NULL) BZFREE(s->arr1); | |
183 if (s->arr2 != NULL) BZFREE(s->arr2); | |
184 if (s->ftab != NULL) BZFREE(s->ftab); | |
185 if (s != NULL) BZFREE(s); | |
186 return BZ_MEM_ERROR; | |
187 } | |
188 | |
189 s->blockNo = 0; | |
190 s->state = BZ_S_INPUT; | |
191 s->mode = BZ_M_RUNNING; | |
192 s->combinedCRC = 0; | |
193 s->blockSize100k = blockSize100k; | |
194 s->nblockMAX = 100000 * blockSize100k - 19; | |
195 s->verbosity = verbosity; | |
196 s->workFactor = workFactor; | |
197 | |
198 s->block = (UChar*)s->arr2; | |
199 s->mtfv = (UInt16*)s->arr1; | |
200 s->zbits = NULL; | |
201 s->ptr = (UInt32*)s->arr1; | |
202 | |
203 strm->state = s; | |
204 strm->total_in_lo32 = 0; | |
205 strm->total_in_hi32 = 0; | |
206 strm->total_out_lo32 = 0; | |
207 strm->total_out_hi32 = 0; | |
208 init_RL ( s ); | |
209 prepare_new_block ( s ); | |
210 return BZ_OK; | |
211 } | |
212 | |
213 | |
214 /*---------------------------------------------------*/ | |
215 static | |
216 void add_pair_to_block ( EState* s ) | |
217 { | |
218 Int32 i; | |
219 UChar ch = (UChar)(s->state_in_ch); | |
220 for (i = 0; i < s->state_in_len; i++) { | |
221 BZ_UPDATE_CRC( s->blockCRC, ch ); | |
222 } | |
223 s->inUse[s->state_in_ch] = True; | |
224 switch (s->state_in_len) { | |
225 case 1: | |
226 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
227 break; | |
228 case 2: | |
229 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
230 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
231 break; | |
232 case 3: | |
233 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
234 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
235 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
236 break; | |
237 default: | |
238 s->inUse[s->state_in_len-4] = True; | |
239 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
240 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
241 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
242 s->block[s->nblock] = (UChar)ch; s->nblock++; | |
243 s->block[s->nblock] = ((UChar)(s->state_in_len-4)); | |
244 s->nblock++; | |
245 break; | |
246 } | |
247 } | |
248 | |
249 | |
250 /*---------------------------------------------------*/ | |
251 static | |
252 void flush_RL ( EState* s ) | |
253 { | |
254 if (s->state_in_ch < 256) add_pair_to_block ( s ); | |
255 init_RL ( s ); | |
256 } | |
257 | |
258 | |
259 /*---------------------------------------------------*/ | |
260 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \ | |
261 { \ | |
262 UInt32 zchh = (UInt32)(zchh0); \ | |
263 /*-- fast track the common case --*/ \ | |
264 if (zchh != zs->state_in_ch && \ | |
265 zs->state_in_len == 1) { \ | |
266 UChar ch = (UChar)(zs->state_in_ch); \ | |
267 BZ_UPDATE_CRC( zs->blockCRC, ch ); \ | |
268 zs->inUse[zs->state_in_ch] = True; \ | |
269 zs->block[zs->nblock] = (UChar)ch; \ | |
270 zs->nblock++; \ | |
271 zs->state_in_ch = zchh; \ | |
272 } \ | |
273 else \ | |
274 /*-- general, uncommon cases --*/ \ | |
275 if (zchh != zs->state_in_ch || \ | |
276 zs->state_in_len == 255) { \ | |
277 if (zs->state_in_ch < 256) \ | |
278 add_pair_to_block ( zs ); \ | |
279 zs->state_in_ch = zchh; \ | |
280 zs->state_in_len = 1; \ | |
281 } else { \ | |
282 zs->state_in_len++; \ | |
283 } \ | |
284 } | |
285 | |
286 | |
287 /*---------------------------------------------------*/ | |
288 static | |
289 Bool copy_input_until_stop ( EState* s ) | |
290 { | |
291 Bool progress_in = False; | |
292 | |
293 if (s->mode == BZ_M_RUNNING) { | |
294 | |
295 /*-- fast track the common case --*/ | |
296 while (True) { | |
297 /*-- block full? --*/ | |
298 if (s->nblock >= s->nblockMAX) break; | |
299 /*-- no input? --*/ | |
300 if (s->strm->avail_in == 0) break; | |
301 progress_in = True; | |
302 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); | |
303 s->strm->next_in++; | |
304 s->strm->avail_in--; | |
305 s->strm->total_in_lo32++; | |
306 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; | |
307 } | |
308 | |
309 } else { | |
310 | |
311 /*-- general, uncommon case --*/ | |
312 while (True) { | |
313 /*-- block full? --*/ | |
314 if (s->nblock >= s->nblockMAX) break; | |
315 /*-- no input? --*/ | |
316 if (s->strm->avail_in == 0) break; | |
317 /*-- flush/finish end? --*/ | |
318 if (s->avail_in_expect == 0) break; | |
319 progress_in = True; | |
320 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); | |
321 s->strm->next_in++; | |
322 s->strm->avail_in--; | |
323 s->strm->total_in_lo32++; | |
324 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; | |
325 s->avail_in_expect--; | |
326 } | |
327 } | |
328 return progress_in; | |
329 } | |
330 | |
331 | |
332 /*---------------------------------------------------*/ | |
333 static | |
334 Bool copy_output_until_stop ( EState* s ) | |
335 { | |
336 Bool progress_out = False; | |
337 | |
338 while (True) { | |
339 | |
340 /*-- no output space? --*/ | |
341 if (s->strm->avail_out == 0) break; | |
342 | |
343 /*-- block done? --*/ | |
344 if (s->state_out_pos >= s->numZ) break; | |
345 | |
346 progress_out = True; | |
347 *(s->strm->next_out) = s->zbits[s->state_out_pos]; | |
348 s->state_out_pos++; | |
349 s->strm->avail_out--; | |
350 s->strm->next_out++; | |
351 s->strm->total_out_lo32++; | |
352 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
353 } | |
354 | |
355 return progress_out; | |
356 } | |
357 | |
358 | |
359 /*---------------------------------------------------*/ | |
360 static | |
361 Bool handle_compress ( bz_stream* strm ) | |
362 { | |
363 Bool progress_in = False; | |
364 Bool progress_out = False; | |
365 EState* s = strm->state; | |
366 | |
367 while (True) { | |
368 | |
369 if (s->state == BZ_S_OUTPUT) { | |
370 progress_out |= copy_output_until_stop ( s ); | |
371 if (s->state_out_pos < s->numZ) break; | |
372 if (s->mode == BZ_M_FINISHING && | |
373 s->avail_in_expect == 0 && | |
374 isempty_RL(s)) break; | |
375 prepare_new_block ( s ); | |
376 s->state = BZ_S_INPUT; | |
377 if (s->mode == BZ_M_FLUSHING && | |
378 s->avail_in_expect == 0 && | |
379 isempty_RL(s)) break; | |
380 } | |
381 | |
382 if (s->state == BZ_S_INPUT) { | |
383 progress_in |= copy_input_until_stop ( s ); | |
384 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { | |
385 flush_RL ( s ); | |
386 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); | |
387 s->state = BZ_S_OUTPUT; | |
388 } | |
389 else | |
390 if (s->nblock >= s->nblockMAX) { | |
391 BZ2_compressBlock ( s, False ); | |
392 s->state = BZ_S_OUTPUT; | |
393 } | |
394 else | |
395 if (s->strm->avail_in == 0) { | |
396 break; | |
397 } | |
398 } | |
399 | |
400 } | |
401 | |
402 return progress_in || progress_out; | |
403 } | |
404 | |
405 | |
406 /*---------------------------------------------------*/ | |
407 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) | |
408 { | |
409 Bool progress; | |
410 EState* s; | |
411 if (strm == NULL) return BZ_PARAM_ERROR; | |
412 s = strm->state; | |
413 if (s == NULL) return BZ_PARAM_ERROR; | |
414 if (s->strm != strm) return BZ_PARAM_ERROR; | |
415 | |
416 preswitch: | |
417 switch (s->mode) { | |
418 | |
419 case BZ_M_IDLE: | |
420 return BZ_SEQUENCE_ERROR; | |
421 | |
422 case BZ_M_RUNNING: | |
423 if (action == BZ_RUN) { | |
424 progress = handle_compress ( strm ); | |
425 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; | |
426 } | |
427 else | |
428 if (action == BZ_FLUSH) { | |
429 s->avail_in_expect = strm->avail_in; | |
430 s->mode = BZ_M_FLUSHING; | |
431 goto preswitch; | |
432 } | |
433 else | |
434 if (action == BZ_FINISH) { | |
435 s->avail_in_expect = strm->avail_in; | |
436 s->mode = BZ_M_FINISHING; | |
437 goto preswitch; | |
438 } | |
439 else | |
440 return BZ_PARAM_ERROR; | |
441 | |
442 case BZ_M_FLUSHING: | |
443 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; | |
444 if (s->avail_in_expect != s->strm->avail_in) | |
445 return BZ_SEQUENCE_ERROR; | |
446 progress = handle_compress ( strm ); | |
447 if (s->avail_in_expect > 0 || !isempty_RL(s) || | |
448 s->state_out_pos < s->numZ) return BZ_FLUSH_OK; | |
449 s->mode = BZ_M_RUNNING; | |
450 return BZ_RUN_OK; | |
451 | |
452 case BZ_M_FINISHING: | |
453 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; | |
454 if (s->avail_in_expect != s->strm->avail_in) | |
455 return BZ_SEQUENCE_ERROR; | |
456 progress = handle_compress ( strm ); | |
457 if (!progress) return BZ_SEQUENCE_ERROR; | |
458 if (s->avail_in_expect > 0 || !isempty_RL(s) || | |
459 s->state_out_pos < s->numZ) return BZ_FINISH_OK; | |
460 s->mode = BZ_M_IDLE; | |
461 return BZ_STREAM_END; | |
462 } | |
463 return BZ_OK; /*--not reached--*/ | |
464 } | |
465 | |
466 | |
467 /*---------------------------------------------------*/ | |
468 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) | |
469 { | |
470 EState* s; | |
471 if (strm == NULL) return BZ_PARAM_ERROR; | |
472 s = strm->state; | |
473 if (s == NULL) return BZ_PARAM_ERROR; | |
474 if (s->strm != strm) return BZ_PARAM_ERROR; | |
475 | |
476 if (s->arr1 != NULL) BZFREE(s->arr1); | |
477 if (s->arr2 != NULL) BZFREE(s->arr2); | |
478 if (s->ftab != NULL) BZFREE(s->ftab); | |
479 BZFREE(strm->state); | |
480 | |
481 strm->state = NULL; | |
482 | |
483 return BZ_OK; | |
484 } | |
485 | |
486 | |
487 /*---------------------------------------------------*/ | |
488 /*--- Decompression stuff ---*/ | |
489 /*---------------------------------------------------*/ | |
490 | |
491 /*---------------------------------------------------*/ | |
492 int BZ_API(BZ2_bzDecompressInit) | |
493 ( bz_stream* strm, | |
494 int verbosity, | |
495 int small ) | |
496 { | |
497 DState* s; | |
498 | |
499 if (!bz_config_ok()) return BZ_CONFIG_ERROR; | |
500 | |
501 if (strm == NULL) return BZ_PARAM_ERROR; | |
502 if (small != 0 && small != 1) return BZ_PARAM_ERROR; | |
503 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; | |
504 | |
505 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; | |
506 if (strm->bzfree == NULL) strm->bzfree = default_bzfree; | |
507 | |
508 s = BZALLOC( sizeof(DState) ); | |
509 if (s == NULL) return BZ_MEM_ERROR; | |
510 s->strm = strm; | |
511 strm->state = s; | |
512 s->state = BZ_X_MAGIC_1; | |
513 s->bsLive = 0; | |
514 s->bsBuff = 0; | |
515 s->calculatedCombinedCRC = 0; | |
516 strm->total_in_lo32 = 0; | |
517 strm->total_in_hi32 = 0; | |
518 strm->total_out_lo32 = 0; | |
519 strm->total_out_hi32 = 0; | |
520 s->smallDecompress = (Bool)small; | |
521 s->ll4 = NULL; | |
522 s->ll16 = NULL; | |
523 s->tt = NULL; | |
524 s->currBlockNo = 0; | |
525 s->verbosity = verbosity; | |
526 | |
527 return BZ_OK; | |
528 } | |
529 | |
530 | |
531 /*---------------------------------------------------*/ | |
532 /* Return True iff data corruption is discovered. | |
533 Returns False if there is no problem. | |
534 */ | |
535 static | |
536 Bool unRLE_obuf_to_output_FAST ( DState* s ) | |
537 { | |
538 UChar k1; | |
539 | |
540 if (s->blockRandomised) { | |
541 | |
542 while (True) { | |
543 /* try to finish existing run */ | |
544 while (True) { | |
545 if (s->strm->avail_out == 0) return False; | |
546 if (s->state_out_len == 0) break; | |
547 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; | |
548 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); | |
549 s->state_out_len--; | |
550 s->strm->next_out++; | |
551 s->strm->avail_out--; | |
552 s->strm->total_out_lo32++; | |
553 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
554 } | |
555 | |
556 /* can a new run be started? */ | |
557 if (s->nblock_used == s->save_nblock+1) return False; | |
558 | |
559 /* Only caused by corrupt data stream? */ | |
560 if (s->nblock_used > s->save_nblock+1) | |
561 return True; | |
562 | |
563 s->state_out_len = 1; | |
564 s->state_out_ch = s->k0; | |
565 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
566 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
567 if (s->nblock_used == s->save_nblock+1) continue; | |
568 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
569 | |
570 s->state_out_len = 2; | |
571 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
572 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
573 if (s->nblock_used == s->save_nblock+1) continue; | |
574 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
575 | |
576 s->state_out_len = 3; | |
577 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
578 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
579 if (s->nblock_used == s->save_nblock+1) continue; | |
580 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
581 | |
582 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; | |
583 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
584 s->state_out_len = ((Int32)k1) + 4; | |
585 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; | |
586 s->k0 ^= BZ_RAND_MASK; s->nblock_used++; | |
587 } | |
588 | |
589 } else { | |
590 | |
591 /* restore */ | |
592 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; | |
593 UChar c_state_out_ch = s->state_out_ch; | |
594 Int32 c_state_out_len = s->state_out_len; | |
595 Int32 c_nblock_used = s->nblock_used; | |
596 Int32 c_k0 = s->k0; | |
597 UInt32* c_tt = s->tt; | |
598 UInt32 c_tPos = s->tPos; | |
599 char* cs_next_out = s->strm->next_out; | |
600 unsigned int cs_avail_out = s->strm->avail_out; | |
601 Int32 ro_blockSize100k = s->blockSize100k; | |
602 /* end restore */ | |
603 | |
604 UInt32 avail_out_INIT = cs_avail_out; | |
605 Int32 s_save_nblockPP = s->save_nblock+1; | |
606 unsigned int total_out_lo32_old; | |
607 | |
608 while (True) { | |
609 | |
610 /* try to finish existing run */ | |
611 if (c_state_out_len > 0) { | |
612 while (True) { | |
613 if (cs_avail_out == 0) goto return_notr; | |
614 if (c_state_out_len == 1) break; | |
615 *( (UChar*)(cs_next_out) ) = c_state_out_ch; | |
616 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); | |
617 c_state_out_len--; | |
618 cs_next_out++; | |
619 cs_avail_out--; | |
620 } | |
621 s_state_out_len_eq_one: | |
622 { | |
623 if (cs_avail_out == 0) { | |
624 c_state_out_len = 1; goto return_notr; | |
625 }; | |
626 *( (UChar*)(cs_next_out) ) = c_state_out_ch; | |
627 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); | |
628 cs_next_out++; | |
629 cs_avail_out--; | |
630 } | |
631 } | |
632 /* Only caused by corrupt data stream? */ | |
633 if (c_nblock_used > s_save_nblockPP) | |
634 return True; | |
635 | |
636 /* can a new run be started? */ | |
637 if (c_nblock_used == s_save_nblockPP) { | |
638 c_state_out_len = 0; goto return_notr; | |
639 }; | |
640 c_state_out_ch = c_k0; | |
641 BZ_GET_FAST_C(k1); c_nblock_used++; | |
642 if (k1 != c_k0) { | |
643 c_k0 = k1; goto s_state_out_len_eq_one; | |
644 }; | |
645 if (c_nblock_used == s_save_nblockPP) | |
646 goto s_state_out_len_eq_one; | |
647 | |
648 c_state_out_len = 2; | |
649 BZ_GET_FAST_C(k1); c_nblock_used++; | |
650 if (c_nblock_used == s_save_nblockPP) continue; | |
651 if (k1 != c_k0) { c_k0 = k1; continue; }; | |
652 | |
653 c_state_out_len = 3; | |
654 BZ_GET_FAST_C(k1); c_nblock_used++; | |
655 if (c_nblock_used == s_save_nblockPP) continue; | |
656 if (k1 != c_k0) { c_k0 = k1; continue; }; | |
657 | |
658 BZ_GET_FAST_C(k1); c_nblock_used++; | |
659 c_state_out_len = ((Int32)k1) + 4; | |
660 BZ_GET_FAST_C(c_k0); c_nblock_used++; | |
661 } | |
662 | |
663 return_notr: | |
664 total_out_lo32_old = s->strm->total_out_lo32; | |
665 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); | |
666 if (s->strm->total_out_lo32 < total_out_lo32_old) | |
667 s->strm->total_out_hi32++; | |
668 | |
669 /* save */ | |
670 s->calculatedBlockCRC = c_calculatedBlockCRC; | |
671 s->state_out_ch = c_state_out_ch; | |
672 s->state_out_len = c_state_out_len; | |
673 s->nblock_used = c_nblock_used; | |
674 s->k0 = c_k0; | |
675 s->tt = c_tt; | |
676 s->tPos = c_tPos; | |
677 s->strm->next_out = cs_next_out; | |
678 s->strm->avail_out = cs_avail_out; | |
679 /* end save */ | |
680 } | |
681 return False; | |
682 } | |
683 | |
684 | |
685 | |
686 /*---------------------------------------------------*/ | |
687 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) | |
688 { | |
689 Int32 nb, na, mid; | |
690 nb = 0; | |
691 na = 256; | |
692 do { | |
693 mid = (nb + na) >> 1; | |
694 if (indx >= cftab[mid]) nb = mid; else na = mid; | |
695 } | |
696 while (na - nb != 1); | |
697 return nb; | |
698 } | |
699 | |
700 | |
701 /*---------------------------------------------------*/ | |
702 /* Return True iff data corruption is discovered. | |
703 Returns False if there is no problem. | |
704 */ | |
705 static | |
706 Bool unRLE_obuf_to_output_SMALL ( DState* s ) | |
707 { | |
708 UChar k1; | |
709 | |
710 if (s->blockRandomised) { | |
711 | |
712 while (True) { | |
713 /* try to finish existing run */ | |
714 while (True) { | |
715 if (s->strm->avail_out == 0) return False; | |
716 if (s->state_out_len == 0) break; | |
717 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; | |
718 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); | |
719 s->state_out_len--; | |
720 s->strm->next_out++; | |
721 s->strm->avail_out--; | |
722 s->strm->total_out_lo32++; | |
723 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
724 } | |
725 | |
726 /* can a new run be started? */ | |
727 if (s->nblock_used == s->save_nblock+1) return False; | |
728 | |
729 /* Only caused by corrupt data stream? */ | |
730 if (s->nblock_used > s->save_nblock+1) | |
731 return True; | |
732 | |
733 s->state_out_len = 1; | |
734 s->state_out_ch = s->k0; | |
735 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
736 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
737 if (s->nblock_used == s->save_nblock+1) continue; | |
738 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
739 | |
740 s->state_out_len = 2; | |
741 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
742 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
743 if (s->nblock_used == s->save_nblock+1) continue; | |
744 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
745 | |
746 s->state_out_len = 3; | |
747 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
748 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
749 if (s->nblock_used == s->save_nblock+1) continue; | |
750 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
751 | |
752 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; | |
753 k1 ^= BZ_RAND_MASK; s->nblock_used++; | |
754 s->state_out_len = ((Int32)k1) + 4; | |
755 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; | |
756 s->k0 ^= BZ_RAND_MASK; s->nblock_used++; | |
757 } | |
758 | |
759 } else { | |
760 | |
761 while (True) { | |
762 /* try to finish existing run */ | |
763 while (True) { | |
764 if (s->strm->avail_out == 0) return False; | |
765 if (s->state_out_len == 0) break; | |
766 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; | |
767 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); | |
768 s->state_out_len--; | |
769 s->strm->next_out++; | |
770 s->strm->avail_out--; | |
771 s->strm->total_out_lo32++; | |
772 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; | |
773 } | |
774 | |
775 /* can a new run be started? */ | |
776 if (s->nblock_used == s->save_nblock+1) return False; | |
777 | |
778 /* Only caused by corrupt data stream? */ | |
779 if (s->nblock_used > s->save_nblock+1) | |
780 return True; | |
781 | |
782 s->state_out_len = 1; | |
783 s->state_out_ch = s->k0; | |
784 BZ_GET_SMALL(k1); s->nblock_used++; | |
785 if (s->nblock_used == s->save_nblock+1) continue; | |
786 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
787 | |
788 s->state_out_len = 2; | |
789 BZ_GET_SMALL(k1); s->nblock_used++; | |
790 if (s->nblock_used == s->save_nblock+1) continue; | |
791 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
792 | |
793 s->state_out_len = 3; | |
794 BZ_GET_SMALL(k1); s->nblock_used++; | |
795 if (s->nblock_used == s->save_nblock+1) continue; | |
796 if (k1 != s->k0) { s->k0 = k1; continue; }; | |
797 | |
798 BZ_GET_SMALL(k1); s->nblock_used++; | |
799 s->state_out_len = ((Int32)k1) + 4; | |
800 BZ_GET_SMALL(s->k0); s->nblock_used++; | |
801 } | |
802 | |
803 } | |
804 } | |
805 | |
806 | |
807 /*---------------------------------------------------*/ | |
808 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) | |
809 { | |
810 Bool corrupt; | |
811 DState* s; | |
812 if (strm == NULL) return BZ_PARAM_ERROR; | |
813 s = strm->state; | |
814 if (s == NULL) return BZ_PARAM_ERROR; | |
815 if (s->strm != strm) return BZ_PARAM_ERROR; | |
816 | |
817 while (True) { | |
818 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; | |
819 if (s->state == BZ_X_OUTPUT) { | |
820 if (s->smallDecompress) | |
821 corrupt = unRLE_obuf_to_output_SMALL ( s ); else | |
822 corrupt = unRLE_obuf_to_output_FAST ( s ); | |
823 if (corrupt) return BZ_DATA_ERROR; | |
824 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { | |
825 BZ_FINALISE_CRC ( s->calculatedBlockCRC ); | |
826 if (s->verbosity >= 3) | |
827 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, | |
828 s->calculatedBlockCRC ); | |
829 if (s->verbosity >= 2) VPrintf0 ( "]" ); | |
830 if (s->calculatedBlockCRC != s->storedBlockCRC) | |
831 return BZ_DATA_ERROR; | |
832 s->calculatedCombinedCRC | |
833 = (s->calculatedCombinedCRC << 1) | | |
834 (s->calculatedCombinedCRC >> 31); | |
835 s->calculatedCombinedCRC ^= s->calculatedBlockCRC; | |
836 s->state = BZ_X_BLKHDR_1; | |
837 } else { | |
838 return BZ_OK; | |
839 } | |
840 } | |
841 if (s->state >= BZ_X_MAGIC_1) { | |
842 Int32 r = BZ2_decompress ( s ); | |
843 if (r == BZ_STREAM_END) { | |
844 if (s->verbosity >= 3) | |
845 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%0
8x", | |
846 s->storedCombinedCRC, s->calculatedCombinedCRC ); | |
847 if (s->calculatedCombinedCRC != s->storedCombinedCRC) | |
848 return BZ_DATA_ERROR; | |
849 return r; | |
850 } | |
851 if (s->state != BZ_X_OUTPUT) return r; | |
852 } | |
853 } | |
854 | |
855 AssertH ( 0, 6001 ); | |
856 | |
857 return 0; /*NOTREACHED*/ | |
858 } | |
859 | |
860 | |
861 /*---------------------------------------------------*/ | |
862 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) | |
863 { | |
864 DState* s; | |
865 if (strm == NULL) return BZ_PARAM_ERROR; | |
866 s = strm->state; | |
867 if (s == NULL) return BZ_PARAM_ERROR; | |
868 if (s->strm != strm) return BZ_PARAM_ERROR; | |
869 | |
870 if (s->tt != NULL) BZFREE(s->tt); | |
871 if (s->ll16 != NULL) BZFREE(s->ll16); | |
872 if (s->ll4 != NULL) BZFREE(s->ll4); | |
873 | |
874 BZFREE(strm->state); | |
875 strm->state = NULL; | |
876 | |
877 return BZ_OK; | |
878 } | |
879 | |
880 | |
881 #ifndef BZ_NO_STDIO | |
882 /*---------------------------------------------------*/ | |
883 /*--- File I/O stuff ---*/ | |
884 /*---------------------------------------------------*/ | |
885 | |
886 #define BZ_SETERR(eee) \ | |
887 { \ | |
888 if (bzerror != NULL) *bzerror = eee; \ | |
889 if (bzf != NULL) bzf->lastErr = eee; \ | |
890 } | |
891 | |
892 typedef | |
893 struct { | |
894 FILE* handle; | |
895 Char buf[BZ_MAX_UNUSED]; | |
896 Int32 bufN; | |
897 Bool writing; | |
898 bz_stream strm; | |
899 Int32 lastErr; | |
900 Bool initialisedOk; | |
901 } | |
902 bzFile; | |
903 | |
904 | |
905 /*---------------------------------------------*/ | |
906 static Bool myfeof ( FILE* f ) | |
907 { | |
908 Int32 c = fgetc ( f ); | |
909 if (c == EOF) return True; | |
910 ungetc ( c, f ); | |
911 return False; | |
912 } | |
913 | |
914 | |
915 /*---------------------------------------------------*/ | |
916 BZFILE* BZ_API(BZ2_bzWriteOpen) | |
917 ( int* bzerror, | |
918 FILE* f, | |
919 int blockSize100k, | |
920 int verbosity, | |
921 int workFactor ) | |
922 { | |
923 Int32 ret; | |
924 bzFile* bzf = NULL; | |
925 | |
926 BZ_SETERR(BZ_OK); | |
927 | |
928 if (f == NULL || | |
929 (blockSize100k < 1 || blockSize100k > 9) || | |
930 (workFactor < 0 || workFactor > 250) || | |
931 (verbosity < 0 || verbosity > 4)) | |
932 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; | |
933 | |
934 if (ferror(f)) | |
935 { BZ_SETERR(BZ_IO_ERROR); return NULL; }; | |
936 | |
937 bzf = malloc ( sizeof(bzFile) ); | |
938 if (bzf == NULL) | |
939 { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; | |
940 | |
941 BZ_SETERR(BZ_OK); | |
942 bzf->initialisedOk = False; | |
943 bzf->bufN = 0; | |
944 bzf->handle = f; | |
945 bzf->writing = True; | |
946 bzf->strm.bzalloc = NULL; | |
947 bzf->strm.bzfree = NULL; | |
948 bzf->strm.opaque = NULL; | |
949 | |
950 if (workFactor == 0) workFactor = 30; | |
951 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, | |
952 verbosity, workFactor ); | |
953 if (ret != BZ_OK) | |
954 { BZ_SETERR(ret); free(bzf); return NULL; }; | |
955 | |
956 bzf->strm.avail_in = 0; | |
957 bzf->initialisedOk = True; | |
958 return bzf; | |
959 } | |
960 | |
961 | |
962 | |
963 /*---------------------------------------------------*/ | |
964 void BZ_API(BZ2_bzWrite) | |
965 ( int* bzerror, | |
966 BZFILE* b, | |
967 void* buf, | |
968 int len ) | |
969 { | |
970 Int32 n, n2, ret; | |
971 bzFile* bzf = (bzFile*)b; | |
972 | |
973 BZ_SETERR(BZ_OK); | |
974 if (bzf == NULL || buf == NULL || len < 0) | |
975 { BZ_SETERR(BZ_PARAM_ERROR); return; }; | |
976 if (!(bzf->writing)) | |
977 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
978 if (ferror(bzf->handle)) | |
979 { BZ_SETERR(BZ_IO_ERROR); return; }; | |
980 | |
981 if (len == 0) | |
982 { BZ_SETERR(BZ_OK); return; }; | |
983 | |
984 bzf->strm.avail_in = len; | |
985 bzf->strm.next_in = buf; | |
986 | |
987 while (True) { | |
988 bzf->strm.avail_out = BZ_MAX_UNUSED; | |
989 bzf->strm.next_out = bzf->buf; | |
990 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); | |
991 if (ret != BZ_RUN_OK) | |
992 { BZ_SETERR(ret); return; }; | |
993 | |
994 if (bzf->strm.avail_out < BZ_MAX_UNUSED) { | |
995 n = BZ_MAX_UNUSED - bzf->strm.avail_out; | |
996 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), | |
997 n, bzf->handle ); | |
998 if (n != n2 || ferror(bzf->handle)) | |
999 { BZ_SETERR(BZ_IO_ERROR); return; }; | |
1000 } | |
1001 | |
1002 if (bzf->strm.avail_in == 0) | |
1003 { BZ_SETERR(BZ_OK); return; }; | |
1004 } | |
1005 } | |
1006 | |
1007 | |
1008 /*---------------------------------------------------*/ | |
1009 void BZ_API(BZ2_bzWriteClose) | |
1010 ( int* bzerror, | |
1011 BZFILE* b, | |
1012 int abandon, | |
1013 unsigned int* nbytes_in, | |
1014 unsigned int* nbytes_out ) | |
1015 { | |
1016 BZ2_bzWriteClose64 ( bzerror, b, abandon, | |
1017 nbytes_in, NULL, nbytes_out, NULL ); | |
1018 } | |
1019 | |
1020 | |
1021 void BZ_API(BZ2_bzWriteClose64) | |
1022 ( int* bzerror, | |
1023 BZFILE* b, | |
1024 int abandon, | |
1025 unsigned int* nbytes_in_lo32, | |
1026 unsigned int* nbytes_in_hi32, | |
1027 unsigned int* nbytes_out_lo32, | |
1028 unsigned int* nbytes_out_hi32 ) | |
1029 { | |
1030 Int32 n, n2, ret; | |
1031 bzFile* bzf = (bzFile*)b; | |
1032 | |
1033 if (bzf == NULL) | |
1034 { BZ_SETERR(BZ_OK); return; }; | |
1035 if (!(bzf->writing)) | |
1036 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
1037 if (ferror(bzf->handle)) | |
1038 { BZ_SETERR(BZ_IO_ERROR); return; }; | |
1039 | |
1040 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; | |
1041 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; | |
1042 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; | |
1043 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; | |
1044 | |
1045 if ((!abandon) && bzf->lastErr == BZ_OK) { | |
1046 while (True) { | |
1047 bzf->strm.avail_out = BZ_MAX_UNUSED; | |
1048 bzf->strm.next_out = bzf->buf; | |
1049 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); | |
1050 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) | |
1051 { BZ_SETERR(ret); return; }; | |
1052 | |
1053 if (bzf->strm.avail_out < BZ_MAX_UNUSED) { | |
1054 n = BZ_MAX_UNUSED - bzf->strm.avail_out; | |
1055 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), | |
1056 n, bzf->handle ); | |
1057 if (n != n2 || ferror(bzf->handle)) | |
1058 { BZ_SETERR(BZ_IO_ERROR); return; }; | |
1059 } | |
1060 | |
1061 if (ret == BZ_STREAM_END) break; | |
1062 } | |
1063 } | |
1064 | |
1065 if ( !abandon && !ferror ( bzf->handle ) ) { | |
1066 fflush ( bzf->handle ); | |
1067 if (ferror(bzf->handle)) | |
1068 { BZ_SETERR(BZ_IO_ERROR); return; }; | |
1069 } | |
1070 | |
1071 if (nbytes_in_lo32 != NULL) | |
1072 *nbytes_in_lo32 = bzf->strm.total_in_lo32; | |
1073 if (nbytes_in_hi32 != NULL) | |
1074 *nbytes_in_hi32 = bzf->strm.total_in_hi32; | |
1075 if (nbytes_out_lo32 != NULL) | |
1076 *nbytes_out_lo32 = bzf->strm.total_out_lo32; | |
1077 if (nbytes_out_hi32 != NULL) | |
1078 *nbytes_out_hi32 = bzf->strm.total_out_hi32; | |
1079 | |
1080 BZ_SETERR(BZ_OK); | |
1081 BZ2_bzCompressEnd ( &(bzf->strm) ); | |
1082 free ( bzf ); | |
1083 } | |
1084 | |
1085 | |
1086 /*---------------------------------------------------*/ | |
1087 BZFILE* BZ_API(BZ2_bzReadOpen) | |
1088 ( int* bzerror, | |
1089 FILE* f, | |
1090 int verbosity, | |
1091 int small, | |
1092 void* unused, | |
1093 int nUnused ) | |
1094 { | |
1095 bzFile* bzf = NULL; | |
1096 int ret; | |
1097 | |
1098 BZ_SETERR(BZ_OK); | |
1099 | |
1100 if (f == NULL || | |
1101 (small != 0 && small != 1) || | |
1102 (verbosity < 0 || verbosity > 4) || | |
1103 (unused == NULL && nUnused != 0) || | |
1104 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) | |
1105 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; | |
1106 | |
1107 if (ferror(f)) | |
1108 { BZ_SETERR(BZ_IO_ERROR); return NULL; }; | |
1109 | |
1110 bzf = malloc ( sizeof(bzFile) ); | |
1111 if (bzf == NULL) | |
1112 { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; | |
1113 | |
1114 BZ_SETERR(BZ_OK); | |
1115 | |
1116 bzf->initialisedOk = False; | |
1117 bzf->handle = f; | |
1118 bzf->bufN = 0; | |
1119 bzf->writing = False; | |
1120 bzf->strm.bzalloc = NULL; | |
1121 bzf->strm.bzfree = NULL; | |
1122 bzf->strm.opaque = NULL; | |
1123 | |
1124 while (nUnused > 0) { | |
1125 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; | |
1126 unused = ((void*)( 1 + ((UChar*)(unused)) )); | |
1127 nUnused--; | |
1128 } | |
1129 | |
1130 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); | |
1131 if (ret != BZ_OK) | |
1132 { BZ_SETERR(ret); free(bzf); return NULL; }; | |
1133 | |
1134 bzf->strm.avail_in = bzf->bufN; | |
1135 bzf->strm.next_in = bzf->buf; | |
1136 | |
1137 bzf->initialisedOk = True; | |
1138 return bzf; | |
1139 } | |
1140 | |
1141 | |
1142 /*---------------------------------------------------*/ | |
1143 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) | |
1144 { | |
1145 bzFile* bzf = (bzFile*)b; | |
1146 | |
1147 BZ_SETERR(BZ_OK); | |
1148 if (bzf == NULL) | |
1149 { BZ_SETERR(BZ_OK); return; }; | |
1150 | |
1151 if (bzf->writing) | |
1152 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
1153 | |
1154 if (bzf->initialisedOk) | |
1155 (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); | |
1156 free ( bzf ); | |
1157 } | |
1158 | |
1159 | |
1160 /*---------------------------------------------------*/ | |
1161 int BZ_API(BZ2_bzRead) | |
1162 ( int* bzerror, | |
1163 BZFILE* b, | |
1164 void* buf, | |
1165 int len ) | |
1166 { | |
1167 Int32 n, ret; | |
1168 bzFile* bzf = (bzFile*)b; | |
1169 | |
1170 BZ_SETERR(BZ_OK); | |
1171 | |
1172 if (bzf == NULL || buf == NULL || len < 0) | |
1173 { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; | |
1174 | |
1175 if (bzf->writing) | |
1176 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; | |
1177 | |
1178 if (len == 0) | |
1179 { BZ_SETERR(BZ_OK); return 0; }; | |
1180 | |
1181 bzf->strm.avail_out = len; | |
1182 bzf->strm.next_out = buf; | |
1183 | |
1184 while (True) { | |
1185 | |
1186 if (ferror(bzf->handle)) | |
1187 { BZ_SETERR(BZ_IO_ERROR); return 0; }; | |
1188 | |
1189 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { | |
1190 n = fread ( bzf->buf, sizeof(UChar), | |
1191 BZ_MAX_UNUSED, bzf->handle ); | |
1192 if (ferror(bzf->handle)) | |
1193 { BZ_SETERR(BZ_IO_ERROR); return 0; }; | |
1194 bzf->bufN = n; | |
1195 bzf->strm.avail_in = bzf->bufN; | |
1196 bzf->strm.next_in = bzf->buf; | |
1197 } | |
1198 | |
1199 ret = BZ2_bzDecompress ( &(bzf->strm) ); | |
1200 | |
1201 if (ret != BZ_OK && ret != BZ_STREAM_END) | |
1202 { BZ_SETERR(ret); return 0; }; | |
1203 | |
1204 if (ret == BZ_OK && myfeof(bzf->handle) && | |
1205 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) | |
1206 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; | |
1207 | |
1208 if (ret == BZ_STREAM_END) | |
1209 { BZ_SETERR(BZ_STREAM_END); | |
1210 return len - bzf->strm.avail_out; }; | |
1211 if (bzf->strm.avail_out == 0) | |
1212 { BZ_SETERR(BZ_OK); return len; }; | |
1213 | |
1214 } | |
1215 | |
1216 return 0; /*not reached*/ | |
1217 } | |
1218 | |
1219 | |
1220 /*---------------------------------------------------*/ | |
1221 void BZ_API(BZ2_bzReadGetUnused) | |
1222 ( int* bzerror, | |
1223 BZFILE* b, | |
1224 void** unused, | |
1225 int* nUnused ) | |
1226 { | |
1227 bzFile* bzf = (bzFile*)b; | |
1228 if (bzf == NULL) | |
1229 { BZ_SETERR(BZ_PARAM_ERROR); return; }; | |
1230 if (bzf->lastErr != BZ_STREAM_END) | |
1231 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; | |
1232 if (unused == NULL || nUnused == NULL) | |
1233 { BZ_SETERR(BZ_PARAM_ERROR); return; }; | |
1234 | |
1235 BZ_SETERR(BZ_OK); | |
1236 *nUnused = bzf->strm.avail_in; | |
1237 *unused = bzf->strm.next_in; | |
1238 } | |
1239 #endif | |
1240 | |
1241 | |
1242 /*---------------------------------------------------*/ | |
1243 /*--- Misc convenience stuff ---*/ | |
1244 /*---------------------------------------------------*/ | |
1245 | |
1246 /*---------------------------------------------------*/ | |
1247 int BZ_API(BZ2_bzBuffToBuffCompress) | |
1248 ( char* dest, | |
1249 unsigned int* destLen, | |
1250 char* source, | |
1251 unsigned int sourceLen, | |
1252 int blockSize100k, | |
1253 int verbosity, | |
1254 int workFactor ) | |
1255 { | |
1256 bz_stream strm; | |
1257 int ret; | |
1258 | |
1259 if (dest == NULL || destLen == NULL || | |
1260 source == NULL || | |
1261 blockSize100k < 1 || blockSize100k > 9 || | |
1262 verbosity < 0 || verbosity > 4 || | |
1263 workFactor < 0 || workFactor > 250) | |
1264 return BZ_PARAM_ERROR; | |
1265 | |
1266 if (workFactor == 0) workFactor = 30; | |
1267 strm.bzalloc = NULL; | |
1268 strm.bzfree = NULL; | |
1269 strm.opaque = NULL; | |
1270 ret = BZ2_bzCompressInit ( &strm, blockSize100k, | |
1271 verbosity, workFactor ); | |
1272 if (ret != BZ_OK) return ret; | |
1273 | |
1274 strm.next_in = source; | |
1275 strm.next_out = dest; | |
1276 strm.avail_in = sourceLen; | |
1277 strm.avail_out = *destLen; | |
1278 | |
1279 ret = BZ2_bzCompress ( &strm, BZ_FINISH ); | |
1280 if (ret == BZ_FINISH_OK) goto output_overflow; | |
1281 if (ret != BZ_STREAM_END) goto errhandler; | |
1282 | |
1283 /* normal termination */ | |
1284 *destLen -= strm.avail_out; | |
1285 BZ2_bzCompressEnd ( &strm ); | |
1286 return BZ_OK; | |
1287 | |
1288 output_overflow: | |
1289 BZ2_bzCompressEnd ( &strm ); | |
1290 return BZ_OUTBUFF_FULL; | |
1291 | |
1292 errhandler: | |
1293 BZ2_bzCompressEnd ( &strm ); | |
1294 return ret; | |
1295 } | |
1296 | |
1297 | |
1298 /*---------------------------------------------------*/ | |
1299 int BZ_API(BZ2_bzBuffToBuffDecompress) | |
1300 ( char* dest, | |
1301 unsigned int* destLen, | |
1302 char* source, | |
1303 unsigned int sourceLen, | |
1304 int small, | |
1305 int verbosity ) | |
1306 { | |
1307 bz_stream strm; | |
1308 int ret; | |
1309 | |
1310 if (dest == NULL || destLen == NULL || | |
1311 source == NULL || | |
1312 (small != 0 && small != 1) || | |
1313 verbosity < 0 || verbosity > 4) | |
1314 return BZ_PARAM_ERROR; | |
1315 | |
1316 strm.bzalloc = NULL; | |
1317 strm.bzfree = NULL; | |
1318 strm.opaque = NULL; | |
1319 ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); | |
1320 if (ret != BZ_OK) return ret; | |
1321 | |
1322 strm.next_in = source; | |
1323 strm.next_out = dest; | |
1324 strm.avail_in = sourceLen; | |
1325 strm.avail_out = *destLen; | |
1326 | |
1327 ret = BZ2_bzDecompress ( &strm ); | |
1328 if (ret == BZ_OK) goto output_overflow_or_eof; | |
1329 if (ret != BZ_STREAM_END) goto errhandler; | |
1330 | |
1331 /* normal termination */ | |
1332 *destLen -= strm.avail_out; | |
1333 BZ2_bzDecompressEnd ( &strm ); | |
1334 return BZ_OK; | |
1335 | |
1336 output_overflow_or_eof: | |
1337 if (strm.avail_out > 0) { | |
1338 BZ2_bzDecompressEnd ( &strm ); | |
1339 return BZ_UNEXPECTED_EOF; | |
1340 } else { | |
1341 BZ2_bzDecompressEnd ( &strm ); | |
1342 return BZ_OUTBUFF_FULL; | |
1343 }; | |
1344 | |
1345 errhandler: | |
1346 BZ2_bzDecompressEnd ( &strm ); | |
1347 return ret; | |
1348 } | |
1349 | |
1350 | |
1351 /*---------------------------------------------------*/ | |
1352 /*-- | |
1353 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) | |
1354 to support better zlib compatibility. | |
1355 This code is not _officially_ part of libbzip2 (yet); | |
1356 I haven't tested it, documented it, or considered the | |
1357 threading-safeness of it. | |
1358 If this code breaks, please contact both Yoshioka and me. | |
1359 --*/ | |
1360 /*---------------------------------------------------*/ | |
1361 | |
1362 /*---------------------------------------------------*/ | |
1363 /*-- | |
1364 return version like "0.9.5d, 4-Sept-1999". | |
1365 --*/ | |
1366 const char * BZ_API(BZ2_bzlibVersion)(void) | |
1367 { | |
1368 return BZ_VERSION; | |
1369 } | |
1370 | |
1371 | |
1372 #ifndef BZ_NO_STDIO | |
1373 /*---------------------------------------------------*/ | |
1374 | |
1375 #if defined(_WIN32) || defined(OS2) || defined(MSDOS) | |
1376 # include <fcntl.h> | |
1377 # include <io.h> | |
1378 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) | |
1379 #else | |
1380 # define SET_BINARY_MODE(file) | |
1381 #endif | |
1382 static | |
1383 BZFILE * bzopen_or_bzdopen | |
1384 ( const char *path, /* no use when bzdopen */ | |
1385 int fd, /* no use when bzdopen */ | |
1386 const char *mode, | |
1387 int open_mode) /* bzopen: 0, bzdopen:1 */ | |
1388 { | |
1389 int bzerr; | |
1390 char unused[BZ_MAX_UNUSED]; | |
1391 int blockSize100k = 9; | |
1392 int writing = 0; | |
1393 char mode2[10] = ""; | |
1394 FILE *fp = NULL; | |
1395 BZFILE *bzfp = NULL; | |
1396 int verbosity = 0; | |
1397 int workFactor = 30; | |
1398 int smallMode = 0; | |
1399 int nUnused = 0; | |
1400 | |
1401 if (mode == NULL) return NULL; | |
1402 while (*mode) { | |
1403 switch (*mode) { | |
1404 case 'r': | |
1405 writing = 0; break; | |
1406 case 'w': | |
1407 writing = 1; break; | |
1408 case 's': | |
1409 smallMode = 1; break; | |
1410 default: | |
1411 if (isdigit((int)(*mode))) { | |
1412 blockSize100k = *mode-BZ_HDR_0; | |
1413 } | |
1414 } | |
1415 mode++; | |
1416 } | |
1417 strcat(mode2, writing ? "w" : "r" ); | |
1418 strcat(mode2,"b"); /* binary mode */ | |
1419 | |
1420 if (open_mode==0) { | |
1421 if (path==NULL || strcmp(path,"")==0) { | |
1422 fp = (writing ? stdout : stdin); | |
1423 SET_BINARY_MODE(fp); | |
1424 } else { | |
1425 fp = fopen(path,mode2); | |
1426 } | |
1427 } else { | |
1428 #ifdef BZ_STRICT_ANSI | |
1429 fp = NULL; | |
1430 #else | |
1431 fp = fdopen(fd,mode2); | |
1432 #endif | |
1433 } | |
1434 if (fp == NULL) return NULL; | |
1435 | |
1436 if (writing) { | |
1437 /* Guard against total chaos and anarchy -- JRS */ | |
1438 if (blockSize100k < 1) blockSize100k = 1; | |
1439 if (blockSize100k > 9) blockSize100k = 9; | |
1440 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, | |
1441 verbosity,workFactor); | |
1442 } else { | |
1443 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, | |
1444 unused,nUnused); | |
1445 } | |
1446 if (bzfp == NULL) { | |
1447 if (fp != stdin && fp != stdout) fclose(fp); | |
1448 return NULL; | |
1449 } | |
1450 return bzfp; | |
1451 } | |
1452 | |
1453 | |
1454 /*---------------------------------------------------*/ | |
1455 /*-- | |
1456 open file for read or write. | |
1457 ex) bzopen("file","w9") | |
1458 case path="" or NULL => use stdin or stdout. | |
1459 --*/ | |
1460 BZFILE * BZ_API(BZ2_bzopen) | |
1461 ( const char *path, | |
1462 const char *mode ) | |
1463 { | |
1464 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); | |
1465 } | |
1466 | |
1467 | |
1468 /*---------------------------------------------------*/ | |
1469 BZFILE * BZ_API(BZ2_bzdopen) | |
1470 ( int fd, | |
1471 const char *mode ) | |
1472 { | |
1473 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); | |
1474 } | |
1475 | |
1476 | |
1477 /*---------------------------------------------------*/ | |
1478 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) | |
1479 { | |
1480 int bzerr, nread; | |
1481 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; | |
1482 nread = BZ2_bzRead(&bzerr,b,buf,len); | |
1483 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { | |
1484 return nread; | |
1485 } else { | |
1486 return -1; | |
1487 } | |
1488 } | |
1489 | |
1490 | |
1491 /*---------------------------------------------------*/ | |
1492 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) | |
1493 { | |
1494 int bzerr; | |
1495 | |
1496 BZ2_bzWrite(&bzerr,b,buf,len); | |
1497 if(bzerr == BZ_OK){ | |
1498 return len; | |
1499 }else{ | |
1500 return -1; | |
1501 } | |
1502 } | |
1503 | |
1504 | |
1505 /*---------------------------------------------------*/ | |
1506 int BZ_API(BZ2_bzflush) (BZFILE *b) | |
1507 { | |
1508 /* do nothing now... */ | |
1509 return 0; | |
1510 } | |
1511 | |
1512 | |
1513 /*---------------------------------------------------*/ | |
1514 void BZ_API(BZ2_bzclose) (BZFILE* b) | |
1515 { | |
1516 int bzerr; | |
1517 FILE *fp; | |
1518 | |
1519 if (b==NULL) {return;} | |
1520 fp = ((bzFile *)b)->handle; | |
1521 if(((bzFile*)b)->writing){ | |
1522 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); | |
1523 if(bzerr != BZ_OK){ | |
1524 BZ2_bzWriteClose(NULL,b,1,NULL,NULL); | |
1525 } | |
1526 }else{ | |
1527 BZ2_bzReadClose(&bzerr,b); | |
1528 } | |
1529 if(fp!=stdin && fp!=stdout){ | |
1530 fclose(fp); | |
1531 } | |
1532 } | |
1533 | |
1534 | |
1535 /*---------------------------------------------------*/ | |
1536 /*-- | |
1537 return last error code | |
1538 --*/ | |
1539 static const char *bzerrorstrings[] = { | |
1540 "OK" | |
1541 ,"SEQUENCE_ERROR" | |
1542 ,"PARAM_ERROR" | |
1543 ,"MEM_ERROR" | |
1544 ,"DATA_ERROR" | |
1545 ,"DATA_ERROR_MAGIC" | |
1546 ,"IO_ERROR" | |
1547 ,"UNEXPECTED_EOF" | |
1548 ,"OUTBUFF_FULL" | |
1549 ,"CONFIG_ERROR" | |
1550 ,"???" /* for future */ | |
1551 ,"???" /* for future */ | |
1552 ,"???" /* for future */ | |
1553 ,"???" /* for future */ | |
1554 ,"???" /* for future */ | |
1555 ,"???" /* for future */ | |
1556 }; | |
1557 | |
1558 | |
1559 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) | |
1560 { | |
1561 int err = ((bzFile *)b)->lastErr; | |
1562 | |
1563 if(err>0) err = 0; | |
1564 *errnum = err; | |
1565 return bzerrorstrings[err*-1]; | |
1566 } | |
1567 #endif | |
1568 | |
1569 | |
1570 /*-------------------------------------------------------------*/ | |
1571 /*--- end bzlib.c ---*/ | |
1572 /*-------------------------------------------------------------*/ | |
OLD | NEW |