2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
5 /*-------------------------------------------------------------*/
8 This file is a part of bzip2 and/or libbzip2, a program and
9 library for lossless, block-sorting data compression.
11 Copyright (C) 1996-2005 Julian R Seward. All rights reserved.
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
20 2. The origin of this software must not be misrepresented; you must
21 not claim that you wrote the original software. If you use this
22 software in a product, an acknowledgment in the product
23 documentation would be appreciated but is not required.
25 3. Altered source versions must be plainly marked as such, and must
26 not be misrepresented as being the original software.
28 4. The name of the author may not be used to endorse or promote
29 products derived from this software without specific prior written
32 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
33 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
36 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 Julian Seward, Cambridge, UK.
46 bzip2/libbzip2 version 1.0 of 21 March 2000
48 This program is based on (at least) the work of:
58 For more information on these sources, see the manual.
64 0.9.0 -- original version.
66 0.9.0a/b -- no changes in this file.
69 * made zero-length BZ_FLUSH work correctly in bzCompress().
70 * fixed bzWrite/bzRead to ignore zero-length requests.
71 * fixed bzread to correctly handle read requests after EOF.
72 * wrong parameter order in call to bzDecompressInit in
73 bzBuffToBuffDecompress. Fixed.
76 #include <sys/cdefs.h>
77 __FBSDID("$FreeBSD$");
79 #include "bzlib_private.h"
81 #ifndef BZ_NO_COMPRESS
83 /*---------------------------------------------------*/
84 /*--- Compression stuff ---*/
85 /*---------------------------------------------------*/
88 /*---------------------------------------------------*/
90 void BZ2_bz__AssertH__fail ( int errcode )
93 "\n\nbzip2/libbzip2: internal error number %d.\n"
94 "This is a bug in bzip2/libbzip2, %s.\n"
95 "Please report it to me at: jseward@bzip.org. If this happened\n"
96 "when you were using some program which uses libbzip2 as a\n"
97 "component, you should also report this bug to the author(s)\n"
98 "of that program. Please make an effort to report this bug;\n"
99 "timely and accurate bug reports eventually lead to higher\n"
100 "quality software. Thanks. Julian Seward, 15 February 2005.\n\n",
105 if (errcode == 1007) {
107 "\n*** A special note about internal error number 1007 ***\n"
109 "Experience suggests that a common cause of i.e. 1007\n"
110 "is unreliable memory or other hardware. The 1007 assertion\n"
111 "just happens to cross-check the results of huge numbers of\n"
112 "memory reads/writes, and so acts (unintendedly) as a stress\n"
113 "test of your memory system.\n"
115 "I suggest the following: try compressing the file again,\n"
116 "possibly monitoring progress in detail with the -vv flag.\n"
118 "* If the error cannot be reproduced, and/or happens at different\n"
119 " points in compression, you may have a flaky memory system.\n"
120 " Try a memory-test program. I have used Memtest86\n"
121 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
122 " Memtest86 tests memory much more thorougly than your BIOSs\n"
123 " power-on test, and may find failures that the BIOS doesn't.\n"
125 "* If the error can be repeatably reproduced, this is a bug in\n"
126 " bzip2, and I would very much like to hear about it. Please\n"
127 " let me know, and, ideally, save a copy of the file causing the\n"
128 " problem -- without which I will be unable to investigate it.\n"
137 #endif /* BZ_NO_COMPRESS */
139 /*---------------------------------------------------*/
141 int bz_config_ok ( void )
143 if (sizeof(int) != 4) return 0;
144 if (sizeof(short) != 2) return 0;
145 if (sizeof(char) != 1) return 0;
150 /*---------------------------------------------------*/
152 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
154 void* v = malloc ( items * size );
159 void default_bzfree ( void* opaque, void* addr )
161 if (addr != NULL) free ( addr );
164 #ifndef BZ_NO_COMPRESS
166 /*---------------------------------------------------*/
168 void prepare_new_block ( EState* s )
173 s->state_out_pos = 0;
174 BZ_INITIALISE_CRC ( s->blockCRC );
175 for (i = 0; i < 256; i++) s->inUse[i] = False;
180 /*---------------------------------------------------*/
182 void init_RL ( EState* s )
184 s->state_in_ch = 256;
190 Bool isempty_RL ( EState* s )
192 if (s->state_in_ch < 256 && s->state_in_len > 0)
198 /*---------------------------------------------------*/
199 int BZ_API(BZ2_bzCompressInit)
208 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
211 blockSize100k < 1 || blockSize100k > 9 ||
212 workFactor < 0 || workFactor > 250)
213 return BZ_PARAM_ERROR;
215 if (workFactor == 0) workFactor = 30;
216 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
217 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
219 s = BZALLOC( sizeof(EState) );
220 if (s == NULL) return BZ_MEM_ERROR;
227 n = 100000 * blockSize100k;
228 s->arr1 = BZALLOC( n * sizeof(UInt32) );
229 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
230 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
232 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
233 if (s->arr1 != NULL) BZFREE(s->arr1);
234 if (s->arr2 != NULL) BZFREE(s->arr2);
235 if (s->ftab != NULL) BZFREE(s->ftab);
236 if (s != NULL) BZFREE(s);
241 s->state = BZ_S_INPUT;
242 s->mode = BZ_M_RUNNING;
244 s->blockSize100k = blockSize100k;
245 s->nblockMAX = 100000 * blockSize100k - 19;
246 s->verbosity = verbosity;
247 s->workFactor = workFactor;
249 s->block = (UChar*)s->arr2;
250 s->mtfv = (UInt16*)s->arr1;
252 s->ptr = (UInt32*)s->arr1;
255 strm->total_in_lo32 = 0;
256 strm->total_in_hi32 = 0;
257 strm->total_out_lo32 = 0;
258 strm->total_out_hi32 = 0;
260 prepare_new_block ( s );
265 /*---------------------------------------------------*/
267 void add_pair_to_block ( EState* s )
270 UChar ch = (UChar)(s->state_in_ch);
271 for (i = 0; i < s->state_in_len; i++) {
272 BZ_UPDATE_CRC( s->blockCRC, ch );
274 s->inUse[s->state_in_ch] = True;
275 switch (s->state_in_len) {
277 s->block[s->nblock] = (UChar)ch; s->nblock++;
280 s->block[s->nblock] = (UChar)ch; s->nblock++;
281 s->block[s->nblock] = (UChar)ch; s->nblock++;
284 s->block[s->nblock] = (UChar)ch; s->nblock++;
285 s->block[s->nblock] = (UChar)ch; s->nblock++;
286 s->block[s->nblock] = (UChar)ch; s->nblock++;
289 s->inUse[s->state_in_len-4] = True;
290 s->block[s->nblock] = (UChar)ch; s->nblock++;
291 s->block[s->nblock] = (UChar)ch; s->nblock++;
292 s->block[s->nblock] = (UChar)ch; s->nblock++;
293 s->block[s->nblock] = (UChar)ch; s->nblock++;
294 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
301 /*---------------------------------------------------*/
303 void flush_RL ( EState* s )
305 if (s->state_in_ch < 256) add_pair_to_block ( s );
310 /*---------------------------------------------------*/
311 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
313 UInt32 zchh = (UInt32)(zchh0); \
314 /*-- fast track the common case --*/ \
315 if (zchh != zs->state_in_ch && \
316 zs->state_in_len == 1) { \
317 UChar ch = (UChar)(zs->state_in_ch); \
318 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
319 zs->inUse[zs->state_in_ch] = True; \
320 zs->block[zs->nblock] = (UChar)ch; \
322 zs->state_in_ch = zchh; \
325 /*-- general, uncommon cases --*/ \
326 if (zchh != zs->state_in_ch || \
327 zs->state_in_len == 255) { \
328 if (zs->state_in_ch < 256) \
329 add_pair_to_block ( zs ); \
330 zs->state_in_ch = zchh; \
331 zs->state_in_len = 1; \
333 zs->state_in_len++; \
338 /*---------------------------------------------------*/
340 Bool copy_input_until_stop ( EState* s )
342 Bool progress_in = False;
344 if (s->mode == BZ_M_RUNNING) {
346 /*-- fast track the common case --*/
348 /*-- block full? --*/
349 if (s->nblock >= s->nblockMAX) break;
351 if (s->strm->avail_in == 0) break;
353 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
356 s->strm->total_in_lo32++;
357 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
362 /*-- general, uncommon case --*/
364 /*-- block full? --*/
365 if (s->nblock >= s->nblockMAX) break;
367 if (s->strm->avail_in == 0) break;
368 /*-- flush/finish end? --*/
369 if (s->avail_in_expect == 0) break;
371 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
374 s->strm->total_in_lo32++;
375 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
376 s->avail_in_expect--;
383 /*---------------------------------------------------*/
385 Bool copy_output_until_stop ( EState* s )
387 Bool progress_out = False;
391 /*-- no output space? --*/
392 if (s->strm->avail_out == 0) break;
394 /*-- block done? --*/
395 if (s->state_out_pos >= s->numZ) break;
398 *(s->strm->next_out) = s->zbits[s->state_out_pos];
400 s->strm->avail_out--;
402 s->strm->total_out_lo32++;
403 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
410 /*---------------------------------------------------*/
412 Bool handle_compress ( bz_stream* strm )
414 Bool progress_in = False;
415 Bool progress_out = False;
416 EState* s = strm->state;
420 if (s->state == BZ_S_OUTPUT) {
421 progress_out |= copy_output_until_stop ( s );
422 if (s->state_out_pos < s->numZ) break;
423 if (s->mode == BZ_M_FINISHING &&
424 s->avail_in_expect == 0 &&
425 isempty_RL(s)) break;
426 prepare_new_block ( s );
427 s->state = BZ_S_INPUT;
428 if (s->mode == BZ_M_FLUSHING &&
429 s->avail_in_expect == 0 &&
430 isempty_RL(s)) break;
433 if (s->state == BZ_S_INPUT) {
434 progress_in |= copy_input_until_stop ( s );
435 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
437 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
438 s->state = BZ_S_OUTPUT;
441 if (s->nblock >= s->nblockMAX) {
442 BZ2_compressBlock ( s, False );
443 s->state = BZ_S_OUTPUT;
446 if (s->strm->avail_in == 0) {
453 return progress_in || progress_out;
457 /*---------------------------------------------------*/
458 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
462 if (strm == NULL) return BZ_PARAM_ERROR;
464 if (s == NULL) return BZ_PARAM_ERROR;
465 if (s->strm != strm) return BZ_PARAM_ERROR;
471 return BZ_SEQUENCE_ERROR;
474 if (action == BZ_RUN) {
475 progress = handle_compress ( strm );
476 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
479 if (action == BZ_FLUSH) {
480 s->avail_in_expect = strm->avail_in;
481 s->mode = BZ_M_FLUSHING;
485 if (action == BZ_FINISH) {
486 s->avail_in_expect = strm->avail_in;
487 s->mode = BZ_M_FINISHING;
491 return BZ_PARAM_ERROR;
494 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
495 if (s->avail_in_expect != s->strm->avail_in)
496 return BZ_SEQUENCE_ERROR;
497 progress = handle_compress ( strm );
498 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
499 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
500 s->mode = BZ_M_RUNNING;
504 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
505 if (s->avail_in_expect != s->strm->avail_in)
506 return BZ_SEQUENCE_ERROR;
507 progress = handle_compress ( strm );
508 if (!progress) return BZ_SEQUENCE_ERROR;
509 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
510 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
512 return BZ_STREAM_END;
514 return BZ_OK; /*--not reached--*/
518 /*---------------------------------------------------*/
519 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
522 if (strm == NULL) return BZ_PARAM_ERROR;
524 if (s == NULL) return BZ_PARAM_ERROR;
525 if (s->strm != strm) return BZ_PARAM_ERROR;
527 if (s->arr1 != NULL) BZFREE(s->arr1);
528 if (s->arr2 != NULL) BZFREE(s->arr2);
529 if (s->ftab != NULL) BZFREE(s->ftab);
537 #endif /* BZ_NO_COMPRESS */
539 /*---------------------------------------------------*/
540 /*--- Decompression stuff ---*/
541 /*---------------------------------------------------*/
543 /*---------------------------------------------------*/
544 int BZ_API(BZ2_bzDecompressInit)
551 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
553 if (strm == NULL) return BZ_PARAM_ERROR;
554 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
555 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
557 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
558 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
560 s = BZALLOC( sizeof(DState) );
561 if (s == NULL) return BZ_MEM_ERROR;
564 s->state = BZ_X_MAGIC_1;
567 s->calculatedCombinedCRC = 0;
568 strm->total_in_lo32 = 0;
569 strm->total_in_hi32 = 0;
570 strm->total_out_lo32 = 0;
571 strm->total_out_hi32 = 0;
572 s->smallDecompress = (Bool)small;
577 s->verbosity = verbosity;
583 /*---------------------------------------------------*/
584 /* Return True iff data corruption is discovered.
585 Returns False if there is no problem.
588 Bool unRLE_obuf_to_output_FAST ( DState* s )
592 if (s->blockRandomised) {
595 /* try to finish existing run */
597 if (s->strm->avail_out == 0) return False;
598 if (s->state_out_len == 0) break;
599 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
600 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
603 s->strm->avail_out--;
604 s->strm->total_out_lo32++;
605 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
608 /* can a new run be started? */
609 if (s->nblock_used == s->save_nblock+1) return False;
611 /* Only caused by corrupt data stream? */
612 if (s->nblock_used > s->save_nblock+1)
615 s->state_out_len = 1;
616 s->state_out_ch = s->k0;
617 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
618 k1 ^= BZ_RAND_MASK; s->nblock_used++;
619 if (s->nblock_used == s->save_nblock+1) continue;
620 if (k1 != s->k0) { s->k0 = k1; continue; };
622 s->state_out_len = 2;
623 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
624 k1 ^= BZ_RAND_MASK; s->nblock_used++;
625 if (s->nblock_used == s->save_nblock+1) continue;
626 if (k1 != s->k0) { s->k0 = k1; continue; };
628 s->state_out_len = 3;
629 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
630 k1 ^= BZ_RAND_MASK; s->nblock_used++;
631 if (s->nblock_used == s->save_nblock+1) continue;
632 if (k1 != s->k0) { s->k0 = k1; continue; };
634 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
635 k1 ^= BZ_RAND_MASK; s->nblock_used++;
636 s->state_out_len = ((Int32)k1) + 4;
637 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
638 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
644 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
645 UChar c_state_out_ch = s->state_out_ch;
646 Int32 c_state_out_len = s->state_out_len;
647 Int32 c_nblock_used = s->nblock_used;
649 UInt32* c_tt = s->tt;
650 UInt32 c_tPos = s->tPos;
651 char* cs_next_out = s->strm->next_out;
652 unsigned int cs_avail_out = s->strm->avail_out;
655 UInt32 avail_out_INIT = cs_avail_out;
656 Int32 s_save_nblockPP = s->save_nblock+1;
657 unsigned int total_out_lo32_old;
661 /* try to finish existing run */
662 if (c_state_out_len > 0) {
664 if (cs_avail_out == 0) goto return_notr;
665 if (c_state_out_len == 1) break;
666 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
667 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
672 s_state_out_len_eq_one:
674 if (cs_avail_out == 0) {
675 c_state_out_len = 1; goto return_notr;
677 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
678 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
683 /* Only caused by corrupt data stream? */
684 if (c_nblock_used > s_save_nblockPP)
687 /* can a new run be started? */
688 if (c_nblock_used == s_save_nblockPP) {
689 c_state_out_len = 0; goto return_notr;
691 c_state_out_ch = c_k0;
692 BZ_GET_FAST_C(k1); c_nblock_used++;
694 c_k0 = k1; goto s_state_out_len_eq_one;
696 if (c_nblock_used == s_save_nblockPP)
697 goto s_state_out_len_eq_one;
700 BZ_GET_FAST_C(k1); c_nblock_used++;
701 if (c_nblock_used == s_save_nblockPP) continue;
702 if (k1 != c_k0) { c_k0 = k1; continue; };
705 BZ_GET_FAST_C(k1); c_nblock_used++;
706 if (c_nblock_used == s_save_nblockPP) continue;
707 if (k1 != c_k0) { c_k0 = k1; continue; };
709 BZ_GET_FAST_C(k1); c_nblock_used++;
710 c_state_out_len = ((Int32)k1) + 4;
711 BZ_GET_FAST_C(c_k0); c_nblock_used++;
715 total_out_lo32_old = s->strm->total_out_lo32;
716 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
717 if (s->strm->total_out_lo32 < total_out_lo32_old)
718 s->strm->total_out_hi32++;
721 s->calculatedBlockCRC = c_calculatedBlockCRC;
722 s->state_out_ch = c_state_out_ch;
723 s->state_out_len = c_state_out_len;
724 s->nblock_used = c_nblock_used;
728 s->strm->next_out = cs_next_out;
729 s->strm->avail_out = cs_avail_out;
737 /*---------------------------------------------------*/
738 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
744 mid = (nb + na) >> 1;
745 if (indx >= cftab[mid]) nb = mid; else na = mid;
747 while (na - nb != 1);
752 /*---------------------------------------------------*/
753 /* Return True iff data corruption is discovered.
754 Returns False if there is no problem.
757 Bool unRLE_obuf_to_output_SMALL ( DState* s )
761 if (s->blockRandomised) {
764 /* try to finish existing run */
766 if (s->strm->avail_out == 0) return False;
767 if (s->state_out_len == 0) break;
768 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
769 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
772 s->strm->avail_out--;
773 s->strm->total_out_lo32++;
774 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
777 /* can a new run be started? */
778 if (s->nblock_used == s->save_nblock+1) return False;
780 /* Only caused by corrupt data stream? */
781 if (s->nblock_used > s->save_nblock+1)
784 s->state_out_len = 1;
785 s->state_out_ch = s->k0;
786 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
787 k1 ^= BZ_RAND_MASK; s->nblock_used++;
788 if (s->nblock_used == s->save_nblock+1) continue;
789 if (k1 != s->k0) { s->k0 = k1; continue; };
791 s->state_out_len = 2;
792 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
793 k1 ^= BZ_RAND_MASK; s->nblock_used++;
794 if (s->nblock_used == s->save_nblock+1) continue;
795 if (k1 != s->k0) { s->k0 = k1; continue; };
797 s->state_out_len = 3;
798 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
799 k1 ^= BZ_RAND_MASK; s->nblock_used++;
800 if (s->nblock_used == s->save_nblock+1) continue;
801 if (k1 != s->k0) { s->k0 = k1; continue; };
803 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
804 k1 ^= BZ_RAND_MASK; s->nblock_used++;
805 s->state_out_len = ((Int32)k1) + 4;
806 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
807 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
813 /* try to finish existing run */
815 if (s->strm->avail_out == 0) return False;
816 if (s->state_out_len == 0) break;
817 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
818 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
821 s->strm->avail_out--;
822 s->strm->total_out_lo32++;
823 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
826 /* can a new run be started? */
827 if (s->nblock_used == s->save_nblock+1) return False;
829 /* Only caused by corrupt data stream? */
830 if (s->nblock_used > s->save_nblock+1)
833 s->state_out_len = 1;
834 s->state_out_ch = s->k0;
835 BZ_GET_SMALL(k1); s->nblock_used++;
836 if (s->nblock_used == s->save_nblock+1) continue;
837 if (k1 != s->k0) { s->k0 = k1; continue; };
839 s->state_out_len = 2;
840 BZ_GET_SMALL(k1); s->nblock_used++;
841 if (s->nblock_used == s->save_nblock+1) continue;
842 if (k1 != s->k0) { s->k0 = k1; continue; };
844 s->state_out_len = 3;
845 BZ_GET_SMALL(k1); s->nblock_used++;
846 if (s->nblock_used == s->save_nblock+1) continue;
847 if (k1 != s->k0) { s->k0 = k1; continue; };
849 BZ_GET_SMALL(k1); s->nblock_used++;
850 s->state_out_len = ((Int32)k1) + 4;
851 BZ_GET_SMALL(s->k0); s->nblock_used++;
858 /*---------------------------------------------------*/
859 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
863 if (strm == NULL) return BZ_PARAM_ERROR;
865 if (s == NULL) return BZ_PARAM_ERROR;
866 if (s->strm != strm) return BZ_PARAM_ERROR;
869 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
870 if (s->state == BZ_X_OUTPUT) {
871 if (s->smallDecompress)
872 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
873 corrupt = unRLE_obuf_to_output_FAST ( s );
874 if (corrupt) return BZ_DATA_ERROR;
875 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
876 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
877 if (s->verbosity >= 3)
878 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
879 s->calculatedBlockCRC );
880 if (s->verbosity >= 2) VPrintf0 ( "]" );
881 if (s->calculatedBlockCRC != s->storedBlockCRC)
882 return BZ_DATA_ERROR;
883 s->calculatedCombinedCRC
884 = (s->calculatedCombinedCRC << 1) |
885 (s->calculatedCombinedCRC >> 31);
886 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
887 s->state = BZ_X_BLKHDR_1;
892 if (s->state >= BZ_X_MAGIC_1) {
893 Int32 r = BZ2_decompress ( s );
894 if (r == BZ_STREAM_END) {
895 if (s->verbosity >= 3)
896 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
897 s->storedCombinedCRC, s->calculatedCombinedCRC );
898 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
899 return BZ_DATA_ERROR;
902 if (s->state != BZ_X_OUTPUT) return r;
908 return 0; /*NOTREACHED*/
912 /*---------------------------------------------------*/
913 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
916 if (strm == NULL) return BZ_PARAM_ERROR;
918 if (s == NULL) return BZ_PARAM_ERROR;
919 if (s->strm != strm) return BZ_PARAM_ERROR;
921 if (s->tt != NULL) BZFREE(s->tt);
922 if (s->ll16 != NULL) BZFREE(s->ll16);
923 if (s->ll4 != NULL) BZFREE(s->ll4);
931 #ifndef BZ_NO_COMPRESS
934 /*---------------------------------------------------*/
935 /*--- File I/O stuff ---*/
936 /*---------------------------------------------------*/
938 #define BZ_SETERR(eee) \
940 if (bzerror != NULL) *bzerror = eee; \
941 if (bzf != NULL) bzf->lastErr = eee; \
947 Char buf[BZ_MAX_UNUSED];
957 /*---------------------------------------------*/
958 static Bool myfeof ( FILE* f )
960 Int32 c = fgetc ( f );
961 if (c == EOF) return True;
967 /*---------------------------------------------------*/
968 BZFILE* BZ_API(BZ2_bzWriteOpen)
981 (blockSize100k < 1 || blockSize100k > 9) ||
982 (workFactor < 0 || workFactor > 250) ||
983 (verbosity < 0 || verbosity > 4))
984 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
987 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
989 bzf = malloc ( sizeof(bzFile) );
991 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
994 bzf->initialisedOk = False;
998 bzf->strm.bzalloc = NULL;
999 bzf->strm.bzfree = NULL;
1000 bzf->strm.opaque = NULL;
1002 if (workFactor == 0) workFactor = 30;
1003 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
1004 verbosity, workFactor );
1006 { BZ_SETERR(ret); free(bzf); return NULL; };
1008 bzf->strm.avail_in = 0;
1009 bzf->initialisedOk = True;
1015 /*---------------------------------------------------*/
1016 void BZ_API(BZ2_bzWrite)
1023 bzFile* bzf = (bzFile*)b;
1026 if (bzf == NULL || buf == NULL || len < 0)
1027 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1028 if (!(bzf->writing))
1029 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1030 if (ferror(bzf->handle))
1031 { BZ_SETERR(BZ_IO_ERROR); return; };
1034 { BZ_SETERR(BZ_OK); return; };
1036 bzf->strm.avail_in = len;
1037 bzf->strm.next_in = buf;
1040 bzf->strm.avail_out = BZ_MAX_UNUSED;
1041 bzf->strm.next_out = bzf->buf;
1042 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1043 if (ret != BZ_RUN_OK)
1044 { BZ_SETERR(ret); return; };
1046 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1047 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1048 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1050 if (n != n2 || ferror(bzf->handle))
1051 { BZ_SETERR(BZ_IO_ERROR); return; };
1054 if (bzf->strm.avail_in == 0)
1055 { BZ_SETERR(BZ_OK); return; };
1060 /*---------------------------------------------------*/
1061 void BZ_API(BZ2_bzWriteClose)
1065 unsigned int* nbytes_in,
1066 unsigned int* nbytes_out )
1068 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1069 nbytes_in, NULL, nbytes_out, NULL );
1073 void BZ_API(BZ2_bzWriteClose64)
1077 unsigned int* nbytes_in_lo32,
1078 unsigned int* nbytes_in_hi32,
1079 unsigned int* nbytes_out_lo32,
1080 unsigned int* nbytes_out_hi32 )
1083 bzFile* bzf = (bzFile*)b;
1086 { BZ_SETERR(BZ_OK); return; };
1087 if (!(bzf->writing))
1088 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1089 if (ferror(bzf->handle))
1090 { BZ_SETERR(BZ_IO_ERROR); return; };
1092 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1093 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1094 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1095 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1097 if ((!abandon) && bzf->lastErr == BZ_OK) {
1099 bzf->strm.avail_out = BZ_MAX_UNUSED;
1100 bzf->strm.next_out = bzf->buf;
1101 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1102 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1103 { BZ_SETERR(ret); return; };
1105 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1106 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1107 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1109 if (n != n2 || ferror(bzf->handle))
1110 { BZ_SETERR(BZ_IO_ERROR); return; };
1113 if (ret == BZ_STREAM_END) break;
1117 if ( !abandon && !ferror ( bzf->handle ) ) {
1118 fflush ( bzf->handle );
1119 if (ferror(bzf->handle))
1120 { BZ_SETERR(BZ_IO_ERROR); return; };
1123 if (nbytes_in_lo32 != NULL)
1124 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1125 if (nbytes_in_hi32 != NULL)
1126 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1127 if (nbytes_out_lo32 != NULL)
1128 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1129 if (nbytes_out_hi32 != NULL)
1130 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1133 BZ2_bzCompressEnd ( &(bzf->strm) );
1138 /*---------------------------------------------------*/
1139 BZFILE* BZ_API(BZ2_bzReadOpen)
1153 (small != 0 && small != 1) ||
1154 (verbosity < 0 || verbosity > 4) ||
1155 (unused == NULL && nUnused != 0) ||
1156 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1157 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1160 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1162 bzf = malloc ( sizeof(bzFile) );
1164 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1168 bzf->initialisedOk = False;
1171 bzf->writing = False;
1172 bzf->strm.bzalloc = NULL;
1173 bzf->strm.bzfree = NULL;
1174 bzf->strm.opaque = NULL;
1176 while (nUnused > 0) {
1177 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1178 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1182 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1184 { BZ_SETERR(ret); free(bzf); return NULL; };
1186 bzf->strm.avail_in = bzf->bufN;
1187 bzf->strm.next_in = bzf->buf;
1189 bzf->initialisedOk = True;
1194 /*---------------------------------------------------*/
1195 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1197 bzFile* bzf = (bzFile*)b;
1201 { BZ_SETERR(BZ_OK); return; };
1204 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1206 if (bzf->initialisedOk)
1207 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1212 /*---------------------------------------------------*/
1213 int BZ_API(BZ2_bzRead)
1220 bzFile* bzf = (bzFile*)b;
1224 if (bzf == NULL || buf == NULL || len < 0)
1225 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1228 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1231 { BZ_SETERR(BZ_OK); return 0; };
1233 bzf->strm.avail_out = len;
1234 bzf->strm.next_out = buf;
1238 if (ferror(bzf->handle))
1239 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1241 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1242 n = fread ( bzf->buf, sizeof(UChar),
1243 BZ_MAX_UNUSED, bzf->handle );
1244 if (ferror(bzf->handle))
1245 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1247 bzf->strm.avail_in = bzf->bufN;
1248 bzf->strm.next_in = bzf->buf;
1251 ret = BZ2_bzDecompress ( &(bzf->strm) );
1253 if (ret != BZ_OK && ret != BZ_STREAM_END)
1254 { BZ_SETERR(ret); return 0; };
1256 if (ret == BZ_OK && myfeof(bzf->handle) &&
1257 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1258 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1260 if (ret == BZ_STREAM_END)
1261 { BZ_SETERR(BZ_STREAM_END);
1262 return len - bzf->strm.avail_out; };
1263 if (bzf->strm.avail_out == 0)
1264 { BZ_SETERR(BZ_OK); return len; };
1268 return 0; /*not reached*/
1272 /*---------------------------------------------------*/
1273 void BZ_API(BZ2_bzReadGetUnused)
1279 bzFile* bzf = (bzFile*)b;
1281 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1282 if (bzf->lastErr != BZ_STREAM_END)
1283 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1284 if (unused == NULL || nUnused == NULL)
1285 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1288 *nUnused = bzf->strm.avail_in;
1289 *unused = bzf->strm.next_in;
1294 /*---------------------------------------------------*/
1295 /*--- Misc convenience stuff ---*/
1296 /*---------------------------------------------------*/
1298 /*---------------------------------------------------*/
1299 int BZ_API(BZ2_bzBuffToBuffCompress)
1301 unsigned int* destLen,
1303 unsigned int sourceLen,
1311 if (dest == NULL || destLen == NULL ||
1313 blockSize100k < 1 || blockSize100k > 9 ||
1314 verbosity < 0 || verbosity > 4 ||
1315 workFactor < 0 || workFactor > 250)
1316 return BZ_PARAM_ERROR;
1318 if (workFactor == 0) workFactor = 30;
1319 strm.bzalloc = NULL;
1322 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1323 verbosity, workFactor );
1324 if (ret != BZ_OK) return ret;
1326 strm.next_in = source;
1327 strm.next_out = dest;
1328 strm.avail_in = sourceLen;
1329 strm.avail_out = *destLen;
1331 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1332 if (ret == BZ_FINISH_OK) goto output_overflow;
1333 if (ret != BZ_STREAM_END) goto errhandler;
1335 /* normal termination */
1336 *destLen -= strm.avail_out;
1337 BZ2_bzCompressEnd ( &strm );
1341 BZ2_bzCompressEnd ( &strm );
1342 return BZ_OUTBUFF_FULL;
1345 BZ2_bzCompressEnd ( &strm );
1350 /*---------------------------------------------------*/
1351 int BZ_API(BZ2_bzBuffToBuffDecompress)
1353 unsigned int* destLen,
1355 unsigned int sourceLen,
1362 if (dest == NULL || destLen == NULL ||
1364 (small != 0 && small != 1) ||
1365 verbosity < 0 || verbosity > 4)
1366 return BZ_PARAM_ERROR;
1368 strm.bzalloc = NULL;
1371 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1372 if (ret != BZ_OK) return ret;
1374 strm.next_in = source;
1375 strm.next_out = dest;
1376 strm.avail_in = sourceLen;
1377 strm.avail_out = *destLen;
1379 ret = BZ2_bzDecompress ( &strm );
1380 if (ret == BZ_OK) goto output_overflow_or_eof;
1381 if (ret != BZ_STREAM_END) goto errhandler;
1383 /* normal termination */
1384 *destLen -= strm.avail_out;
1385 BZ2_bzDecompressEnd ( &strm );
1388 output_overflow_or_eof:
1389 if (strm.avail_out > 0) {
1390 BZ2_bzDecompressEnd ( &strm );
1391 return BZ_UNEXPECTED_EOF;
1393 BZ2_bzDecompressEnd ( &strm );
1394 return BZ_OUTBUFF_FULL;
1398 BZ2_bzDecompressEnd ( &strm );
1403 /*---------------------------------------------------*/
1405 Code contributed by Yoshioka Tsuneo
1406 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1407 to support better zlib compatibility.
1408 This code is not _officially_ part of libbzip2 (yet);
1409 I haven't tested it, documented it, or considered the
1410 threading-safeness of it.
1411 If this code breaks, please contact both Yoshioka and me.
1413 /*---------------------------------------------------*/
1415 /*---------------------------------------------------*/
1417 return version like "0.9.0c".
1419 const char * BZ_API(BZ2_bzlibVersion)(void)
1426 /*---------------------------------------------------*/
1428 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1431 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1433 # define SET_BINARY_MODE(file)
1436 BZFILE * bzopen_or_bzdopen
1437 ( const char *path, /* no use when bzdopen */
1438 int fd, /* no use when bzdopen */
1440 int open_mode) /* bzopen: 0, bzdopen:1 */
1443 char unused[BZ_MAX_UNUSED];
1444 int blockSize100k = 9;
1446 char mode2[10] = "";
1448 BZFILE *bzfp = NULL;
1450 int workFactor = 30;
1454 if (mode == NULL) return NULL;
1462 smallMode = 1; break;
1464 if (isdigit((int)(*mode))) {
1465 blockSize100k = *mode-BZ_HDR_0;
1470 strcat(mode2, writing ? "w" : "r" );
1471 strcat(mode2,"b"); /* binary mode */
1474 if (path==NULL || strcmp(path,"")==0) {
1475 fp = (writing ? stdout : stdin);
1476 SET_BINARY_MODE(fp);
1478 fp = fopen(path,mode2);
1481 #ifdef BZ_STRICT_ANSI
1484 fp = fdopen(fd,mode2);
1487 if (fp == NULL) return NULL;
1490 /* Guard against total chaos and anarchy -- JRS */
1491 if (blockSize100k < 1) blockSize100k = 1;
1492 if (blockSize100k > 9) blockSize100k = 9;
1493 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1494 verbosity,workFactor);
1496 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1500 if (fp != stdin && fp != stdout) fclose(fp);
1507 /*---------------------------------------------------*/
1509 open file for read or write.
1510 ex) bzopen("file","w9")
1511 case path="" or NULL => use stdin or stdout.
1513 BZFILE * BZ_API(BZ2_bzopen)
1517 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1521 /*---------------------------------------------------*/
1522 BZFILE * BZ_API(BZ2_bzdopen)
1526 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1530 /*---------------------------------------------------*/
1531 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1534 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1535 nread = BZ2_bzRead(&bzerr,b,buf,len);
1536 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1544 /*---------------------------------------------------*/
1545 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1549 BZ2_bzWrite(&bzerr,b,buf,len);
1558 /*---------------------------------------------------*/
1559 int BZ_API(BZ2_bzflush) (BZFILE *b)
1561 /* do nothing now... */
1566 /*---------------------------------------------------*/
1567 void BZ_API(BZ2_bzclose) (BZFILE* b)
1570 FILE *fp = ((bzFile *)b)->handle;
1572 if (b==NULL) {return;}
1573 if(((bzFile*)b)->writing){
1574 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1576 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1579 BZ2_bzReadClose(&bzerr,b);
1581 if(fp!=stdin && fp!=stdout){
1587 /*---------------------------------------------------*/
1589 return last error code
1591 static char *bzerrorstrings[] = {
1602 ,"???" /* for future */
1603 ,"???" /* for future */
1604 ,"???" /* for future */
1605 ,"???" /* for future */
1606 ,"???" /* for future */
1607 ,"???" /* for future */
1611 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1613 int err = ((bzFile *)b)->lastErr;
1617 return bzerrorstrings[err*-1];
1621 #endif /* BZ_NO_COMPRESS */
1623 /*-------------------------------------------------------------*/
1624 /*--- end bzlib.c ---*/
1625 /*-------------------------------------------------------------*/