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.8 of 13 July 2019
12 Copyright (C) 1996-2019 Julian Seward <jseward@acm.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"
33 #ifndef BZ_NO_COMPRESS
35 /*---------------------------------------------------*/
36 /*--- Compression stuff ---*/
37 /*---------------------------------------------------*/
40 /*---------------------------------------------------*/
42 void BZ2_bz__AssertH__fail ( int errcode
)
45 "\n\nbzip2/libbzip2: internal error number %d.\n"
46 "This is a bug in bzip2/libbzip2, %s.\n"
47 "Please report it to: bzip2-devel@sourceware.org. If this happened\n"
48 "when you were using some program which uses libbzip2 as a\n"
49 "component, you should also report this bug to the author(s)\n"
50 "of that program. Please make an effort to report this bug;\n"
51 "timely and accurate bug reports eventually lead to higher\n"
52 "quality software. Thanks.\n\n",
57 if (errcode
== 1007) {
59 "\n*** A special note about internal error number 1007 ***\n"
61 "Experience suggests that a common cause of i.e. 1007\n"
62 "is unreliable memory or other hardware. The 1007 assertion\n"
63 "just happens to cross-check the results of huge numbers of\n"
64 "memory reads/writes, and so acts (unintendedly) as a stress\n"
65 "test of your memory system.\n"
67 "I suggest the following: try compressing the file again,\n"
68 "possibly monitoring progress in detail with the -vv flag.\n"
70 "* If the error cannot be reproduced, and/or happens at different\n"
71 " points in compression, you may have a flaky memory system.\n"
72 " Try a memory-test program. I have used Memtest86\n"
73 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
74 " Memtest86 tests memory much more thorougly than your BIOSs\n"
75 " power-on test, and may find failures that the BIOS doesn't.\n"
77 "* If the error can be repeatably reproduced, this is a bug in\n"
78 " bzip2, and I would very much like to hear about it. Please\n"
79 " let me know, and, ideally, save a copy of the file causing the\n"
80 " problem -- without which I will be unable to investigate it.\n"
89 #endif /* BZ_NO_COMPRESS */
91 /*---------------------------------------------------*/
93 int bz_config_ok ( void )
95 if (sizeof(int) != 4) return 0;
96 if (sizeof(short) != 2) return 0;
97 if (sizeof(char) != 1) return 0;
102 /*---------------------------------------------------*/
104 void* default_bzalloc ( void* opaque
, Int32 items
, Int32 size
)
106 void* v
= malloc ( items
* size
);
111 void default_bzfree ( void* opaque
, void* addr
)
113 if (addr
!= NULL
) free ( addr
);
116 #ifndef BZ_NO_COMPRESS
118 /*---------------------------------------------------*/
120 void prepare_new_block ( EState
* s
)
125 s
->state_out_pos
= 0;
126 BZ_INITIALISE_CRC ( s
->blockCRC
);
127 for (i
= 0; i
< 256; i
++) s
->inUse
[i
] = False
;
132 /*---------------------------------------------------*/
134 void init_RL ( EState
* s
)
136 s
->state_in_ch
= 256;
142 Bool
isempty_RL ( EState
* s
)
144 if (s
->state_in_ch
< 256 && s
->state_in_len
> 0)
150 /*---------------------------------------------------*/
151 int BZ_API(BZ2_bzCompressInit
)
160 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
163 blockSize100k
< 1 || blockSize100k
> 9 ||
164 workFactor
< 0 || workFactor
> 250)
165 return BZ_PARAM_ERROR
;
167 if (workFactor
== 0) workFactor
= 30;
168 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
169 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
171 s
= BZALLOC( sizeof(EState
) );
172 if (s
== NULL
) return BZ_MEM_ERROR
;
179 n
= 100000 * blockSize100k
;
180 s
->arr1
= BZALLOC( n
* sizeof(UInt32
) );
181 s
->arr2
= BZALLOC( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
182 s
->ftab
= BZALLOC( 65537 * sizeof(UInt32
) );
184 if (s
->arr1
== NULL
|| s
->arr2
== NULL
|| s
->ftab
== NULL
) {
185 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
186 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
187 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
188 if (s
!= NULL
) BZFREE(s
);
193 s
->state
= BZ_S_INPUT
;
194 s
->mode
= BZ_M_RUNNING
;
196 s
->blockSize100k
= blockSize100k
;
197 s
->nblockMAX
= 100000 * blockSize100k
- 19;
198 s
->verbosity
= verbosity
;
199 s
->workFactor
= workFactor
;
201 s
->block
= (UChar
*)s
->arr2
;
202 s
->mtfv
= (UInt16
*)s
->arr1
;
204 s
->ptr
= (UInt32
*)s
->arr1
;
207 strm
->total_in_lo32
= 0;
208 strm
->total_in_hi32
= 0;
209 strm
->total_out_lo32
= 0;
210 strm
->total_out_hi32
= 0;
212 prepare_new_block ( s
);
217 /*---------------------------------------------------*/
219 void add_pair_to_block ( EState
* s
)
222 UChar ch
= (UChar
)(s
->state_in_ch
);
223 for (i
= 0; i
< s
->state_in_len
; i
++) {
224 BZ_UPDATE_CRC( s
->blockCRC
, ch
);
226 s
->inUse
[s
->state_in_ch
] = True
;
227 switch (s
->state_in_len
) {
229 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
232 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
233 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
236 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
237 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
238 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
241 s
->inUse
[s
->state_in_len
-4] = True
;
242 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
++;
246 s
->block
[s
->nblock
] = ((UChar
)(s
->state_in_len
-4));
253 /*---------------------------------------------------*/
255 void flush_RL ( EState
* s
)
257 if (s
->state_in_ch
< 256) add_pair_to_block ( s
);
262 /*---------------------------------------------------*/
263 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
265 UInt32 zchh = (UInt32)(zchh0); \
266 /*-- fast track the common case --*/ \
267 if (zchh != zs->state_in_ch && \
268 zs->state_in_len == 1) { \
269 UChar ch = (UChar)(zs->state_in_ch); \
270 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
271 zs->inUse[zs->state_in_ch] = True; \
272 zs->block[zs->nblock] = (UChar)ch; \
274 zs->state_in_ch = zchh; \
277 /*-- general, uncommon cases --*/ \
278 if (zchh != zs->state_in_ch || \
279 zs->state_in_len == 255) { \
280 if (zs->state_in_ch < 256) \
281 add_pair_to_block ( zs ); \
282 zs->state_in_ch = zchh; \
283 zs->state_in_len = 1; \
285 zs->state_in_len++; \
290 /*---------------------------------------------------*/
292 Bool
copy_input_until_stop ( EState
* s
)
294 Bool progress_in
= False
;
296 if (s
->mode
== BZ_M_RUNNING
) {
298 /*-- fast track the common case --*/
300 /*-- block full? --*/
301 if (s
->nblock
>= s
->nblockMAX
) break;
303 if (s
->strm
->avail_in
== 0) break;
305 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
308 s
->strm
->total_in_lo32
++;
309 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
314 /*-- general, uncommon case --*/
316 /*-- block full? --*/
317 if (s
->nblock
>= s
->nblockMAX
) break;
319 if (s
->strm
->avail_in
== 0) break;
320 /*-- flush/finish end? --*/
321 if (s
->avail_in_expect
== 0) break;
323 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
326 s
->strm
->total_in_lo32
++;
327 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
328 s
->avail_in_expect
--;
335 /*---------------------------------------------------*/
337 Bool
copy_output_until_stop ( EState
* s
)
339 Bool progress_out
= False
;
343 /*-- no output space? --*/
344 if (s
->strm
->avail_out
== 0) break;
346 /*-- block done? --*/
347 if (s
->state_out_pos
>= s
->numZ
) break;
350 *(s
->strm
->next_out
) = s
->zbits
[s
->state_out_pos
];
352 s
->strm
->avail_out
--;
354 s
->strm
->total_out_lo32
++;
355 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
362 /*---------------------------------------------------*/
364 Bool
handle_compress ( bz_stream
* strm
)
366 Bool progress_in
= False
;
367 Bool progress_out
= False
;
368 EState
* s
= strm
->state
;
372 if (s
->state
== BZ_S_OUTPUT
) {
373 progress_out
|= copy_output_until_stop ( s
);
374 if (s
->state_out_pos
< s
->numZ
) break;
375 if (s
->mode
== BZ_M_FINISHING
&&
376 s
->avail_in_expect
== 0 &&
377 isempty_RL(s
)) break;
378 prepare_new_block ( s
);
379 s
->state
= BZ_S_INPUT
;
380 if (s
->mode
== BZ_M_FLUSHING
&&
381 s
->avail_in_expect
== 0 &&
382 isempty_RL(s
)) break;
385 if (s
->state
== BZ_S_INPUT
) {
386 progress_in
|= copy_input_until_stop ( s
);
387 if (s
->mode
!= BZ_M_RUNNING
&& s
->avail_in_expect
== 0) {
389 BZ2_compressBlock ( s
, (Bool
)(s
->mode
== BZ_M_FINISHING
) );
390 s
->state
= BZ_S_OUTPUT
;
393 if (s
->nblock
>= s
->nblockMAX
) {
394 BZ2_compressBlock ( s
, False
);
395 s
->state
= BZ_S_OUTPUT
;
398 if (s
->strm
->avail_in
== 0) {
405 return progress_in
|| progress_out
;
409 /*---------------------------------------------------*/
410 int BZ_API(BZ2_bzCompress
) ( bz_stream
*strm
, int action
)
414 if (strm
== NULL
) return BZ_PARAM_ERROR
;
416 if (s
== NULL
) return BZ_PARAM_ERROR
;
417 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
423 return BZ_SEQUENCE_ERROR
;
426 if (action
== BZ_RUN
) {
427 progress
= handle_compress ( strm
);
428 return progress
? BZ_RUN_OK
: BZ_PARAM_ERROR
;
431 if (action
== BZ_FLUSH
) {
432 s
->avail_in_expect
= strm
->avail_in
;
433 s
->mode
= BZ_M_FLUSHING
;
437 if (action
== BZ_FINISH
) {
438 s
->avail_in_expect
= strm
->avail_in
;
439 s
->mode
= BZ_M_FINISHING
;
443 return BZ_PARAM_ERROR
;
446 if (action
!= BZ_FLUSH
) return BZ_SEQUENCE_ERROR
;
447 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
448 return BZ_SEQUENCE_ERROR
;
449 progress
= handle_compress ( strm
);
450 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
451 s
->state_out_pos
< s
->numZ
) return BZ_FLUSH_OK
;
452 s
->mode
= BZ_M_RUNNING
;
456 if (action
!= BZ_FINISH
) return BZ_SEQUENCE_ERROR
;
457 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
458 return BZ_SEQUENCE_ERROR
;
459 progress
= handle_compress ( strm
);
460 if (!progress
) return BZ_SEQUENCE_ERROR
;
461 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
462 s
->state_out_pos
< s
->numZ
) return BZ_FINISH_OK
;
464 return BZ_STREAM_END
;
466 return BZ_OK
; /*--not reached--*/
470 /*---------------------------------------------------*/
471 int BZ_API(BZ2_bzCompressEnd
) ( bz_stream
*strm
)
474 if (strm
== NULL
) return BZ_PARAM_ERROR
;
476 if (s
== NULL
) return BZ_PARAM_ERROR
;
477 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
479 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
480 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
481 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
489 #endif /* BZ_NO_COMPRESS */
491 /*---------------------------------------------------*/
492 /*--- Decompression stuff ---*/
493 /*---------------------------------------------------*/
495 /*---------------------------------------------------*/
496 int BZ_API(BZ2_bzDecompressInit
)
503 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
505 if (strm
== NULL
) return BZ_PARAM_ERROR
;
506 if (small
!= 0 && small
!= 1) return BZ_PARAM_ERROR
;
507 if (verbosity
< 0 || verbosity
> 4) return BZ_PARAM_ERROR
;
509 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
510 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
512 s
= BZALLOC( sizeof(DState
) );
513 if (s
== NULL
) return BZ_MEM_ERROR
;
516 s
->state
= BZ_X_MAGIC_1
;
519 s
->calculatedCombinedCRC
= 0;
520 strm
->total_in_lo32
= 0;
521 strm
->total_in_hi32
= 0;
522 strm
->total_out_lo32
= 0;
523 strm
->total_out_hi32
= 0;
524 s
->smallDecompress
= (Bool
)small
;
529 s
->verbosity
= verbosity
;
535 /*---------------------------------------------------*/
536 /* Return True iff data corruption is discovered.
537 Returns False if there is no problem.
540 Bool
unRLE_obuf_to_output_FAST ( DState
* s
)
544 if (s
->blockRandomised
) {
547 /* try to finish existing run */
549 if (s
->strm
->avail_out
== 0) return False
;
550 if (s
->state_out_len
== 0) break;
551 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
552 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
555 s
->strm
->avail_out
--;
556 s
->strm
->total_out_lo32
++;
557 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
560 /* can a new run be started? */
561 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
563 /* Only caused by corrupt data stream? */
564 if (s
->nblock_used
> s
->save_nblock
+1)
567 s
->state_out_len
= 1;
568 s
->state_out_ch
= s
->k0
;
569 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
570 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
571 if (s
->nblock_used
== s
->save_nblock
+1) continue;
572 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
574 s
->state_out_len
= 2;
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
= 3;
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 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
587 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
588 s
->state_out_len
= ((Int32
)k1
) + 4;
589 BZ_GET_FAST(s
->k0
); BZ_RAND_UPD_MASK
;
590 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
596 UInt32 c_calculatedBlockCRC
= s
->calculatedBlockCRC
;
597 UChar c_state_out_ch
= s
->state_out_ch
;
598 Int32 c_state_out_len
= s
->state_out_len
;
599 Int32 c_nblock_used
= s
->nblock_used
;
601 UInt32
* c_tt
= s
->tt
;
602 UInt32 c_tPos
= s
->tPos
;
603 char* cs_next_out
= s
->strm
->next_out
;
604 unsigned int cs_avail_out
= s
->strm
->avail_out
;
605 Int32 ro_blockSize100k
= s
->blockSize100k
;
608 UInt32 avail_out_INIT
= cs_avail_out
;
609 Int32 s_save_nblockPP
= s
->save_nblock
+1;
610 unsigned int total_out_lo32_old
;
614 /* try to finish existing run */
615 if (c_state_out_len
> 0) {
617 if (cs_avail_out
== 0) goto return_notr
;
618 if (c_state_out_len
== 1) break;
619 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
620 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
625 s_state_out_len_eq_one
:
627 if (cs_avail_out
== 0) {
628 c_state_out_len
= 1; goto return_notr
;
630 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
631 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
636 /* Only caused by corrupt data stream? */
637 if (c_nblock_used
> s_save_nblockPP
)
640 /* can a new run be started? */
641 if (c_nblock_used
== s_save_nblockPP
) {
642 c_state_out_len
= 0; goto return_notr
;
644 c_state_out_ch
= c_k0
;
645 BZ_GET_FAST_C(k1
); c_nblock_used
++;
647 c_k0
= k1
; goto s_state_out_len_eq_one
;
649 if (c_nblock_used
== s_save_nblockPP
)
650 goto s_state_out_len_eq_one
;
653 BZ_GET_FAST_C(k1
); c_nblock_used
++;
654 if (c_nblock_used
== s_save_nblockPP
) continue;
655 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
658 BZ_GET_FAST_C(k1
); c_nblock_used
++;
659 if (c_nblock_used
== s_save_nblockPP
) continue;
660 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
662 BZ_GET_FAST_C(k1
); c_nblock_used
++;
663 c_state_out_len
= ((Int32
)k1
) + 4;
664 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
668 total_out_lo32_old
= s
->strm
->total_out_lo32
;
669 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
670 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
671 s
->strm
->total_out_hi32
++;
674 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
675 s
->state_out_ch
= c_state_out_ch
;
676 s
->state_out_len
= c_state_out_len
;
677 s
->nblock_used
= c_nblock_used
;
681 s
->strm
->next_out
= cs_next_out
;
682 s
->strm
->avail_out
= cs_avail_out
;
690 /*---------------------------------------------------*/
691 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
697 mid
= (nb
+ na
) >> 1;
698 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
700 while (na
- nb
!= 1);
705 /*---------------------------------------------------*/
706 /* Return True iff data corruption is discovered.
707 Returns False if there is no problem.
710 Bool
unRLE_obuf_to_output_SMALL ( DState
* s
)
714 if (s
->blockRandomised
) {
717 /* try to finish existing run */
719 if (s
->strm
->avail_out
== 0) return False
;
720 if (s
->state_out_len
== 0) break;
721 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
722 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
725 s
->strm
->avail_out
--;
726 s
->strm
->total_out_lo32
++;
727 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
730 /* can a new run be started? */
731 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
733 /* Only caused by corrupt data stream? */
734 if (s
->nblock_used
> s
->save_nblock
+1)
737 s
->state_out_len
= 1;
738 s
->state_out_ch
= s
->k0
;
739 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
740 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
741 if (s
->nblock_used
== s
->save_nblock
+1) continue;
742 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
744 s
->state_out_len
= 2;
745 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
746 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
747 if (s
->nblock_used
== s
->save_nblock
+1) continue;
748 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
750 s
->state_out_len
= 3;
751 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
752 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
753 if (s
->nblock_used
== s
->save_nblock
+1) continue;
754 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
756 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
757 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
758 s
->state_out_len
= ((Int32
)k1
) + 4;
759 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
760 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
766 /* try to finish existing run */
768 if (s
->strm
->avail_out
== 0) return False
;
769 if (s
->state_out_len
== 0) break;
770 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
771 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
774 s
->strm
->avail_out
--;
775 s
->strm
->total_out_lo32
++;
776 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
779 /* can a new run be started? */
780 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
782 /* Only caused by corrupt data stream? */
783 if (s
->nblock_used
> s
->save_nblock
+1)
786 s
->state_out_len
= 1;
787 s
->state_out_ch
= s
->k0
;
788 BZ_GET_SMALL(k1
); s
->nblock_used
++;
789 if (s
->nblock_used
== s
->save_nblock
+1) continue;
790 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
792 s
->state_out_len
= 2;
793 BZ_GET_SMALL(k1
); 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
); s
->nblock_used
++;
799 if (s
->nblock_used
== s
->save_nblock
+1) continue;
800 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
802 BZ_GET_SMALL(k1
); s
->nblock_used
++;
803 s
->state_out_len
= ((Int32
)k1
) + 4;
804 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
811 /*---------------------------------------------------*/
812 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
816 if (strm
== NULL
) return BZ_PARAM_ERROR
;
818 if (s
== NULL
) return BZ_PARAM_ERROR
;
819 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
822 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
823 if (s
->state
== BZ_X_OUTPUT
) {
824 if (s
->smallDecompress
)
825 corrupt
= unRLE_obuf_to_output_SMALL ( s
); else
826 corrupt
= unRLE_obuf_to_output_FAST ( s
);
827 if (corrupt
) return BZ_DATA_ERROR
;
828 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
829 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
830 if (s
->verbosity
>= 3)
831 VPrintf2 ( " {0x%08x, 0x%08x}", s
->storedBlockCRC
,
832 s
->calculatedBlockCRC
);
833 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
834 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
835 return BZ_DATA_ERROR
;
836 s
->calculatedCombinedCRC
837 = (s
->calculatedCombinedCRC
<< 1) |
838 (s
->calculatedCombinedCRC
>> 31);
839 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
840 s
->state
= BZ_X_BLKHDR_1
;
845 if (s
->state
>= BZ_X_MAGIC_1
) {
846 Int32 r
= BZ2_decompress ( s
);
847 if (r
== BZ_STREAM_END
) {
848 if (s
->verbosity
>= 3)
849 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
850 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
851 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
852 return BZ_DATA_ERROR
;
855 if (s
->state
!= BZ_X_OUTPUT
) return r
;
861 return 0; /*NOTREACHED*/
865 /*---------------------------------------------------*/
866 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
869 if (strm
== NULL
) return BZ_PARAM_ERROR
;
871 if (s
== NULL
) return BZ_PARAM_ERROR
;
872 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
874 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
875 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
876 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
884 #ifndef BZ_NO_COMPRESS
887 /*---------------------------------------------------*/
888 /*--- File I/O stuff ---*/
889 /*---------------------------------------------------*/
891 #define BZ_SETERR(eee) \
893 if (bzerror != NULL) *bzerror = eee; \
894 if (bzf != NULL) bzf->lastErr = eee; \
900 Char buf
[BZ_MAX_UNUSED
];
910 /*---------------------------------------------*/
911 static Bool
myfeof ( FILE* f
)
913 Int32 c
= fgetc ( f
);
914 if (c
== EOF
) return True
;
920 /*---------------------------------------------------*/
921 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
934 (blockSize100k
< 1 || blockSize100k
> 9) ||
935 (workFactor
< 0 || workFactor
> 250) ||
936 (verbosity
< 0 || verbosity
> 4))
937 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
940 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
942 bzf
= malloc ( sizeof(bzFile
) );
944 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
947 bzf
->initialisedOk
= False
;
951 bzf
->strm
.bzalloc
= NULL
;
952 bzf
->strm
.bzfree
= NULL
;
953 bzf
->strm
.opaque
= NULL
;
955 if (workFactor
== 0) workFactor
= 30;
956 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
957 verbosity
, workFactor
);
959 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
961 bzf
->strm
.avail_in
= 0;
962 bzf
->initialisedOk
= True
;
968 /*---------------------------------------------------*/
969 void BZ_API(BZ2_bzWrite
)
976 bzFile
* bzf
= (bzFile
*)b
;
979 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
980 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
982 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
983 if (ferror(bzf
->handle
))
984 { BZ_SETERR(BZ_IO_ERROR
); return; };
987 { BZ_SETERR(BZ_OK
); return; };
989 bzf
->strm
.avail_in
= len
;
990 bzf
->strm
.next_in
= buf
;
993 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
994 bzf
->strm
.next_out
= bzf
->buf
;
995 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
996 if (ret
!= BZ_RUN_OK
)
997 { BZ_SETERR(ret
); return; };
999 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1000 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1001 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1003 if (n
!= n2
|| ferror(bzf
->handle
))
1004 { BZ_SETERR(BZ_IO_ERROR
); return; };
1007 if (bzf
->strm
.avail_in
== 0)
1008 { BZ_SETERR(BZ_OK
); return; };
1013 /*---------------------------------------------------*/
1014 void BZ_API(BZ2_bzWriteClose
)
1018 unsigned int* nbytes_in
,
1019 unsigned int* nbytes_out
)
1021 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1022 nbytes_in
, NULL
, nbytes_out
, NULL
);
1026 void BZ_API(BZ2_bzWriteClose64
)
1030 unsigned int* nbytes_in_lo32
,
1031 unsigned int* nbytes_in_hi32
,
1032 unsigned int* nbytes_out_lo32
,
1033 unsigned int* nbytes_out_hi32
)
1036 bzFile
* bzf
= (bzFile
*)b
;
1039 { BZ_SETERR(BZ_OK
); return; };
1040 if (!(bzf
->writing
))
1041 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1042 if (ferror(bzf
->handle
))
1043 { BZ_SETERR(BZ_IO_ERROR
); return; };
1045 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1046 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1047 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1048 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1050 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1052 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1053 bzf
->strm
.next_out
= bzf
->buf
;
1054 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1055 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1056 { BZ_SETERR(ret
); return; };
1058 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1059 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1060 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1062 if (n
!= n2
|| ferror(bzf
->handle
))
1063 { BZ_SETERR(BZ_IO_ERROR
); return; };
1066 if (ret
== BZ_STREAM_END
) break;
1070 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1071 fflush ( bzf
->handle
);
1072 if (ferror(bzf
->handle
))
1073 { BZ_SETERR(BZ_IO_ERROR
); return; };
1076 if (nbytes_in_lo32
!= NULL
)
1077 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1078 if (nbytes_in_hi32
!= NULL
)
1079 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1080 if (nbytes_out_lo32
!= NULL
)
1081 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1082 if (nbytes_out_hi32
!= NULL
)
1083 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1086 BZ2_bzCompressEnd ( &(bzf
->strm
) );
1091 /*---------------------------------------------------*/
1092 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1106 (small
!= 0 && small
!= 1) ||
1107 (verbosity
< 0 || verbosity
> 4) ||
1108 (unused
== NULL
&& nUnused
!= 0) ||
1109 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1110 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1113 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1115 bzf
= malloc ( sizeof(bzFile
) );
1117 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1121 bzf
->initialisedOk
= False
;
1124 bzf
->writing
= False
;
1125 bzf
->strm
.bzalloc
= NULL
;
1126 bzf
->strm
.bzfree
= NULL
;
1127 bzf
->strm
.opaque
= NULL
;
1129 while (nUnused
> 0) {
1130 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1131 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1135 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1137 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1139 bzf
->strm
.avail_in
= bzf
->bufN
;
1140 bzf
->strm
.next_in
= bzf
->buf
;
1142 bzf
->initialisedOk
= True
;
1147 /*---------------------------------------------------*/
1148 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1150 bzFile
* bzf
= (bzFile
*)b
;
1154 { BZ_SETERR(BZ_OK
); return; };
1157 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1159 if (bzf
->initialisedOk
)
1160 (void)BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1165 /*---------------------------------------------------*/
1166 int BZ_API(BZ2_bzRead
)
1173 bzFile
* bzf
= (bzFile
*)b
;
1177 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1178 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1181 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1184 { BZ_SETERR(BZ_OK
); return 0; };
1186 bzf
->strm
.avail_out
= len
;
1187 bzf
->strm
.next_out
= buf
;
1191 if (ferror(bzf
->handle
))
1192 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1194 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1195 n
= fread ( bzf
->buf
, sizeof(UChar
),
1196 BZ_MAX_UNUSED
, bzf
->handle
);
1197 if (ferror(bzf
->handle
))
1198 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1200 bzf
->strm
.avail_in
= bzf
->bufN
;
1201 bzf
->strm
.next_in
= bzf
->buf
;
1204 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1206 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1207 { BZ_SETERR(ret
); return 0; };
1209 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1210 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1211 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1213 if (ret
== BZ_STREAM_END
)
1214 { BZ_SETERR(BZ_STREAM_END
);
1215 return len
- bzf
->strm
.avail_out
; };
1216 if (bzf
->strm
.avail_out
== 0)
1217 { BZ_SETERR(BZ_OK
); return len
; };
1221 return 0; /*not reached*/
1225 /*---------------------------------------------------*/
1226 void BZ_API(BZ2_bzReadGetUnused
)
1232 bzFile
* bzf
= (bzFile
*)b
;
1234 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1235 if (bzf
->lastErr
!= BZ_STREAM_END
)
1236 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1237 if (unused
== NULL
|| nUnused
== NULL
)
1238 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1241 *nUnused
= bzf
->strm
.avail_in
;
1242 *unused
= bzf
->strm
.next_in
;
1247 /*---------------------------------------------------*/
1248 /*--- Misc convenience stuff ---*/
1249 /*---------------------------------------------------*/
1251 /*---------------------------------------------------*/
1252 int BZ_API(BZ2_bzBuffToBuffCompress
)
1254 unsigned int* destLen
,
1256 unsigned int sourceLen
,
1264 if (dest
== NULL
|| destLen
== NULL
||
1266 blockSize100k
< 1 || blockSize100k
> 9 ||
1267 verbosity
< 0 || verbosity
> 4 ||
1268 workFactor
< 0 || workFactor
> 250)
1269 return BZ_PARAM_ERROR
;
1271 if (workFactor
== 0) workFactor
= 30;
1272 strm
.bzalloc
= NULL
;
1275 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1276 verbosity
, workFactor
);
1277 if (ret
!= BZ_OK
) return ret
;
1279 strm
.next_in
= source
;
1280 strm
.next_out
= dest
;
1281 strm
.avail_in
= sourceLen
;
1282 strm
.avail_out
= *destLen
;
1284 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1285 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1286 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1288 /* normal termination */
1289 *destLen
-= strm
.avail_out
;
1290 BZ2_bzCompressEnd ( &strm
);
1294 BZ2_bzCompressEnd ( &strm
);
1295 return BZ_OUTBUFF_FULL
;
1298 BZ2_bzCompressEnd ( &strm
);
1303 /*---------------------------------------------------*/
1304 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1306 unsigned int* destLen
,
1308 unsigned int sourceLen
,
1315 if (dest
== NULL
|| destLen
== NULL
||
1317 (small
!= 0 && small
!= 1) ||
1318 verbosity
< 0 || verbosity
> 4)
1319 return BZ_PARAM_ERROR
;
1321 strm
.bzalloc
= NULL
;
1324 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1325 if (ret
!= BZ_OK
) return ret
;
1327 strm
.next_in
= source
;
1328 strm
.next_out
= dest
;
1329 strm
.avail_in
= sourceLen
;
1330 strm
.avail_out
= *destLen
;
1332 ret
= BZ2_bzDecompress ( &strm
);
1333 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1334 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1336 /* normal termination */
1337 *destLen
-= strm
.avail_out
;
1338 BZ2_bzDecompressEnd ( &strm
);
1341 output_overflow_or_eof
:
1342 if (strm
.avail_out
> 0) {
1343 BZ2_bzDecompressEnd ( &strm
);
1344 return BZ_UNEXPECTED_EOF
;
1346 BZ2_bzDecompressEnd ( &strm
);
1347 return BZ_OUTBUFF_FULL
;
1351 BZ2_bzDecompressEnd ( &strm
);
1356 /*---------------------------------------------------*/
1358 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1359 to support better zlib compatibility.
1360 This code is not _officially_ part of libbzip2 (yet);
1361 I haven't tested it, documented it, or considered the
1362 threading-safeness of it.
1363 If this code breaks, please contact both Yoshioka and me.
1365 /*---------------------------------------------------*/
1367 /*---------------------------------------------------*/
1369 return version like "0.9.5d, 4-Sept-1999".
1371 const char * BZ_API(BZ2_bzlibVersion
)(void)
1378 /*---------------------------------------------------*/
1380 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1383 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1385 # define SET_BINARY_MODE(file)
1388 BZFILE
* bzopen_or_bzdopen
1389 ( const char *path
, /* no use when bzdopen */
1390 int fd
, /* no use when bzdopen */
1392 int open_mode
) /* bzopen: 0, bzdopen:1 */
1395 char unused
[BZ_MAX_UNUSED
];
1396 int blockSize100k
= 9;
1398 char mode2
[10] = "";
1400 BZFILE
*bzfp
= NULL
;
1402 int workFactor
= 30;
1406 if (mode
== NULL
) return NULL
;
1414 smallMode
= 1; break;
1416 if (isdigit((int)(*mode
))) {
1417 blockSize100k
= *mode
-BZ_HDR_0
;
1422 strcat(mode2
, writing
? "w" : "r" );
1423 strcat(mode2
,"b"); /* binary mode */
1426 if (path
==NULL
|| strcmp(path
,"")==0) {
1427 fp
= (writing
? stdout
: stdin
);
1428 SET_BINARY_MODE(fp
);
1430 fp
= fopen(path
,mode2
);
1433 #ifdef BZ_STRICT_ANSI
1436 fp
= fdopen(fd
,mode2
);
1439 if (fp
== NULL
) return NULL
;
1442 /* Guard against total chaos and anarchy -- JRS */
1443 if (blockSize100k
< 1) blockSize100k
= 1;
1444 if (blockSize100k
> 9) blockSize100k
= 9;
1445 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1446 verbosity
,workFactor
);
1448 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1452 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1459 /*---------------------------------------------------*/
1461 open file for read or write.
1462 ex) bzopen("file","w9")
1463 case path="" or NULL => use stdin or stdout.
1465 BZFILE
* BZ_API(BZ2_bzopen
)
1469 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1473 /*---------------------------------------------------*/
1474 BZFILE
* BZ_API(BZ2_bzdopen
)
1478 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1482 /*---------------------------------------------------*/
1483 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1486 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1487 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1488 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1496 /*---------------------------------------------------*/
1497 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1501 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1510 /*---------------------------------------------------*/
1511 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1513 /* do nothing now... */
1518 /*---------------------------------------------------*/
1519 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1524 if (b
==NULL
) {return;}
1525 fp
= ((bzFile
*)b
)->handle
;
1526 if(((bzFile
*)b
)->writing
){
1527 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1529 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1532 BZ2_bzReadClose(&bzerr
,b
);
1534 if(fp
!=stdin
&& fp
!=stdout
){
1540 /*---------------------------------------------------*/
1542 return last error code
1544 static const char *bzerrorstrings
[] = {
1555 ,"???" /* for future */
1556 ,"???" /* for future */
1557 ,"???" /* for future */
1558 ,"???" /* for future */
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1564 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1566 int err
= ((bzFile
*)b
)->lastErr
;
1570 return bzerrorstrings
[err
*-1];
1574 #endif /* BZ_NO_COMPRESS */
1576 /*-------------------------------------------------------------*/
1577 /*--- end bzlib.c ---*/
1578 /*-------------------------------------------------------------*/