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.6 of 6 September 2010
12 Copyright (C) 1996-2010 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 "bzlib_private.h"
34 /*---------------------------------------------------*/
35 /*--- Compression stuff ---*/
36 /*---------------------------------------------------*/
39 /*---------------------------------------------------*/
41 void BZ2_bz__AssertH__fail ( int errcode )
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",
56 if (errcode == 1007) {
58 "\n*** A special note about internal error number 1007 ***\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"
66 "I suggest the following: try compressing the file again,\n"
67 "possibly monitoring progress in detail with the -vv flag.\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"
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"
89 /*---------------------------------------------------*/
91 int bz_config_ok ( void )
93 if (sizeof(int) != 4) return 0;
94 if (sizeof(short) != 2) return 0;
95 if (sizeof(char) != 1) return 0;
100 /*---------------------------------------------------*/
107 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
109 void* v = malloc ( items * size );
115 void default_bzfree ( void* opaque, void* addr )
118 if (addr != NULL) free ( addr );
125 /*---------------------------------------------------*/
127 void prepare_new_block ( EState* s )
132 s->state_out_pos = 0;
133 BZ_INITIALISE_CRC ( s->blockCRC );
134 for (i = 0; i < 256; i++) s->inUse[i] = False;
139 /*---------------------------------------------------*/
141 void init_RL ( EState* s )
143 s->state_in_ch = 256;
149 Bool isempty_RL ( EState* s )
151 if (s->state_in_ch < 256 && s->state_in_len > 0)
157 /*---------------------------------------------------*/
158 int BZ_API(BZ2_bzCompressInit)
167 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
170 blockSize100k < 1 || blockSize100k > 9 ||
171 workFactor < 0 || workFactor > 250)
172 return BZ_PARAM_ERROR;
174 if (workFactor == 0) workFactor = 30;
175 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
176 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
178 s = (EState*) BZALLOC( sizeof(EState) );
179 if (s == NULL) return BZ_MEM_ERROR;
186 n = 100000 * blockSize100k;
187 s->arr1 = (UInt32*) BZALLOC( n * sizeof(UInt32) );
188 s->arr2 = (UInt32*) BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
189 s->ftab = (UInt32*) BZALLOC( 65537 * sizeof(UInt32) );
191 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
192 if (s->arr1 != NULL) BZFREE(s->arr1);
193 if (s->arr2 != NULL) BZFREE(s->arr2);
194 if (s->ftab != NULL) BZFREE(s->ftab);
195 if (s != NULL) BZFREE(s);
200 s->state = BZ_S_INPUT;
201 s->mode = BZ_M_RUNNING;
203 s->blockSize100k = blockSize100k;
204 s->nblockMAX = 100000 * blockSize100k - 19;
205 s->verbosity = verbosity;
206 s->workFactor = workFactor;
208 s->block = (UChar*)s->arr2;
209 s->mtfv = (UInt16*)s->arr1;
211 s->ptr = (UInt32*)s->arr1;
214 strm->total_in_lo32 = 0;
215 strm->total_in_hi32 = 0;
216 strm->total_out_lo32 = 0;
217 strm->total_out_hi32 = 0;
219 prepare_new_block ( s );
224 /*---------------------------------------------------*/
226 void add_pair_to_block ( EState* s )
229 UChar ch = (UChar)(s->state_in_ch);
230 for (i = 0; i < s->state_in_len; i++) {
231 BZ_UPDATE_CRC( s->blockCRC, ch );
233 s->inUse[s->state_in_ch] = True;
234 switch (s->state_in_len) {
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++;
243 s->block[s->nblock] = (UChar)ch; s->nblock++;
244 s->block[s->nblock] = (UChar)ch; s->nblock++;
245 s->block[s->nblock] = (UChar)ch; s->nblock++;
248 s->inUse[s->state_in_len-4] = True;
249 s->block[s->nblock] = (UChar)ch; s->nblock++;
250 s->block[s->nblock] = (UChar)ch; s->nblock++;
251 s->block[s->nblock] = (UChar)ch; s->nblock++;
252 s->block[s->nblock] = (UChar)ch; s->nblock++;
253 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
260 /*---------------------------------------------------*/
262 void flush_RL ( EState* s )
264 if (s->state_in_ch < 256) add_pair_to_block ( s );
269 /*---------------------------------------------------*/
270 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
272 UInt32 zchh = (UInt32)(zchh0); \
273 /*-- fast track the common case --*/ \
274 if (zchh != zs->state_in_ch && \
275 zs->state_in_len == 1) { \
276 UChar ch = (UChar)(zs->state_in_ch); \
277 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
278 zs->inUse[zs->state_in_ch] = True; \
279 zs->block[zs->nblock] = (UChar)ch; \
281 zs->state_in_ch = zchh; \
284 /*-- general, uncommon cases --*/ \
285 if (zchh != zs->state_in_ch || \
286 zs->state_in_len == 255) { \
287 if (zs->state_in_ch < 256) \
288 add_pair_to_block ( zs ); \
289 zs->state_in_ch = zchh; \
290 zs->state_in_len = 1; \
292 zs->state_in_len++; \
297 /*---------------------------------------------------*/
299 Bool copy_input_until_stop ( EState* s )
301 Bool progress_in = False;
303 if (s->mode == BZ_M_RUNNING) {
305 /*-- fast track the common case --*/
307 /*-- block full? --*/
308 if (s->nblock >= s->nblockMAX) break;
310 if (s->strm->avail_in == 0) break;
312 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
315 s->strm->total_in_lo32++;
316 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
321 /*-- general, uncommon case --*/
323 /*-- block full? --*/
324 if (s->nblock >= s->nblockMAX) break;
326 if (s->strm->avail_in == 0) break;
327 /*-- flush/finish end? --*/
328 if (s->avail_in_expect == 0) break;
330 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
333 s->strm->total_in_lo32++;
334 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
335 s->avail_in_expect--;
342 /*---------------------------------------------------*/
344 Bool copy_output_until_stop ( EState* s )
346 Bool progress_out = False;
350 /*-- no output space? --*/
351 if (s->strm->avail_out == 0) break;
353 /*-- block done? --*/
354 if (s->state_out_pos >= s->numZ) break;
357 *(s->strm->next_out) = s->zbits[s->state_out_pos];
359 s->strm->avail_out--;
361 s->strm->total_out_lo32++;
362 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
369 /*---------------------------------------------------*/
371 Bool handle_compress ( bz_stream* strm )
373 Bool progress_in = False;
374 Bool progress_out = False;
375 EState* s = (EState*) strm->state;
379 if (s->state == BZ_S_OUTPUT) {
380 progress_out |= copy_output_until_stop ( s );
381 if (s->state_out_pos < s->numZ) break;
382 if (s->mode == BZ_M_FINISHING &&
383 s->avail_in_expect == 0 &&
384 isempty_RL(s)) break;
385 prepare_new_block ( s );
386 s->state = BZ_S_INPUT;
387 if (s->mode == BZ_M_FLUSHING &&
388 s->avail_in_expect == 0 &&
389 isempty_RL(s)) break;
392 if (s->state == BZ_S_INPUT) {
393 progress_in |= copy_input_until_stop ( s );
394 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
396 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
397 s->state = BZ_S_OUTPUT;
400 if (s->nblock >= s->nblockMAX) {
401 BZ2_compressBlock ( s, False );
402 s->state = BZ_S_OUTPUT;
405 if (s->strm->avail_in == 0) {
412 return progress_in || progress_out;
416 /*---------------------------------------------------*/
417 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
421 if (strm == NULL) return BZ_PARAM_ERROR;
422 s = (EState*) strm->state;
423 if (s == NULL) return BZ_PARAM_ERROR;
424 if (s->strm != strm) return BZ_PARAM_ERROR;
430 return BZ_SEQUENCE_ERROR;
433 if (action == BZ_RUN) {
434 progress = handle_compress ( strm );
435 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
438 if (action == BZ_FLUSH) {
439 s->avail_in_expect = strm->avail_in;
440 s->mode = BZ_M_FLUSHING;
444 if (action == BZ_FINISH) {
445 s->avail_in_expect = strm->avail_in;
446 s->mode = BZ_M_FINISHING;
450 return BZ_PARAM_ERROR;
453 if (action != BZ_FLUSH) 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 (s->avail_in_expect > 0 || !isempty_RL(s) ||
458 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
459 s->mode = BZ_M_RUNNING;
463 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
464 if (s->avail_in_expect != s->strm->avail_in)
465 return BZ_SEQUENCE_ERROR;
466 progress = handle_compress ( strm );
467 if (!progress) return BZ_SEQUENCE_ERROR;
468 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
469 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
471 return BZ_STREAM_END;
473 return BZ_OK; /*--not reached--*/
477 /*---------------------------------------------------*/
478 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
481 if (strm == NULL) return BZ_PARAM_ERROR;
482 s = (EState*) strm->state;
483 if (s == NULL) return BZ_PARAM_ERROR;
484 if (s->strm != strm) return BZ_PARAM_ERROR;
486 if (s->arr1 != NULL) BZFREE(s->arr1);
487 if (s->arr2 != NULL) BZFREE(s->arr2);
488 if (s->ftab != NULL) BZFREE(s->ftab);
497 /*---------------------------------------------------*/
498 /*--- Decompression stuff ---*/
499 /*---------------------------------------------------*/
501 /*---------------------------------------------------*/
502 int BZ_API(BZ2_bzDecompressInit)
509 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
511 if (strm == NULL) return BZ_PARAM_ERROR;
512 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
513 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
515 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
516 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
518 s = (DState*) BZALLOC( sizeof(DState) );
519 if (s == NULL) return BZ_MEM_ERROR;
522 s->state = BZ_X_MAGIC_1;
525 s->calculatedCombinedCRC = 0;
526 strm->total_in_lo32 = 0;
527 strm->total_in_hi32 = 0;
528 strm->total_out_lo32 = 0;
529 strm->total_out_hi32 = 0;
530 s->smallDecompress = (Bool)small;
535 s->verbosity = verbosity;
541 /*---------------------------------------------------*/
542 /* Return True iff data corruption is discovered.
543 Returns False if there is no problem.
546 Bool unRLE_obuf_to_output_FAST ( DState* s )
550 if (s->blockRandomised) {
553 /* try to finish existing run */
555 if (s->strm->avail_out == 0) return False;
556 if (s->state_out_len == 0) break;
557 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
558 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
561 s->strm->avail_out--;
562 s->strm->total_out_lo32++;
563 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
566 /* can a new run be started? */
567 if (s->nblock_used == s->save_nblock+1) return False;
569 /* Only caused by corrupt data stream? */
570 if (s->nblock_used > s->save_nblock+1)
573 s->state_out_len = 1;
574 s->state_out_ch = s->k0;
575 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
576 k1 ^= BZ_RAND_MASK; s->nblock_used++;
577 if (s->nblock_used == s->save_nblock+1) continue;
578 if (k1 != s->k0) { s->k0 = k1; continue; };
580 s->state_out_len = 2;
581 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
582 k1 ^= BZ_RAND_MASK; s->nblock_used++;
583 if (s->nblock_used == s->save_nblock+1) continue;
584 if (k1 != s->k0) { s->k0 = k1; continue; };
586 s->state_out_len = 3;
587 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
588 k1 ^= BZ_RAND_MASK; s->nblock_used++;
589 if (s->nblock_used == s->save_nblock+1) continue;
590 if (k1 != s->k0) { s->k0 = k1; continue; };
592 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
593 k1 ^= BZ_RAND_MASK; s->nblock_used++;
594 s->state_out_len = ((Int32)k1) + 4;
595 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
596 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
602 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
603 UChar c_state_out_ch = s->state_out_ch;
604 Int32 c_state_out_len = s->state_out_len;
605 Int32 c_nblock_used = s->nblock_used;
607 UInt32* c_tt = s->tt;
608 UInt32 c_tPos = s->tPos;
609 char* cs_next_out = s->strm->next_out;
610 unsigned int cs_avail_out = s->strm->avail_out;
611 Int32 ro_blockSize100k = s->blockSize100k;
614 UInt32 avail_out_INIT = cs_avail_out;
615 Int32 s_save_nblockPP = s->save_nblock+1;
616 unsigned int total_out_lo32_old;
620 /* try to finish existing run */
621 if (c_state_out_len > 0) {
623 if (cs_avail_out == 0) goto return_notr;
624 if (c_state_out_len == 1) break;
625 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
626 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
631 s_state_out_len_eq_one:
633 if (cs_avail_out == 0) {
634 c_state_out_len = 1; goto return_notr;
636 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
637 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
642 /* Only caused by corrupt data stream? */
643 if (c_nblock_used > s_save_nblockPP)
646 /* can a new run be started? */
647 if (c_nblock_used == s_save_nblockPP) {
648 c_state_out_len = 0; goto return_notr;
650 c_state_out_ch = c_k0;
651 BZ_GET_FAST_C(k1); c_nblock_used++;
653 c_k0 = k1; goto s_state_out_len_eq_one;
655 if (c_nblock_used == s_save_nblockPP)
656 goto s_state_out_len_eq_one;
659 BZ_GET_FAST_C(k1); c_nblock_used++;
660 if (c_nblock_used == s_save_nblockPP) continue;
661 if (k1 != c_k0) { c_k0 = k1; continue; };
664 BZ_GET_FAST_C(k1); c_nblock_used++;
665 if (c_nblock_used == s_save_nblockPP) continue;
666 if (k1 != c_k0) { c_k0 = k1; continue; };
668 BZ_GET_FAST_C(k1); c_nblock_used++;
669 c_state_out_len = ((Int32)k1) + 4;
670 BZ_GET_FAST_C(c_k0); c_nblock_used++;
674 total_out_lo32_old = s->strm->total_out_lo32;
675 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
676 if (s->strm->total_out_lo32 < total_out_lo32_old)
677 s->strm->total_out_hi32++;
680 s->calculatedBlockCRC = c_calculatedBlockCRC;
681 s->state_out_ch = c_state_out_ch;
682 s->state_out_len = c_state_out_len;
683 s->nblock_used = c_nblock_used;
687 s->strm->next_out = cs_next_out;
688 s->strm->avail_out = cs_avail_out;
696 /*---------------------------------------------------*/
700 Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
706 mid = (nb + na) >> 1;
707 if (indx >= cftab[mid]) nb = mid; else na = mid;
709 while (na - nb != 1);
714 /*---------------------------------------------------*/
715 /* Return True iff data corruption is discovered.
716 Returns False if there is no problem.
719 Bool unRLE_obuf_to_output_SMALL ( DState* s )
723 if (s->blockRandomised) {
726 /* try to finish existing run */
728 if (s->strm->avail_out == 0) return False;
729 if (s->state_out_len == 0) break;
730 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
731 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
734 s->strm->avail_out--;
735 s->strm->total_out_lo32++;
736 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
739 /* can a new run be started? */
740 if (s->nblock_used == s->save_nblock+1) return False;
742 /* Only caused by corrupt data stream? */
743 if (s->nblock_used > s->save_nblock+1)
746 s->state_out_len = 1;
747 s->state_out_ch = s->k0;
748 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
749 k1 ^= BZ_RAND_MASK; s->nblock_used++;
750 if (s->nblock_used == s->save_nblock+1) continue;
751 if (k1 != s->k0) { s->k0 = k1; continue; };
753 s->state_out_len = 2;
754 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
755 k1 ^= BZ_RAND_MASK; s->nblock_used++;
756 if (s->nblock_used == s->save_nblock+1) continue;
757 if (k1 != s->k0) { s->k0 = k1; continue; };
759 s->state_out_len = 3;
760 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
761 k1 ^= BZ_RAND_MASK; s->nblock_used++;
762 if (s->nblock_used == s->save_nblock+1) continue;
763 if (k1 != s->k0) { s->k0 = k1; continue; };
765 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
766 k1 ^= BZ_RAND_MASK; s->nblock_used++;
767 s->state_out_len = ((Int32)k1) + 4;
768 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
769 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
775 /* try to finish existing run */
777 if (s->strm->avail_out == 0) return False;
778 if (s->state_out_len == 0) break;
779 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
780 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
783 s->strm->avail_out--;
784 s->strm->total_out_lo32++;
785 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
788 /* can a new run be started? */
789 if (s->nblock_used == s->save_nblock+1) return False;
791 /* Only caused by corrupt data stream? */
792 if (s->nblock_used > s->save_nblock+1)
795 s->state_out_len = 1;
796 s->state_out_ch = s->k0;
797 BZ_GET_SMALL(k1); s->nblock_used++;
798 if (s->nblock_used == s->save_nblock+1) continue;
799 if (k1 != s->k0) { s->k0 = k1; continue; };
801 s->state_out_len = 2;
802 BZ_GET_SMALL(k1); s->nblock_used++;
803 if (s->nblock_used == s->save_nblock+1) continue;
804 if (k1 != s->k0) { s->k0 = k1; continue; };
806 s->state_out_len = 3;
807 BZ_GET_SMALL(k1); s->nblock_used++;
808 if (s->nblock_used == s->save_nblock+1) continue;
809 if (k1 != s->k0) { s->k0 = k1; continue; };
811 BZ_GET_SMALL(k1); s->nblock_used++;
812 s->state_out_len = ((Int32)k1) + 4;
813 BZ_GET_SMALL(s->k0); s->nblock_used++;
820 /*---------------------------------------------------*/
821 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
825 if (strm == NULL) return BZ_PARAM_ERROR;
826 s = (DState*) strm->state;
827 if (s == NULL) return BZ_PARAM_ERROR;
828 if (s->strm != strm) return BZ_PARAM_ERROR;
831 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
832 if (s->state == BZ_X_OUTPUT) {
833 if (s->smallDecompress)
834 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
835 corrupt = unRLE_obuf_to_output_FAST ( s );
836 if (corrupt) return BZ_DATA_ERROR;
837 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
838 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
839 if (s->verbosity >= 3)
840 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
841 s->calculatedBlockCRC );
842 if (s->verbosity >= 2) VPrintf0 ( "]" );
843 if (s->calculatedBlockCRC != s->storedBlockCRC)
844 return BZ_DATA_ERROR;
845 s->calculatedCombinedCRC
846 = (s->calculatedCombinedCRC << 1) |
847 (s->calculatedCombinedCRC >> 31);
848 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
849 s->state = BZ_X_BLKHDR_1;
854 if (s->state >= BZ_X_MAGIC_1) {
855 Int32 r = BZ2_decompress ( s );
856 if (r == BZ_STREAM_END) {
857 if (s->verbosity >= 3)
858 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
859 s->storedCombinedCRC, s->calculatedCombinedCRC );
860 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
861 return BZ_DATA_ERROR;
864 if (s->state != BZ_X_OUTPUT) return r;
870 return 0; /*NOTREACHED*/
874 /*---------------------------------------------------*/
875 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
878 if (strm == NULL) return BZ_PARAM_ERROR;
879 s = (DState*) strm->state;
880 if (s == NULL) return BZ_PARAM_ERROR;
881 if (s->strm != strm) return BZ_PARAM_ERROR;
883 if (s->tt != NULL) BZFREE(s->tt);
884 if (s->ll16 != NULL) BZFREE(s->ll16);
885 if (s->ll4 != NULL) BZFREE(s->ll4);
895 /*---------------------------------------------------*/
896 /*--- File I/O stuff ---*/
897 /*---------------------------------------------------*/
899 #define BZ_SETERR(eee) \
901 if (bzerror != NULL) *bzerror = eee; \
902 if (bzf != NULL) bzf->lastErr = eee; \
908 Char buf[BZ_MAX_UNUSED];
918 /*---------------------------------------------*/
919 static Bool myfeof ( FILE* f )
921 Int32 c = fgetc ( f );
922 if (c == EOF) return True;
928 /*---------------------------------------------------*/
929 BZFILE* BZ_API(BZ2_bzWriteOpen)
942 (blockSize100k < 1 || blockSize100k > 9) ||
943 (workFactor < 0 || workFactor > 250) ||
944 (verbosity < 0 || verbosity > 4))
945 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
948 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
950 bzf = (bzFile*) malloc ( sizeof(bzFile) );
952 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
955 bzf->initialisedOk = False;
959 bzf->strm.bzalloc = NULL;
960 bzf->strm.bzfree = NULL;
961 bzf->strm.opaque = NULL;
963 if (workFactor == 0) workFactor = 30;
964 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
965 verbosity, workFactor );
967 { BZ_SETERR(ret); free(bzf); return NULL; };
969 bzf->strm.avail_in = 0;
970 bzf->initialisedOk = True;
976 /*---------------------------------------------------*/
977 void BZ_API(BZ2_bzWrite)
984 bzFile* bzf = (bzFile*)b;
987 if (bzf == NULL || buf == NULL || len < 0)
988 { BZ_SETERR(BZ_PARAM_ERROR); return; };
990 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
991 if (ferror(bzf->handle))
992 { BZ_SETERR(BZ_IO_ERROR); return; };
995 { BZ_SETERR(BZ_OK); return; };
997 bzf->strm.avail_in = len;
998 bzf->strm.next_in = (char*)buf;
1001 bzf->strm.avail_out = BZ_MAX_UNUSED;
1002 bzf->strm.next_out = bzf->buf;
1003 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1004 if (ret != BZ_RUN_OK)
1005 { BZ_SETERR(ret); return; };
1007 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1008 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1009 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1011 if (n != n2 || ferror(bzf->handle))
1012 { BZ_SETERR(BZ_IO_ERROR); return; };
1015 if (bzf->strm.avail_in == 0)
1016 { BZ_SETERR(BZ_OK); return; };
1021 /*---------------------------------------------------*/
1022 void BZ_API(BZ2_bzWriteClose)
1026 unsigned int* nbytes_in,
1027 unsigned int* nbytes_out )
1029 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1030 nbytes_in, NULL, nbytes_out, NULL );
1034 void BZ_API(BZ2_bzWriteClose64)
1038 unsigned int* nbytes_in_lo32,
1039 unsigned int* nbytes_in_hi32,
1040 unsigned int* nbytes_out_lo32,
1041 unsigned int* nbytes_out_hi32 )
1044 bzFile* bzf = (bzFile*)b;
1047 { BZ_SETERR(BZ_OK); return; };
1048 if (!(bzf->writing))
1049 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1050 if (ferror(bzf->handle))
1051 { BZ_SETERR(BZ_IO_ERROR); return; };
1053 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1054 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1055 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1056 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1058 if ((!abandon) && bzf->lastErr == BZ_OK) {
1060 bzf->strm.avail_out = BZ_MAX_UNUSED;
1061 bzf->strm.next_out = bzf->buf;
1062 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1063 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1064 { BZ_SETERR(ret); return; };
1066 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1067 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1068 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1070 if (n != n2 || ferror(bzf->handle))
1071 { BZ_SETERR(BZ_IO_ERROR); return; };
1074 if (ret == BZ_STREAM_END) break;
1078 if ( !abandon && !ferror ( bzf->handle ) ) {
1079 fflush ( bzf->handle );
1080 if (ferror(bzf->handle))
1081 { BZ_SETERR(BZ_IO_ERROR); return; };
1084 if (nbytes_in_lo32 != NULL)
1085 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1086 if (nbytes_in_hi32 != NULL)
1087 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1088 if (nbytes_out_lo32 != NULL)
1089 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1090 if (nbytes_out_hi32 != NULL)
1091 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1094 BZ2_bzCompressEnd ( &(bzf->strm) );
1099 /*---------------------------------------------------*/
1100 BZFILE* BZ_API(BZ2_bzReadOpen)
1114 (small != 0 && small != 1) ||
1115 (verbosity < 0 || verbosity > 4) ||
1116 (unused == NULL && nUnused != 0) ||
1117 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1118 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1121 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1123 bzf = (bzFile*) malloc ( sizeof(bzFile) );
1125 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1129 bzf->initialisedOk = False;
1132 bzf->writing = False;
1133 bzf->strm.bzalloc = NULL;
1134 bzf->strm.bzfree = NULL;
1135 bzf->strm.opaque = NULL;
1137 while (nUnused > 0) {
1138 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1139 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1143 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1145 { BZ_SETERR(ret); free(bzf); return NULL; };
1147 bzf->strm.avail_in = bzf->bufN;
1148 bzf->strm.next_in = bzf->buf;
1150 bzf->initialisedOk = True;
1155 /*---------------------------------------------------*/
1156 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1158 bzFile* bzf = (bzFile*)b;
1162 { BZ_SETERR(BZ_OK); return; };
1165 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1167 if (bzf->initialisedOk)
1168 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1173 /*---------------------------------------------------*/
1174 int BZ_API(BZ2_bzRead)
1181 bzFile* bzf = (bzFile*)b;
1185 if (bzf == NULL || buf == NULL || len < 0)
1186 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1189 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1192 { BZ_SETERR(BZ_OK); return 0; };
1194 bzf->strm.avail_out = len;
1195 bzf->strm.next_out = (char*) buf;
1199 if (ferror(bzf->handle))
1200 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1202 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1203 n = fread ( bzf->buf, sizeof(UChar),
1204 BZ_MAX_UNUSED, bzf->handle );
1205 if (ferror(bzf->handle))
1206 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1208 bzf->strm.avail_in = bzf->bufN;
1209 bzf->strm.next_in = bzf->buf;
1212 ret = BZ2_bzDecompress ( &(bzf->strm) );
1214 if (ret != BZ_OK && ret != BZ_STREAM_END)
1215 { BZ_SETERR(ret); return 0; };
1217 if (ret == BZ_OK && myfeof(bzf->handle) &&
1218 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1219 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1221 if (ret == BZ_STREAM_END)
1222 { BZ_SETERR(BZ_STREAM_END);
1223 return len - bzf->strm.avail_out; };
1224 if (bzf->strm.avail_out == 0)
1225 { BZ_SETERR(BZ_OK); return len; };
1229 return 0; /*not reached*/
1233 /*---------------------------------------------------*/
1234 void BZ_API(BZ2_bzReadGetUnused)
1240 bzFile* bzf = (bzFile*)b;
1242 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1243 if (bzf->lastErr != BZ_STREAM_END)
1244 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1245 if (unused == NULL || nUnused == NULL)
1246 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1249 *nUnused = bzf->strm.avail_in;
1250 *unused = bzf->strm.next_in;
1255 /*---------------------------------------------------*/
1256 /*--- Misc convenience stuff ---*/
1257 /*---------------------------------------------------*/
1259 /*---------------------------------------------------*/
1260 int BZ_API(BZ2_bzBuffToBuffCompress)
1262 unsigned int* destLen,
1264 unsigned int sourceLen,
1272 if (dest == NULL || destLen == NULL ||
1274 blockSize100k < 1 || blockSize100k > 9 ||
1275 verbosity < 0 || verbosity > 4 ||
1276 workFactor < 0 || workFactor > 250)
1277 return BZ_PARAM_ERROR;
1279 if (workFactor == 0) workFactor = 30;
1280 strm.bzalloc = NULL;
1283 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1284 verbosity, workFactor );
1285 if (ret != BZ_OK) return ret;
1287 strm.next_in = source;
1288 strm.next_out = dest;
1289 strm.avail_in = sourceLen;
1290 strm.avail_out = *destLen;
1292 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1293 if (ret == BZ_FINISH_OK) goto output_overflow;
1294 if (ret != BZ_STREAM_END) goto errhandler;
1296 /* normal termination */
1297 *destLen -= strm.avail_out;
1298 BZ2_bzCompressEnd ( &strm );
1302 BZ2_bzCompressEnd ( &strm );
1303 return BZ_OUTBUFF_FULL;
1306 BZ2_bzCompressEnd ( &strm );
1311 /*---------------------------------------------------*/
1312 int BZ_API(BZ2_bzBuffToBuffDecompress)
1314 unsigned int* destLen,
1316 unsigned int sourceLen,
1323 if (dest == NULL || destLen == NULL ||
1325 (small != 0 && small != 1) ||
1326 verbosity < 0 || verbosity > 4)
1327 return BZ_PARAM_ERROR;
1329 strm.bzalloc = NULL;
1332 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1333 if (ret != BZ_OK) return ret;
1335 strm.next_in = source;
1336 strm.next_out = dest;
1337 strm.avail_in = sourceLen;
1338 strm.avail_out = *destLen;
1340 ret = BZ2_bzDecompress ( &strm );
1341 if (ret == BZ_OK) goto output_overflow_or_eof;
1342 if (ret != BZ_STREAM_END) goto errhandler;
1344 /* normal termination */
1345 *destLen -= strm.avail_out;
1346 BZ2_bzDecompressEnd ( &strm );
1349 output_overflow_or_eof:
1350 if (strm.avail_out > 0) {
1351 BZ2_bzDecompressEnd ( &strm );
1352 return BZ_UNEXPECTED_EOF;
1354 BZ2_bzDecompressEnd ( &strm );
1355 return BZ_OUTBUFF_FULL;
1359 BZ2_bzDecompressEnd ( &strm );
1364 /*---------------------------------------------------*/
1366 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1367 to support better zlib compatibility.
1368 This code is not _officially_ part of libbzip2 (yet);
1369 I haven't tested it, documented it, or considered the
1370 threading-safeness of it.
1371 If this code breaks, please contact both Yoshioka and me.
1373 /*---------------------------------------------------*/
1375 /*---------------------------------------------------*/
1377 return version like "0.9.5d, 4-Sept-1999".
1379 const char * BZ_API(BZ2_bzlibVersion)(void)
1386 /*---------------------------------------------------*/
1388 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1391 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1393 # define SET_BINARY_MODE(file)
1396 BZFILE * bzopen_or_bzdopen
1397 ( const char *path, /* no use when bzdopen */
1398 int fd, /* no use when bzdopen */
1400 int open_mode) /* bzopen: 0, bzdopen:1 */
1403 char unused[BZ_MAX_UNUSED];
1404 int blockSize100k = 9;
1406 char mode2[10] = "";
1408 BZFILE *bzfp = NULL;
1410 int workFactor = 30;
1414 if (mode == NULL) return NULL;
1422 smallMode = 1; break;
1424 if (isdigit((int)(*mode))) {
1425 blockSize100k = *mode-BZ_HDR_0;
1430 strcat(mode2, writing ? "w" : "r" );
1431 strcat(mode2,"b"); /* binary mode */
1434 if (path==NULL || strcmp(path,"")==0) {
1435 fp = (writing ? stdout : stdin);
1436 SET_BINARY_MODE(fp);
1438 fp = fopen(path,mode2);
1441 #ifdef BZ_STRICT_ANSI
1444 fp = fdopen(fd,mode2);
1447 if (fp == NULL) return NULL;
1450 /* Guard against total chaos and anarchy -- JRS */
1451 if (blockSize100k < 1) blockSize100k = 1;
1452 if (blockSize100k > 9) blockSize100k = 9;
1453 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1454 verbosity,workFactor);
1456 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1460 if (fp != stdin && fp != stdout) fclose(fp);
1467 /*---------------------------------------------------*/
1469 open file for read or write.
1470 ex) bzopen("file","w9")
1471 case path="" or NULL => use stdin or stdout.
1473 BZFILE * BZ_API(BZ2_bzopen)
1477 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1481 /*---------------------------------------------------*/
1482 BZFILE * BZ_API(BZ2_bzdopen)
1486 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1490 /*---------------------------------------------------*/
1491 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1494 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1495 nread = BZ2_bzRead(&bzerr,b,buf,len);
1496 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1504 /*---------------------------------------------------*/
1505 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1509 BZ2_bzWrite(&bzerr,b,buf,len);
1518 /*---------------------------------------------------*/
1519 int BZ_API(BZ2_bzflush) (BZFILE *b)
1521 /* do nothing now... */
1526 /*---------------------------------------------------*/
1527 void BZ_API(BZ2_bzclose) (BZFILE* b)
1532 if (b==NULL) {return;}
1533 fp = ((bzFile *)b)->handle;
1534 if(((bzFile*)b)->writing){
1535 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1537 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1540 BZ2_bzReadClose(&bzerr,b);
1542 if(fp!=stdin && fp!=stdout){
1548 /*---------------------------------------------------*/
1550 return last error code
1552 static const char *bzerrorstrings[] = {
1563 ,"???" /* for future */
1564 ,"???" /* for future */
1565 ,"???" /* for future */
1566 ,"???" /* for future */
1567 ,"???" /* for future */
1568 ,"???" /* for future */
1572 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1574 int err = ((bzFile *)b)->lastErr;
1578 return bzerrorstrings[err*-1];
1583 /*-------------------------------------------------------------*/
1584 /*--- end bzlib.c ---*/
1585 /*-------------------------------------------------------------*/