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.5 of 10 December 2007
12 Copyright (C) 1996-2007 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, 10 December 2007.\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;
608 Int32 ro_blockSize100k = s->blockSize100k;
611 UInt32 avail_out_INIT = cs_avail_out;
612 Int32 s_save_nblockPP = s->save_nblock+1;
613 unsigned int total_out_lo32_old;
617 /* try to finish existing run */
618 if (c_state_out_len > 0) {
620 if (cs_avail_out == 0) goto return_notr;
621 if (c_state_out_len == 1) break;
622 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
623 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
628 s_state_out_len_eq_one:
630 if (cs_avail_out == 0) {
631 c_state_out_len = 1; goto return_notr;
633 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
634 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
639 /* Only caused by corrupt data stream? */
640 if (c_nblock_used > s_save_nblockPP)
643 /* can a new run be started? */
644 if (c_nblock_used == s_save_nblockPP) {
645 c_state_out_len = 0; goto return_notr;
647 c_state_out_ch = c_k0;
648 BZ_GET_FAST_C(k1); c_nblock_used++;
650 c_k0 = k1; goto s_state_out_len_eq_one;
652 if (c_nblock_used == s_save_nblockPP)
653 goto s_state_out_len_eq_one;
656 BZ_GET_FAST_C(k1); c_nblock_used++;
657 if (c_nblock_used == s_save_nblockPP) continue;
658 if (k1 != c_k0) { c_k0 = k1; continue; };
661 BZ_GET_FAST_C(k1); c_nblock_used++;
662 if (c_nblock_used == s_save_nblockPP) continue;
663 if (k1 != c_k0) { c_k0 = k1; continue; };
665 BZ_GET_FAST_C(k1); c_nblock_used++;
666 c_state_out_len = ((Int32)k1) + 4;
667 BZ_GET_FAST_C(c_k0); c_nblock_used++;
671 total_out_lo32_old = s->strm->total_out_lo32;
672 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
673 if (s->strm->total_out_lo32 < total_out_lo32_old)
674 s->strm->total_out_hi32++;
677 s->calculatedBlockCRC = c_calculatedBlockCRC;
678 s->state_out_ch = c_state_out_ch;
679 s->state_out_len = c_state_out_len;
680 s->nblock_used = c_nblock_used;
684 s->strm->next_out = cs_next_out;
685 s->strm->avail_out = cs_avail_out;
693 /*---------------------------------------------------*/
694 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
700 mid = (nb + na) >> 1;
701 if (indx >= cftab[mid]) nb = mid; else na = mid;
703 while (na - nb != 1);
708 /*---------------------------------------------------*/
709 /* Return True iff data corruption is discovered.
710 Returns False if there is no problem.
713 Bool unRLE_obuf_to_output_SMALL ( DState* s )
717 if (s->blockRandomised) {
720 /* try to finish existing run */
722 if (s->strm->avail_out == 0) return False;
723 if (s->state_out_len == 0) break;
724 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
725 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
728 s->strm->avail_out--;
729 s->strm->total_out_lo32++;
730 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
733 /* can a new run be started? */
734 if (s->nblock_used == s->save_nblock+1) return False;
736 /* Only caused by corrupt data stream? */
737 if (s->nblock_used > s->save_nblock+1)
740 s->state_out_len = 1;
741 s->state_out_ch = s->k0;
742 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
743 k1 ^= BZ_RAND_MASK; s->nblock_used++;
744 if (s->nblock_used == s->save_nblock+1) continue;
745 if (k1 != s->k0) { s->k0 = k1; continue; };
747 s->state_out_len = 2;
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 = 3;
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 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
760 k1 ^= BZ_RAND_MASK; s->nblock_used++;
761 s->state_out_len = ((Int32)k1) + 4;
762 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
763 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
769 /* try to finish existing run */
771 if (s->strm->avail_out == 0) return False;
772 if (s->state_out_len == 0) break;
773 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
774 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
777 s->strm->avail_out--;
778 s->strm->total_out_lo32++;
779 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
782 /* can a new run be started? */
783 if (s->nblock_used == s->save_nblock+1) return False;
785 /* Only caused by corrupt data stream? */
786 if (s->nblock_used > s->save_nblock+1)
789 s->state_out_len = 1;
790 s->state_out_ch = s->k0;
791 BZ_GET_SMALL(k1); s->nblock_used++;
792 if (s->nblock_used == s->save_nblock+1) continue;
793 if (k1 != s->k0) { s->k0 = k1; continue; };
795 s->state_out_len = 2;
796 BZ_GET_SMALL(k1); s->nblock_used++;
797 if (s->nblock_used == s->save_nblock+1) continue;
798 if (k1 != s->k0) { s->k0 = k1; continue; };
800 s->state_out_len = 3;
801 BZ_GET_SMALL(k1); s->nblock_used++;
802 if (s->nblock_used == s->save_nblock+1) continue;
803 if (k1 != s->k0) { s->k0 = k1; continue; };
805 BZ_GET_SMALL(k1); s->nblock_used++;
806 s->state_out_len = ((Int32)k1) + 4;
807 BZ_GET_SMALL(s->k0); s->nblock_used++;
814 /*---------------------------------------------------*/
815 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
819 if (strm == NULL) return BZ_PARAM_ERROR;
821 if (s == NULL) return BZ_PARAM_ERROR;
822 if (s->strm != strm) return BZ_PARAM_ERROR;
825 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
826 if (s->state == BZ_X_OUTPUT) {
827 if (s->smallDecompress)
828 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
829 corrupt = unRLE_obuf_to_output_FAST ( s );
830 if (corrupt) return BZ_DATA_ERROR;
831 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
832 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
833 if (s->verbosity >= 3)
834 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
835 s->calculatedBlockCRC );
836 if (s->verbosity >= 2) VPrintf0 ( "]" );
837 if (s->calculatedBlockCRC != s->storedBlockCRC)
838 return BZ_DATA_ERROR;
839 s->calculatedCombinedCRC
840 = (s->calculatedCombinedCRC << 1) |
841 (s->calculatedCombinedCRC >> 31);
842 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
843 s->state = BZ_X_BLKHDR_1;
848 if (s->state >= BZ_X_MAGIC_1) {
849 Int32 r = BZ2_decompress ( s );
850 if (r == BZ_STREAM_END) {
851 if (s->verbosity >= 3)
852 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
853 s->storedCombinedCRC, s->calculatedCombinedCRC );
854 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
855 return BZ_DATA_ERROR;
858 if (s->state != BZ_X_OUTPUT) return r;
864 return 0; /*NOTREACHED*/
868 /*---------------------------------------------------*/
869 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
872 if (strm == NULL) return BZ_PARAM_ERROR;
874 if (s == NULL) return BZ_PARAM_ERROR;
875 if (s->strm != strm) return BZ_PARAM_ERROR;
877 if (s->tt != NULL) BZFREE(s->tt);
878 if (s->ll16 != NULL) BZFREE(s->ll16);
879 if (s->ll4 != NULL) BZFREE(s->ll4);
887 #ifndef BZ_NO_COMPRESS
890 /*---------------------------------------------------*/
891 /*--- File I/O stuff ---*/
892 /*---------------------------------------------------*/
894 #define BZ_SETERR(eee) \
896 if (bzerror != NULL) *bzerror = eee; \
897 if (bzf != NULL) bzf->lastErr = eee; \
903 Char buf[BZ_MAX_UNUSED];
913 /*---------------------------------------------*/
914 static Bool myfeof ( FILE* f )
916 Int32 c = fgetc ( f );
917 if (c == EOF) return True;
923 /*---------------------------------------------------*/
924 BZFILE* BZ_API(BZ2_bzWriteOpen)
937 (blockSize100k < 1 || blockSize100k > 9) ||
938 (workFactor < 0 || workFactor > 250) ||
939 (verbosity < 0 || verbosity > 4))
940 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
943 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
945 bzf = malloc ( sizeof(bzFile) );
947 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
950 bzf->initialisedOk = False;
954 bzf->strm.bzalloc = NULL;
955 bzf->strm.bzfree = NULL;
956 bzf->strm.opaque = NULL;
958 if (workFactor == 0) workFactor = 30;
959 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
960 verbosity, workFactor );
962 { BZ_SETERR(ret); free(bzf); return NULL; };
964 bzf->strm.avail_in = 0;
965 bzf->initialisedOk = True;
971 /*---------------------------------------------------*/
972 void BZ_API(BZ2_bzWrite)
979 bzFile* bzf = (bzFile*)b;
982 if (bzf == NULL || buf == NULL || len < 0)
983 { BZ_SETERR(BZ_PARAM_ERROR); return; };
985 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
986 if (ferror(bzf->handle))
987 { BZ_SETERR(BZ_IO_ERROR); return; };
990 { BZ_SETERR(BZ_OK); return; };
992 bzf->strm.avail_in = len;
993 bzf->strm.next_in = buf;
996 bzf->strm.avail_out = BZ_MAX_UNUSED;
997 bzf->strm.next_out = bzf->buf;
998 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
999 if (ret != BZ_RUN_OK)
1000 { BZ_SETERR(ret); return; };
1002 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1003 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1004 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1006 if (n != n2 || ferror(bzf->handle))
1007 { BZ_SETERR(BZ_IO_ERROR); return; };
1010 if (bzf->strm.avail_in == 0)
1011 { BZ_SETERR(BZ_OK); return; };
1016 /*---------------------------------------------------*/
1017 void BZ_API(BZ2_bzWriteClose)
1021 unsigned int* nbytes_in,
1022 unsigned int* nbytes_out )
1024 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1025 nbytes_in, NULL, nbytes_out, NULL );
1029 void BZ_API(BZ2_bzWriteClose64)
1033 unsigned int* nbytes_in_lo32,
1034 unsigned int* nbytes_in_hi32,
1035 unsigned int* nbytes_out_lo32,
1036 unsigned int* nbytes_out_hi32 )
1039 bzFile* bzf = (bzFile*)b;
1042 { BZ_SETERR(BZ_OK); return; };
1043 if (!(bzf->writing))
1044 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1045 if (ferror(bzf->handle))
1046 { BZ_SETERR(BZ_IO_ERROR); return; };
1048 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1049 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1050 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1051 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1053 if ((!abandon) && bzf->lastErr == BZ_OK) {
1055 bzf->strm.avail_out = BZ_MAX_UNUSED;
1056 bzf->strm.next_out = bzf->buf;
1057 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1058 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1059 { BZ_SETERR(ret); return; };
1061 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1062 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1063 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1065 if (n != n2 || ferror(bzf->handle))
1066 { BZ_SETERR(BZ_IO_ERROR); return; };
1069 if (ret == BZ_STREAM_END) break;
1073 if ( !abandon && !ferror ( bzf->handle ) ) {
1074 fflush ( bzf->handle );
1075 if (ferror(bzf->handle))
1076 { BZ_SETERR(BZ_IO_ERROR); return; };
1079 if (nbytes_in_lo32 != NULL)
1080 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1081 if (nbytes_in_hi32 != NULL)
1082 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1083 if (nbytes_out_lo32 != NULL)
1084 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1085 if (nbytes_out_hi32 != NULL)
1086 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1089 BZ2_bzCompressEnd ( &(bzf->strm) );
1094 /*---------------------------------------------------*/
1095 BZFILE* BZ_API(BZ2_bzReadOpen)
1109 (small != 0 && small != 1) ||
1110 (verbosity < 0 || verbosity > 4) ||
1111 (unused == NULL && nUnused != 0) ||
1112 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1113 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1116 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1118 bzf = malloc ( sizeof(bzFile) );
1120 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1124 bzf->initialisedOk = False;
1127 bzf->writing = False;
1128 bzf->strm.bzalloc = NULL;
1129 bzf->strm.bzfree = NULL;
1130 bzf->strm.opaque = NULL;
1132 while (nUnused > 0) {
1133 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1134 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1138 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1140 { BZ_SETERR(ret); free(bzf); return NULL; };
1142 bzf->strm.avail_in = bzf->bufN;
1143 bzf->strm.next_in = bzf->buf;
1145 bzf->initialisedOk = True;
1150 /*---------------------------------------------------*/
1151 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1153 bzFile* bzf = (bzFile*)b;
1157 { BZ_SETERR(BZ_OK); return; };
1160 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1162 if (bzf->initialisedOk)
1163 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1168 /*---------------------------------------------------*/
1169 int BZ_API(BZ2_bzRead)
1176 bzFile* bzf = (bzFile*)b;
1180 if (bzf == NULL || buf == NULL || len < 0)
1181 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1184 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1187 { BZ_SETERR(BZ_OK); return 0; };
1189 bzf->strm.avail_out = len;
1190 bzf->strm.next_out = buf;
1194 if (ferror(bzf->handle))
1195 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1197 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1198 n = fread ( bzf->buf, sizeof(UChar),
1199 BZ_MAX_UNUSED, bzf->handle );
1200 if (ferror(bzf->handle))
1201 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1203 bzf->strm.avail_in = bzf->bufN;
1204 bzf->strm.next_in = bzf->buf;
1207 ret = BZ2_bzDecompress ( &(bzf->strm) );
1209 if (ret != BZ_OK && ret != BZ_STREAM_END)
1210 { BZ_SETERR(ret); return 0; };
1212 if (ret == BZ_OK && myfeof(bzf->handle) &&
1213 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1214 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1216 if (ret == BZ_STREAM_END)
1217 { BZ_SETERR(BZ_STREAM_END);
1218 return len - bzf->strm.avail_out; };
1219 if (bzf->strm.avail_out == 0)
1220 { BZ_SETERR(BZ_OK); return len; };
1224 return 0; /*not reached*/
1228 /*---------------------------------------------------*/
1229 void BZ_API(BZ2_bzReadGetUnused)
1235 bzFile* bzf = (bzFile*)b;
1237 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1238 if (bzf->lastErr != BZ_STREAM_END)
1239 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1240 if (unused == NULL || nUnused == NULL)
1241 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1244 *nUnused = bzf->strm.avail_in;
1245 *unused = bzf->strm.next_in;
1250 /*---------------------------------------------------*/
1251 /*--- Misc convenience stuff ---*/
1252 /*---------------------------------------------------*/
1254 /*---------------------------------------------------*/
1255 int BZ_API(BZ2_bzBuffToBuffCompress)
1257 unsigned int* destLen,
1259 unsigned int sourceLen,
1267 if (dest == NULL || destLen == NULL ||
1269 blockSize100k < 1 || blockSize100k > 9 ||
1270 verbosity < 0 || verbosity > 4 ||
1271 workFactor < 0 || workFactor > 250)
1272 return BZ_PARAM_ERROR;
1274 if (workFactor == 0) workFactor = 30;
1275 strm.bzalloc = NULL;
1278 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1279 verbosity, workFactor );
1280 if (ret != BZ_OK) return ret;
1282 strm.next_in = source;
1283 strm.next_out = dest;
1284 strm.avail_in = sourceLen;
1285 strm.avail_out = *destLen;
1287 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1288 if (ret == BZ_FINISH_OK) goto output_overflow;
1289 if (ret != BZ_STREAM_END) goto errhandler;
1291 /* normal termination */
1292 *destLen -= strm.avail_out;
1293 BZ2_bzCompressEnd ( &strm );
1297 BZ2_bzCompressEnd ( &strm );
1298 return BZ_OUTBUFF_FULL;
1301 BZ2_bzCompressEnd ( &strm );
1306 /*---------------------------------------------------*/
1307 int BZ_API(BZ2_bzBuffToBuffDecompress)
1309 unsigned int* destLen,
1311 unsigned int sourceLen,
1318 if (dest == NULL || destLen == NULL ||
1320 (small != 0 && small != 1) ||
1321 verbosity < 0 || verbosity > 4)
1322 return BZ_PARAM_ERROR;
1324 strm.bzalloc = NULL;
1327 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1328 if (ret != BZ_OK) return ret;
1330 strm.next_in = source;
1331 strm.next_out = dest;
1332 strm.avail_in = sourceLen;
1333 strm.avail_out = *destLen;
1335 ret = BZ2_bzDecompress ( &strm );
1336 if (ret == BZ_OK) goto output_overflow_or_eof;
1337 if (ret != BZ_STREAM_END) goto errhandler;
1339 /* normal termination */
1340 *destLen -= strm.avail_out;
1341 BZ2_bzDecompressEnd ( &strm );
1344 output_overflow_or_eof:
1345 if (strm.avail_out > 0) {
1346 BZ2_bzDecompressEnd ( &strm );
1347 return BZ_UNEXPECTED_EOF;
1349 BZ2_bzDecompressEnd ( &strm );
1350 return BZ_OUTBUFF_FULL;
1354 BZ2_bzDecompressEnd ( &strm );
1359 /*---------------------------------------------------*/
1361 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1362 to support better zlib compatibility.
1363 This code is not _officially_ part of libbzip2 (yet);
1364 I haven't tested it, documented it, or considered the
1365 threading-safeness of it.
1366 If this code breaks, please contact both Yoshioka and me.
1368 /*---------------------------------------------------*/
1370 /*---------------------------------------------------*/
1372 return version like "0.9.5d, 4-Sept-1999".
1374 const char * BZ_API(BZ2_bzlibVersion)(void)
1381 /*---------------------------------------------------*/
1383 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1386 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1388 # define SET_BINARY_MODE(file)
1391 BZFILE * bzopen_or_bzdopen
1392 ( const char *path, /* no use when bzdopen */
1393 int fd, /* no use when bzdopen */
1395 int open_mode) /* bzopen: 0, bzdopen:1 */
1398 char unused[BZ_MAX_UNUSED];
1399 int blockSize100k = 9;
1401 char mode2[10] = "";
1403 BZFILE *bzfp = NULL;
1405 int workFactor = 30;
1409 if (mode == NULL) return NULL;
1417 smallMode = 1; break;
1419 if (isdigit((int)(*mode))) {
1420 blockSize100k = *mode-BZ_HDR_0;
1425 strcat(mode2, writing ? "w" : "r" );
1426 strcat(mode2,"b"); /* binary mode */
1429 if (path==NULL || strcmp(path,"")==0) {
1430 fp = (writing ? stdout : stdin);
1431 SET_BINARY_MODE(fp);
1433 fp = fopen(path,mode2);
1436 #ifdef BZ_STRICT_ANSI
1439 fp = fdopen(fd,mode2);
1442 if (fp == NULL) return NULL;
1445 /* Guard against total chaos and anarchy -- JRS */
1446 if (blockSize100k < 1) blockSize100k = 1;
1447 if (blockSize100k > 9) blockSize100k = 9;
1448 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1449 verbosity,workFactor);
1451 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1455 if (fp != stdin && fp != stdout) fclose(fp);
1462 /*---------------------------------------------------*/
1464 open file for read or write.
1465 ex) bzopen("file","w9")
1466 case path="" or NULL => use stdin or stdout.
1468 BZFILE * BZ_API(BZ2_bzopen)
1472 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1476 /*---------------------------------------------------*/
1477 BZFILE * BZ_API(BZ2_bzdopen)
1481 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1485 /*---------------------------------------------------*/
1486 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1489 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1490 nread = BZ2_bzRead(&bzerr,b,buf,len);
1491 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1499 /*---------------------------------------------------*/
1500 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1504 BZ2_bzWrite(&bzerr,b,buf,len);
1513 /*---------------------------------------------------*/
1514 int BZ_API(BZ2_bzflush) (BZFILE *b)
1516 /* do nothing now... */
1521 /*---------------------------------------------------*/
1522 void BZ_API(BZ2_bzclose) (BZFILE* b)
1527 if (b==NULL) {return;}
1528 fp = ((bzFile *)b)->handle;
1529 if(((bzFile*)b)->writing){
1530 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1532 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1535 BZ2_bzReadClose(&bzerr,b);
1537 if(fp!=stdin && fp!=stdout){
1543 /*---------------------------------------------------*/
1545 return last error code
1547 static const char *bzerrorstrings[] = {
1558 ,"???" /* for future */
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1561 ,"???" /* for future */
1562 ,"???" /* for future */
1563 ,"???" /* for future */
1567 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1569 int err = ((bzFile *)b)->lastErr;
1573 return bzerrorstrings[err*-1];
1577 #endif /* BZ_NO_COMPRESS */
1579 /*-------------------------------------------------------------*/
1580 /*--- end bzlib.c ---*/
1581 /*-------------------------------------------------------------*/