2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
5 /*-------------------------------------------------------------*/
7 /* ------------------------------------------------------------------
8 This file is part of bzip2/libbzip2, a program and library for
9 lossless, block-sorting data compression.
11 bzip2/libbzip2 version 1.0.4 of 20 December 2006
12 Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
14 Please read the WARNING, DISCLAIMER and PATENTS sections in the
17 This program is released under the terms of the license contained
19 ------------------------------------------------------------------ */
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include "bzlib_private.h"
36 #ifndef BZ_NO_COMPRESS
38 /*---------------------------------------------------*/
39 /*--- Compression stuff ---*/
40 /*---------------------------------------------------*/
43 /*---------------------------------------------------*/
45 void BZ2_bz__AssertH__fail ( int errcode )
48 "\n\nbzip2/libbzip2: internal error number %d.\n"
49 "This is a bug in bzip2/libbzip2, %s.\n"
50 "Please report it to me at: jseward@bzip.org. If this happened\n"
51 "when you were using some program which uses libbzip2 as a\n"
52 "component, you should also report this bug to the author(s)\n"
53 "of that program. Please make an effort to report this bug;\n"
54 "timely and accurate bug reports eventually lead to higher\n"
55 "quality software. Thanks. Julian Seward, 15 February 2005.\n\n",
60 if (errcode == 1007) {
62 "\n*** A special note about internal error number 1007 ***\n"
64 "Experience suggests that a common cause of i.e. 1007\n"
65 "is unreliable memory or other hardware. The 1007 assertion\n"
66 "just happens to cross-check the results of huge numbers of\n"
67 "memory reads/writes, and so acts (unintendedly) as a stress\n"
68 "test of your memory system.\n"
70 "I suggest the following: try compressing the file again,\n"
71 "possibly monitoring progress in detail with the -vv flag.\n"
73 "* If the error cannot be reproduced, and/or happens at different\n"
74 " points in compression, you may have a flaky memory system.\n"
75 " Try a memory-test program. I have used Memtest86\n"
76 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
77 " Memtest86 tests memory much more thorougly than your BIOSs\n"
78 " power-on test, and may find failures that the BIOS doesn't.\n"
80 "* If the error can be repeatably reproduced, this is a bug in\n"
81 " bzip2, and I would very much like to hear about it. Please\n"
82 " let me know, and, ideally, save a copy of the file causing the\n"
83 " problem -- without which I will be unable to investigate it.\n"
92 #endif /* BZ_NO_COMPRESS */
94 /*---------------------------------------------------*/
96 int bz_config_ok ( void )
98 if (sizeof(int) != 4) return 0;
99 if (sizeof(short) != 2) return 0;
100 if (sizeof(char) != 1) return 0;
105 /*---------------------------------------------------*/
107 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
109 void* v = malloc ( items * size );
114 void default_bzfree ( void* opaque, void* addr )
116 if (addr != NULL) free ( addr );
119 #ifndef BZ_NO_COMPRESS
121 /*---------------------------------------------------*/
123 void prepare_new_block ( EState* s )
128 s->state_out_pos = 0;
129 BZ_INITIALISE_CRC ( s->blockCRC );
130 for (i = 0; i < 256; i++) s->inUse[i] = False;
135 /*---------------------------------------------------*/
137 void init_RL ( EState* s )
139 s->state_in_ch = 256;
145 Bool isempty_RL ( EState* s )
147 if (s->state_in_ch < 256 && s->state_in_len > 0)
153 /*---------------------------------------------------*/
154 int BZ_API(BZ2_bzCompressInit)
163 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
166 blockSize100k < 1 || blockSize100k > 9 ||
167 workFactor < 0 || workFactor > 250)
168 return BZ_PARAM_ERROR;
170 if (workFactor == 0) workFactor = 30;
171 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
172 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
174 s = BZALLOC( sizeof(EState) );
175 if (s == NULL) return BZ_MEM_ERROR;
182 n = 100000 * blockSize100k;
183 s->arr1 = BZALLOC( n * sizeof(UInt32) );
184 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
185 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
187 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
188 if (s->arr1 != NULL) BZFREE(s->arr1);
189 if (s->arr2 != NULL) BZFREE(s->arr2);
190 if (s->ftab != NULL) BZFREE(s->ftab);
191 if (s != NULL) BZFREE(s);
196 s->state = BZ_S_INPUT;
197 s->mode = BZ_M_RUNNING;
199 s->blockSize100k = blockSize100k;
200 s->nblockMAX = 100000 * blockSize100k - 19;
201 s->verbosity = verbosity;
202 s->workFactor = workFactor;
204 s->block = (UChar*)s->arr2;
205 s->mtfv = (UInt16*)s->arr1;
207 s->ptr = (UInt32*)s->arr1;
210 strm->total_in_lo32 = 0;
211 strm->total_in_hi32 = 0;
212 strm->total_out_lo32 = 0;
213 strm->total_out_hi32 = 0;
215 prepare_new_block ( s );
220 /*---------------------------------------------------*/
222 void add_pair_to_block ( EState* s )
225 UChar ch = (UChar)(s->state_in_ch);
226 for (i = 0; i < s->state_in_len; i++) {
227 BZ_UPDATE_CRC( s->blockCRC, ch );
229 s->inUse[s->state_in_ch] = True;
230 switch (s->state_in_len) {
232 s->block[s->nblock] = (UChar)ch; s->nblock++;
235 s->block[s->nblock] = (UChar)ch; s->nblock++;
236 s->block[s->nblock] = (UChar)ch; s->nblock++;
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++;
244 s->inUse[s->state_in_len-4] = True;
245 s->block[s->nblock] = (UChar)ch; s->nblock++;
246 s->block[s->nblock] = (UChar)ch; s->nblock++;
247 s->block[s->nblock] = (UChar)ch; s->nblock++;
248 s->block[s->nblock] = (UChar)ch; s->nblock++;
249 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
256 /*---------------------------------------------------*/
258 void flush_RL ( EState* s )
260 if (s->state_in_ch < 256) add_pair_to_block ( s );
265 /*---------------------------------------------------*/
266 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
268 UInt32 zchh = (UInt32)(zchh0); \
269 /*-- fast track the common case --*/ \
270 if (zchh != zs->state_in_ch && \
271 zs->state_in_len == 1) { \
272 UChar ch = (UChar)(zs->state_in_ch); \
273 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
274 zs->inUse[zs->state_in_ch] = True; \
275 zs->block[zs->nblock] = (UChar)ch; \
277 zs->state_in_ch = zchh; \
280 /*-- general, uncommon cases --*/ \
281 if (zchh != zs->state_in_ch || \
282 zs->state_in_len == 255) { \
283 if (zs->state_in_ch < 256) \
284 add_pair_to_block ( zs ); \
285 zs->state_in_ch = zchh; \
286 zs->state_in_len = 1; \
288 zs->state_in_len++; \
293 /*---------------------------------------------------*/
295 Bool copy_input_until_stop ( EState* s )
297 Bool progress_in = False;
299 if (s->mode == BZ_M_RUNNING) {
301 /*-- fast track the common case --*/
303 /*-- block full? --*/
304 if (s->nblock >= s->nblockMAX) break;
306 if (s->strm->avail_in == 0) break;
308 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
311 s->strm->total_in_lo32++;
312 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
317 /*-- general, uncommon case --*/
319 /*-- block full? --*/
320 if (s->nblock >= s->nblockMAX) break;
322 if (s->strm->avail_in == 0) break;
323 /*-- flush/finish end? --*/
324 if (s->avail_in_expect == 0) break;
326 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
329 s->strm->total_in_lo32++;
330 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
331 s->avail_in_expect--;
338 /*---------------------------------------------------*/
340 Bool copy_output_until_stop ( EState* s )
342 Bool progress_out = False;
346 /*-- no output space? --*/
347 if (s->strm->avail_out == 0) break;
349 /*-- block done? --*/
350 if (s->state_out_pos >= s->numZ) break;
353 *(s->strm->next_out) = s->zbits[s->state_out_pos];
355 s->strm->avail_out--;
357 s->strm->total_out_lo32++;
358 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
365 /*---------------------------------------------------*/
367 Bool handle_compress ( bz_stream* strm )
369 Bool progress_in = False;
370 Bool progress_out = False;
371 EState* s = strm->state;
375 if (s->state == BZ_S_OUTPUT) {
376 progress_out |= copy_output_until_stop ( s );
377 if (s->state_out_pos < s->numZ) break;
378 if (s->mode == BZ_M_FINISHING &&
379 s->avail_in_expect == 0 &&
380 isempty_RL(s)) break;
381 prepare_new_block ( s );
382 s->state = BZ_S_INPUT;
383 if (s->mode == BZ_M_FLUSHING &&
384 s->avail_in_expect == 0 &&
385 isempty_RL(s)) break;
388 if (s->state == BZ_S_INPUT) {
389 progress_in |= copy_input_until_stop ( s );
390 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
392 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
393 s->state = BZ_S_OUTPUT;
396 if (s->nblock >= s->nblockMAX) {
397 BZ2_compressBlock ( s, False );
398 s->state = BZ_S_OUTPUT;
401 if (s->strm->avail_in == 0) {
408 return progress_in || progress_out;
412 /*---------------------------------------------------*/
413 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
417 if (strm == NULL) return BZ_PARAM_ERROR;
419 if (s == NULL) return BZ_PARAM_ERROR;
420 if (s->strm != strm) return BZ_PARAM_ERROR;
426 return BZ_SEQUENCE_ERROR;
429 if (action == BZ_RUN) {
430 progress = handle_compress ( strm );
431 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
434 if (action == BZ_FLUSH) {
435 s->avail_in_expect = strm->avail_in;
436 s->mode = BZ_M_FLUSHING;
440 if (action == BZ_FINISH) {
441 s->avail_in_expect = strm->avail_in;
442 s->mode = BZ_M_FINISHING;
446 return BZ_PARAM_ERROR;
449 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
450 if (s->avail_in_expect != s->strm->avail_in)
451 return BZ_SEQUENCE_ERROR;
452 progress = handle_compress ( strm );
453 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
454 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
455 s->mode = BZ_M_RUNNING;
459 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
460 if (s->avail_in_expect != s->strm->avail_in)
461 return BZ_SEQUENCE_ERROR;
462 progress = handle_compress ( strm );
463 if (!progress) return BZ_SEQUENCE_ERROR;
464 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
465 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
467 return BZ_STREAM_END;
469 return BZ_OK; /*--not reached--*/
473 /*---------------------------------------------------*/
474 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
477 if (strm == NULL) return BZ_PARAM_ERROR;
479 if (s == NULL) return BZ_PARAM_ERROR;
480 if (s->strm != strm) return BZ_PARAM_ERROR;
482 if (s->arr1 != NULL) BZFREE(s->arr1);
483 if (s->arr2 != NULL) BZFREE(s->arr2);
484 if (s->ftab != NULL) BZFREE(s->ftab);
492 #endif /* BZ_NO_COMPRESS */
494 /*---------------------------------------------------*/
495 /*--- Decompression stuff ---*/
496 /*---------------------------------------------------*/
498 /*---------------------------------------------------*/
499 int BZ_API(BZ2_bzDecompressInit)
506 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
508 if (strm == NULL) return BZ_PARAM_ERROR;
509 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
510 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
512 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
513 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
515 s = BZALLOC( sizeof(DState) );
516 if (s == NULL) return BZ_MEM_ERROR;
519 s->state = BZ_X_MAGIC_1;
522 s->calculatedCombinedCRC = 0;
523 strm->total_in_lo32 = 0;
524 strm->total_in_hi32 = 0;
525 strm->total_out_lo32 = 0;
526 strm->total_out_hi32 = 0;
527 s->smallDecompress = (Bool)small;
532 s->verbosity = verbosity;
538 /*---------------------------------------------------*/
539 /* Return True iff data corruption is discovered.
540 Returns False if there is no problem.
543 Bool unRLE_obuf_to_output_FAST ( DState* s )
547 if (s->blockRandomised) {
550 /* try to finish existing run */
552 if (s->strm->avail_out == 0) return False;
553 if (s->state_out_len == 0) break;
554 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
555 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
558 s->strm->avail_out--;
559 s->strm->total_out_lo32++;
560 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
563 /* can a new run be started? */
564 if (s->nblock_used == s->save_nblock+1) return False;
566 /* Only caused by corrupt data stream? */
567 if (s->nblock_used > s->save_nblock+1)
570 s->state_out_len = 1;
571 s->state_out_ch = s->k0;
572 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
573 k1 ^= BZ_RAND_MASK; s->nblock_used++;
574 if (s->nblock_used == s->save_nblock+1) continue;
575 if (k1 != s->k0) { s->k0 = k1; continue; };
577 s->state_out_len = 2;
578 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
579 k1 ^= BZ_RAND_MASK; s->nblock_used++;
580 if (s->nblock_used == s->save_nblock+1) continue;
581 if (k1 != s->k0) { s->k0 = k1; continue; };
583 s->state_out_len = 3;
584 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
585 k1 ^= BZ_RAND_MASK; s->nblock_used++;
586 if (s->nblock_used == s->save_nblock+1) continue;
587 if (k1 != s->k0) { s->k0 = k1; continue; };
589 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
590 k1 ^= BZ_RAND_MASK; s->nblock_used++;
591 s->state_out_len = ((Int32)k1) + 4;
592 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
593 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
599 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
600 UChar c_state_out_ch = s->state_out_ch;
601 Int32 c_state_out_len = s->state_out_len;
602 Int32 c_nblock_used = s->nblock_used;
604 UInt32* c_tt = s->tt;
605 UInt32 c_tPos = s->tPos;
606 char* cs_next_out = s->strm->next_out;
607 unsigned int cs_avail_out = s->strm->avail_out;
610 UInt32 avail_out_INIT = cs_avail_out;
611 Int32 s_save_nblockPP = s->save_nblock+1;
612 unsigned int total_out_lo32_old;
616 /* try to finish existing run */
617 if (c_state_out_len > 0) {
619 if (cs_avail_out == 0) goto return_notr;
620 if (c_state_out_len == 1) break;
621 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
622 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
627 s_state_out_len_eq_one:
629 if (cs_avail_out == 0) {
630 c_state_out_len = 1; goto return_notr;
632 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
633 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
638 /* Only caused by corrupt data stream? */
639 if (c_nblock_used > s_save_nblockPP)
642 /* can a new run be started? */
643 if (c_nblock_used == s_save_nblockPP) {
644 c_state_out_len = 0; goto return_notr;
646 c_state_out_ch = c_k0;
647 BZ_GET_FAST_C(k1); c_nblock_used++;
649 c_k0 = k1; goto s_state_out_len_eq_one;
651 if (c_nblock_used == s_save_nblockPP)
652 goto s_state_out_len_eq_one;
655 BZ_GET_FAST_C(k1); c_nblock_used++;
656 if (c_nblock_used == s_save_nblockPP) continue;
657 if (k1 != c_k0) { c_k0 = k1; continue; };
660 BZ_GET_FAST_C(k1); c_nblock_used++;
661 if (c_nblock_used == s_save_nblockPP) continue;
662 if (k1 != c_k0) { c_k0 = k1; continue; };
664 BZ_GET_FAST_C(k1); c_nblock_used++;
665 c_state_out_len = ((Int32)k1) + 4;
666 BZ_GET_FAST_C(c_k0); c_nblock_used++;
670 total_out_lo32_old = s->strm->total_out_lo32;
671 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
672 if (s->strm->total_out_lo32 < total_out_lo32_old)
673 s->strm->total_out_hi32++;
676 s->calculatedBlockCRC = c_calculatedBlockCRC;
677 s->state_out_ch = c_state_out_ch;
678 s->state_out_len = c_state_out_len;
679 s->nblock_used = c_nblock_used;
683 s->strm->next_out = cs_next_out;
684 s->strm->avail_out = cs_avail_out;
692 /*---------------------------------------------------*/
693 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
699 mid = (nb + na) >> 1;
700 if (indx >= cftab[mid]) nb = mid; else na = mid;
702 while (na - nb != 1);
707 /*---------------------------------------------------*/
708 /* Return True iff data corruption is discovered.
709 Returns False if there is no problem.
712 Bool unRLE_obuf_to_output_SMALL ( DState* s )
716 if (s->blockRandomised) {
719 /* try to finish existing run */
721 if (s->strm->avail_out == 0) return False;
722 if (s->state_out_len == 0) break;
723 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
724 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
727 s->strm->avail_out--;
728 s->strm->total_out_lo32++;
729 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
732 /* can a new run be started? */
733 if (s->nblock_used == s->save_nblock+1) return False;
735 /* Only caused by corrupt data stream? */
736 if (s->nblock_used > s->save_nblock+1)
739 s->state_out_len = 1;
740 s->state_out_ch = s->k0;
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; };
746 s->state_out_len = 2;
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; };
752 s->state_out_len = 3;
753 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
754 k1 ^= BZ_RAND_MASK; s->nblock_used++;
755 if (s->nblock_used == s->save_nblock+1) continue;
756 if (k1 != s->k0) { s->k0 = k1; continue; };
758 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
759 k1 ^= BZ_RAND_MASK; s->nblock_used++;
760 s->state_out_len = ((Int32)k1) + 4;
761 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
762 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
768 /* try to finish existing run */
770 if (s->strm->avail_out == 0) return False;
771 if (s->state_out_len == 0) break;
772 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
773 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
776 s->strm->avail_out--;
777 s->strm->total_out_lo32++;
778 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
781 /* can a new run be started? */
782 if (s->nblock_used == s->save_nblock+1) return False;
784 /* Only caused by corrupt data stream? */
785 if (s->nblock_used > s->save_nblock+1)
788 s->state_out_len = 1;
789 s->state_out_ch = s->k0;
790 BZ_GET_SMALL(k1); s->nblock_used++;
791 if (s->nblock_used == s->save_nblock+1) continue;
792 if (k1 != s->k0) { s->k0 = k1; continue; };
794 s->state_out_len = 2;
795 BZ_GET_SMALL(k1); s->nblock_used++;
796 if (s->nblock_used == s->save_nblock+1) continue;
797 if (k1 != s->k0) { s->k0 = k1; continue; };
799 s->state_out_len = 3;
800 BZ_GET_SMALL(k1); s->nblock_used++;
801 if (s->nblock_used == s->save_nblock+1) continue;
802 if (k1 != s->k0) { s->k0 = k1; continue; };
804 BZ_GET_SMALL(k1); s->nblock_used++;
805 s->state_out_len = ((Int32)k1) + 4;
806 BZ_GET_SMALL(s->k0); s->nblock_used++;
813 /*---------------------------------------------------*/
814 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
818 if (strm == NULL) return BZ_PARAM_ERROR;
820 if (s == NULL) return BZ_PARAM_ERROR;
821 if (s->strm != strm) return BZ_PARAM_ERROR;
824 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
825 if (s->state == BZ_X_OUTPUT) {
826 if (s->smallDecompress)
827 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
828 corrupt = unRLE_obuf_to_output_FAST ( s );
829 if (corrupt) return BZ_DATA_ERROR;
830 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
831 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
832 if (s->verbosity >= 3)
833 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
834 s->calculatedBlockCRC );
835 if (s->verbosity >= 2) VPrintf0 ( "]" );
836 if (s->calculatedBlockCRC != s->storedBlockCRC)
837 return BZ_DATA_ERROR;
838 s->calculatedCombinedCRC
839 = (s->calculatedCombinedCRC << 1) |
840 (s->calculatedCombinedCRC >> 31);
841 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
842 s->state = BZ_X_BLKHDR_1;
847 if (s->state >= BZ_X_MAGIC_1) {
848 Int32 r = BZ2_decompress ( s );
849 if (r == BZ_STREAM_END) {
850 if (s->verbosity >= 3)
851 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
852 s->storedCombinedCRC, s->calculatedCombinedCRC );
853 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
854 return BZ_DATA_ERROR;
857 if (s->state != BZ_X_OUTPUT) return r;
863 return 0; /*NOTREACHED*/
867 /*---------------------------------------------------*/
868 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
871 if (strm == NULL) return BZ_PARAM_ERROR;
873 if (s == NULL) return BZ_PARAM_ERROR;
874 if (s->strm != strm) return BZ_PARAM_ERROR;
876 if (s->tt != NULL) BZFREE(s->tt);
877 if (s->ll16 != NULL) BZFREE(s->ll16);
878 if (s->ll4 != NULL) BZFREE(s->ll4);
886 #ifndef BZ_NO_COMPRESS
889 /*---------------------------------------------------*/
890 /*--- File I/O stuff ---*/
891 /*---------------------------------------------------*/
893 #define BZ_SETERR(eee) \
895 if (bzerror != NULL) *bzerror = eee; \
896 if (bzf != NULL) bzf->lastErr = eee; \
902 Char buf[BZ_MAX_UNUSED];
912 /*---------------------------------------------*/
913 static Bool myfeof ( FILE* f )
915 Int32 c = fgetc ( f );
916 if (c == EOF) return True;
922 /*---------------------------------------------------*/
923 BZFILE* BZ_API(BZ2_bzWriteOpen)
936 (blockSize100k < 1 || blockSize100k > 9) ||
937 (workFactor < 0 || workFactor > 250) ||
938 (verbosity < 0 || verbosity > 4))
939 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
942 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
944 bzf = malloc ( sizeof(bzFile) );
946 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
949 bzf->initialisedOk = False;
953 bzf->strm.bzalloc = NULL;
954 bzf->strm.bzfree = NULL;
955 bzf->strm.opaque = NULL;
957 if (workFactor == 0) workFactor = 30;
958 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
959 verbosity, workFactor );
961 { BZ_SETERR(ret); free(bzf); return NULL; };
963 bzf->strm.avail_in = 0;
964 bzf->initialisedOk = True;
970 /*---------------------------------------------------*/
971 void BZ_API(BZ2_bzWrite)
978 bzFile* bzf = (bzFile*)b;
981 if (bzf == NULL || buf == NULL || len < 0)
982 { BZ_SETERR(BZ_PARAM_ERROR); return; };
984 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
985 if (ferror(bzf->handle))
986 { BZ_SETERR(BZ_IO_ERROR); return; };
989 { BZ_SETERR(BZ_OK); return; };
991 bzf->strm.avail_in = len;
992 bzf->strm.next_in = buf;
995 bzf->strm.avail_out = BZ_MAX_UNUSED;
996 bzf->strm.next_out = bzf->buf;
997 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
998 if (ret != BZ_RUN_OK)
999 { BZ_SETERR(ret); return; };
1001 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1002 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1003 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1005 if (n != n2 || ferror(bzf->handle))
1006 { BZ_SETERR(BZ_IO_ERROR); return; };
1009 if (bzf->strm.avail_in == 0)
1010 { BZ_SETERR(BZ_OK); return; };
1015 /*---------------------------------------------------*/
1016 void BZ_API(BZ2_bzWriteClose)
1020 unsigned int* nbytes_in,
1021 unsigned int* nbytes_out )
1023 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1024 nbytes_in, NULL, nbytes_out, NULL );
1028 void BZ_API(BZ2_bzWriteClose64)
1032 unsigned int* nbytes_in_lo32,
1033 unsigned int* nbytes_in_hi32,
1034 unsigned int* nbytes_out_lo32,
1035 unsigned int* nbytes_out_hi32 )
1038 bzFile* bzf = (bzFile*)b;
1041 { BZ_SETERR(BZ_OK); return; };
1042 if (!(bzf->writing))
1043 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1044 if (ferror(bzf->handle))
1045 { BZ_SETERR(BZ_IO_ERROR); return; };
1047 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1048 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1049 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1050 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1052 if ((!abandon) && bzf->lastErr == BZ_OK) {
1054 bzf->strm.avail_out = BZ_MAX_UNUSED;
1055 bzf->strm.next_out = bzf->buf;
1056 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1057 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1058 { BZ_SETERR(ret); return; };
1060 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1061 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1062 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1064 if (n != n2 || ferror(bzf->handle))
1065 { BZ_SETERR(BZ_IO_ERROR); return; };
1068 if (ret == BZ_STREAM_END) break;
1072 if ( !abandon && !ferror ( bzf->handle ) ) {
1073 fflush ( bzf->handle );
1074 if (ferror(bzf->handle))
1075 { BZ_SETERR(BZ_IO_ERROR); return; };
1078 if (nbytes_in_lo32 != NULL)
1079 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1080 if (nbytes_in_hi32 != NULL)
1081 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1082 if (nbytes_out_lo32 != NULL)
1083 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1084 if (nbytes_out_hi32 != NULL)
1085 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1088 BZ2_bzCompressEnd ( &(bzf->strm) );
1093 /*---------------------------------------------------*/
1094 BZFILE* BZ_API(BZ2_bzReadOpen)
1108 (small != 0 && small != 1) ||
1109 (verbosity < 0 || verbosity > 4) ||
1110 (unused == NULL && nUnused != 0) ||
1111 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1112 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1115 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1117 bzf = malloc ( sizeof(bzFile) );
1119 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1123 bzf->initialisedOk = False;
1126 bzf->writing = False;
1127 bzf->strm.bzalloc = NULL;
1128 bzf->strm.bzfree = NULL;
1129 bzf->strm.opaque = NULL;
1131 while (nUnused > 0) {
1132 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1133 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1137 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1139 { BZ_SETERR(ret); free(bzf); return NULL; };
1141 bzf->strm.avail_in = bzf->bufN;
1142 bzf->strm.next_in = bzf->buf;
1144 bzf->initialisedOk = True;
1149 /*---------------------------------------------------*/
1150 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1152 bzFile* bzf = (bzFile*)b;
1156 { BZ_SETERR(BZ_OK); return; };
1159 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1161 if (bzf->initialisedOk)
1162 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1167 /*---------------------------------------------------*/
1168 int BZ_API(BZ2_bzRead)
1175 bzFile* bzf = (bzFile*)b;
1179 if (bzf == NULL || buf == NULL || len < 0)
1180 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1183 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1186 { BZ_SETERR(BZ_OK); return 0; };
1188 bzf->strm.avail_out = len;
1189 bzf->strm.next_out = buf;
1193 if (ferror(bzf->handle))
1194 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1196 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1197 n = fread ( bzf->buf, sizeof(UChar),
1198 BZ_MAX_UNUSED, bzf->handle );
1199 if (ferror(bzf->handle))
1200 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1202 bzf->strm.avail_in = bzf->bufN;
1203 bzf->strm.next_in = bzf->buf;
1206 ret = BZ2_bzDecompress ( &(bzf->strm) );
1208 if (ret != BZ_OK && ret != BZ_STREAM_END)
1209 { BZ_SETERR(ret); return 0; };
1211 if (ret == BZ_OK && myfeof(bzf->handle) &&
1212 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1213 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1215 if (ret == BZ_STREAM_END)
1216 { BZ_SETERR(BZ_STREAM_END);
1217 return len - bzf->strm.avail_out; };
1218 if (bzf->strm.avail_out == 0)
1219 { BZ_SETERR(BZ_OK); return len; };
1223 return 0; /*not reached*/
1227 /*---------------------------------------------------*/
1228 void BZ_API(BZ2_bzReadGetUnused)
1234 bzFile* bzf = (bzFile*)b;
1236 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1237 if (bzf->lastErr != BZ_STREAM_END)
1238 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1239 if (unused == NULL || nUnused == NULL)
1240 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1243 *nUnused = bzf->strm.avail_in;
1244 *unused = bzf->strm.next_in;
1249 /*---------------------------------------------------*/
1250 /*--- Misc convenience stuff ---*/
1251 /*---------------------------------------------------*/
1253 /*---------------------------------------------------*/
1254 int BZ_API(BZ2_bzBuffToBuffCompress)
1256 unsigned int* destLen,
1258 unsigned int sourceLen,
1266 if (dest == NULL || destLen == NULL ||
1268 blockSize100k < 1 || blockSize100k > 9 ||
1269 verbosity < 0 || verbosity > 4 ||
1270 workFactor < 0 || workFactor > 250)
1271 return BZ_PARAM_ERROR;
1273 if (workFactor == 0) workFactor = 30;
1274 strm.bzalloc = NULL;
1277 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1278 verbosity, workFactor );
1279 if (ret != BZ_OK) return ret;
1281 strm.next_in = source;
1282 strm.next_out = dest;
1283 strm.avail_in = sourceLen;
1284 strm.avail_out = *destLen;
1286 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1287 if (ret == BZ_FINISH_OK) goto output_overflow;
1288 if (ret != BZ_STREAM_END) goto errhandler;
1290 /* normal termination */
1291 *destLen -= strm.avail_out;
1292 BZ2_bzCompressEnd ( &strm );
1296 BZ2_bzCompressEnd ( &strm );
1297 return BZ_OUTBUFF_FULL;
1300 BZ2_bzCompressEnd ( &strm );
1305 /*---------------------------------------------------*/
1306 int BZ_API(BZ2_bzBuffToBuffDecompress)
1308 unsigned int* destLen,
1310 unsigned int sourceLen,
1317 if (dest == NULL || destLen == NULL ||
1319 (small != 0 && small != 1) ||
1320 verbosity < 0 || verbosity > 4)
1321 return BZ_PARAM_ERROR;
1323 strm.bzalloc = NULL;
1326 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1327 if (ret != BZ_OK) return ret;
1329 strm.next_in = source;
1330 strm.next_out = dest;
1331 strm.avail_in = sourceLen;
1332 strm.avail_out = *destLen;
1334 ret = BZ2_bzDecompress ( &strm );
1335 if (ret == BZ_OK) goto output_overflow_or_eof;
1336 if (ret != BZ_STREAM_END) goto errhandler;
1338 /* normal termination */
1339 *destLen -= strm.avail_out;
1340 BZ2_bzDecompressEnd ( &strm );
1343 output_overflow_or_eof:
1344 if (strm.avail_out > 0) {
1345 BZ2_bzDecompressEnd ( &strm );
1346 return BZ_UNEXPECTED_EOF;
1348 BZ2_bzDecompressEnd ( &strm );
1349 return BZ_OUTBUFF_FULL;
1353 BZ2_bzDecompressEnd ( &strm );
1358 /*---------------------------------------------------*/
1360 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1361 to support better zlib compatibility.
1362 This code is not _officially_ part of libbzip2 (yet);
1363 I haven't tested it, documented it, or considered the
1364 threading-safeness of it.
1365 If this code breaks, please contact both Yoshioka and me.
1367 /*---------------------------------------------------*/
1369 /*---------------------------------------------------*/
1371 return version like "0.9.5d, 4-Sept-1999".
1373 const char * BZ_API(BZ2_bzlibVersion)(void)
1380 /*---------------------------------------------------*/
1382 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1385 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1387 # define SET_BINARY_MODE(file)
1390 BZFILE * bzopen_or_bzdopen
1391 ( const char *path, /* no use when bzdopen */
1392 int fd, /* no use when bzdopen */
1394 int open_mode) /* bzopen: 0, bzdopen:1 */
1397 char unused[BZ_MAX_UNUSED];
1398 int blockSize100k = 9;
1400 char mode2[10] = "";
1402 BZFILE *bzfp = NULL;
1404 int workFactor = 30;
1408 if (mode == NULL) return NULL;
1416 smallMode = 1; break;
1418 if (isdigit((int)(*mode))) {
1419 blockSize100k = *mode-BZ_HDR_0;
1424 strcat(mode2, writing ? "w" : "r" );
1425 strcat(mode2,"b"); /* binary mode */
1428 if (path==NULL || strcmp(path,"")==0) {
1429 fp = (writing ? stdout : stdin);
1430 SET_BINARY_MODE(fp);
1432 fp = fopen(path,mode2);
1435 #ifdef BZ_STRICT_ANSI
1438 fp = fdopen(fd,mode2);
1441 if (fp == NULL) return NULL;
1444 /* Guard against total chaos and anarchy -- JRS */
1445 if (blockSize100k < 1) blockSize100k = 1;
1446 if (blockSize100k > 9) blockSize100k = 9;
1447 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1448 verbosity,workFactor);
1450 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1454 if (fp != stdin && fp != stdout) fclose(fp);
1461 /*---------------------------------------------------*/
1463 open file for read or write.
1464 ex) bzopen("file","w9")
1465 case path="" or NULL => use stdin or stdout.
1467 BZFILE * BZ_API(BZ2_bzopen)
1471 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1475 /*---------------------------------------------------*/
1476 BZFILE * BZ_API(BZ2_bzdopen)
1480 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1484 /*---------------------------------------------------*/
1485 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1488 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1489 nread = BZ2_bzRead(&bzerr,b,buf,len);
1490 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1498 /*---------------------------------------------------*/
1499 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1503 BZ2_bzWrite(&bzerr,b,buf,len);
1512 /*---------------------------------------------------*/
1513 int BZ_API(BZ2_bzflush) (BZFILE *b)
1515 /* do nothing now... */
1520 /*---------------------------------------------------*/
1521 void BZ_API(BZ2_bzclose) (BZFILE* b)
1526 if (b==NULL) {return;}
1527 fp = ((bzFile *)b)->handle;
1528 if(((bzFile*)b)->writing){
1529 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1531 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1534 BZ2_bzReadClose(&bzerr,b);
1536 if(fp!=stdin && fp!=stdout){
1542 /*---------------------------------------------------*/
1544 return last error code
1546 static const char *bzerrorstrings[] = {
1557 ,"???" /* for future */
1558 ,"???" /* for future */
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1561 ,"???" /* for future */
1562 ,"???" /* for future */
1566 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1568 int err = ((bzFile *)b)->lastErr;
1572 return bzerrorstrings[err*-1];
1576 #endif /* BZ_NO_COMPRESS */
1578 /*-------------------------------------------------------------*/
1579 /*--- end bzlib.c ---*/
1580 /*-------------------------------------------------------------*/