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 "bzlib_private.h"
34 /*---------------------------------------------------*/
35 /*--- Compression stuff ---*/
36 /*---------------------------------------------------*/
39 /*---------------------------------------------------*/
41 void BZ2_bz__AssertH__fail ( int errcode
)
44 "\n\nbzip2/libbzip2: internal error number %d.\n"
45 "This is a bug in bzip2/libbzip2, %s.\n"
46 "Please report it to me at: jseward@bzip.org. If this happened\n"
47 "when you were using some program which uses libbzip2 as a\n"
48 "component, you should also report this bug to the author(s)\n"
49 "of that program. Please make an effort to report this bug;\n"
50 "timely and accurate bug reports eventually lead to higher\n"
51 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
56 if (errcode
== 1007) {
58 "\n*** A special note about internal error number 1007 ***\n"
60 "Experience suggests that a common cause of i.e. 1007\n"
61 "is unreliable memory or other hardware. The 1007 assertion\n"
62 "just happens to cross-check the results of huge numbers of\n"
63 "memory reads/writes, and so acts (unintendedly) as a stress\n"
64 "test of your memory system.\n"
66 "I suggest the following: try compressing the file again,\n"
67 "possibly monitoring progress in detail with the -vv flag.\n"
69 "* If the error cannot be reproduced, and/or happens at different\n"
70 " points in compression, you may have a flaky memory system.\n"
71 " Try a memory-test program. I have used Memtest86\n"
72 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
73 " Memtest86 tests memory much more thorougly than your BIOSs\n"
74 " power-on test, and may find failures that the BIOS doesn't.\n"
76 "* If the error can be repeatably reproduced, this is a bug in\n"
77 " bzip2, and I would very much like to hear about it. Please\n"
78 " let me know, and, ideally, save a copy of the file causing the\n"
79 " problem -- without which I will be unable to investigate it.\n"
89 /*---------------------------------------------------*/
91 int bz_config_ok ( void )
93 if (sizeof(int) != 4) return 0;
94 if (sizeof(short) != 2) return 0;
95 if (sizeof(char) != 1) return 0;
100 /*---------------------------------------------------*/
102 void* default_bzalloc ( void* opaque
, Int32 items
, Int32 size
)
104 void* v
= malloc ( items
* size
);
109 void default_bzfree ( void* opaque
, void* addr
)
111 if (addr
!= NULL
) free ( addr
);
115 /*---------------------------------------------------*/
117 void prepare_new_block ( EState
* s
)
122 s
->state_out_pos
= 0;
123 BZ_INITIALISE_CRC ( s
->blockCRC
);
124 for (i
= 0; i
< 256; i
++) s
->inUse
[i
] = False
;
129 /*---------------------------------------------------*/
131 void init_RL ( EState
* s
)
133 s
->state_in_ch
= 256;
139 Bool
isempty_RL ( EState
* s
)
141 if (s
->state_in_ch
< 256 && s
->state_in_len
> 0)
147 /*---------------------------------------------------*/
148 int BZ_API(BZ2_bzCompressInit
)
157 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
160 blockSize100k
< 1 || blockSize100k
> 9 ||
161 workFactor
< 0 || workFactor
> 250)
162 return BZ_PARAM_ERROR
;
164 if (workFactor
== 0) workFactor
= 30;
165 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
166 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
168 s
= BZALLOC( sizeof(EState
) );
169 if (s
== NULL
) return BZ_MEM_ERROR
;
176 n
= 100000 * blockSize100k
;
177 s
->arr1
= BZALLOC( n
* sizeof(UInt32
) );
178 s
->arr2
= BZALLOC( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
179 s
->ftab
= BZALLOC( 65537 * sizeof(UInt32
) );
181 if (s
->arr1
== NULL
|| s
->arr2
== NULL
|| s
->ftab
== NULL
) {
182 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
183 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
184 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
185 if (s
!= NULL
) BZFREE(s
);
190 s
->state
= BZ_S_INPUT
;
191 s
->mode
= BZ_M_RUNNING
;
193 s
->blockSize100k
= blockSize100k
;
194 s
->nblockMAX
= 100000 * blockSize100k
- 19;
195 s
->verbosity
= verbosity
;
196 s
->workFactor
= workFactor
;
198 s
->block
= (UChar
*)s
->arr2
;
199 s
->mtfv
= (UInt16
*)s
->arr1
;
201 s
->ptr
= (UInt32
*)s
->arr1
;
204 strm
->total_in_lo32
= 0;
205 strm
->total_in_hi32
= 0;
206 strm
->total_out_lo32
= 0;
207 strm
->total_out_hi32
= 0;
209 prepare_new_block ( s
);
214 /*---------------------------------------------------*/
216 void add_pair_to_block ( EState
* s
)
219 UChar ch
= (UChar
)(s
->state_in_ch
);
220 for (i
= 0; i
< s
->state_in_len
; i
++) {
221 BZ_UPDATE_CRC( s
->blockCRC
, ch
);
223 s
->inUse
[s
->state_in_ch
] = True
;
224 switch (s
->state_in_len
) {
226 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
229 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
230 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
233 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
234 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
235 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
238 s
->inUse
[s
->state_in_len
-4] = True
;
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
++;
242 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
243 s
->block
[s
->nblock
] = ((UChar
)(s
->state_in_len
-4));
250 /*---------------------------------------------------*/
252 void flush_RL ( EState
* s
)
254 if (s
->state_in_ch
< 256) add_pair_to_block ( s
);
259 /*---------------------------------------------------*/
260 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
262 UInt32 zchh = (UInt32)(zchh0); \
263 /*-- fast track the common case --*/ \
264 if (zchh != zs->state_in_ch && \
265 zs->state_in_len == 1) { \
266 UChar ch = (UChar)(zs->state_in_ch); \
267 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
268 zs->inUse[zs->state_in_ch] = True; \
269 zs->block[zs->nblock] = (UChar)ch; \
271 zs->state_in_ch = zchh; \
274 /*-- general, uncommon cases --*/ \
275 if (zchh != zs->state_in_ch || \
276 zs->state_in_len == 255) { \
277 if (zs->state_in_ch < 256) \
278 add_pair_to_block ( zs ); \
279 zs->state_in_ch = zchh; \
280 zs->state_in_len = 1; \
282 zs->state_in_len++; \
287 /*---------------------------------------------------*/
289 Bool
copy_input_until_stop ( EState
* s
)
291 Bool progress_in
= False
;
293 if (s
->mode
== BZ_M_RUNNING
) {
295 /*-- fast track the common case --*/
297 /*-- block full? --*/
298 if (s
->nblock
>= s
->nblockMAX
) break;
300 if (s
->strm
->avail_in
== 0) break;
302 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
305 s
->strm
->total_in_lo32
++;
306 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
311 /*-- general, uncommon case --*/
313 /*-- block full? --*/
314 if (s
->nblock
>= s
->nblockMAX
) break;
316 if (s
->strm
->avail_in
== 0) break;
317 /*-- flush/finish end? --*/
318 if (s
->avail_in_expect
== 0) break;
320 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
323 s
->strm
->total_in_lo32
++;
324 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
325 s
->avail_in_expect
--;
332 /*---------------------------------------------------*/
334 Bool
copy_output_until_stop ( EState
* s
)
336 Bool progress_out
= False
;
340 /*-- no output space? --*/
341 if (s
->strm
->avail_out
== 0) break;
343 /*-- block done? --*/
344 if (s
->state_out_pos
>= s
->numZ
) break;
347 *(s
->strm
->next_out
) = s
->zbits
[s
->state_out_pos
];
349 s
->strm
->avail_out
--;
351 s
->strm
->total_out_lo32
++;
352 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
359 /*---------------------------------------------------*/
361 Bool
handle_compress ( bz_stream
* strm
)
363 Bool progress_in
= False
;
364 Bool progress_out
= False
;
365 EState
* s
= strm
->state
;
369 if (s
->state
== BZ_S_OUTPUT
) {
370 progress_out
|= copy_output_until_stop ( s
);
371 if (s
->state_out_pos
< s
->numZ
) break;
372 if (s
->mode
== BZ_M_FINISHING
&&
373 s
->avail_in_expect
== 0 &&
374 isempty_RL(s
)) break;
375 prepare_new_block ( s
);
376 s
->state
= BZ_S_INPUT
;
377 if (s
->mode
== BZ_M_FLUSHING
&&
378 s
->avail_in_expect
== 0 &&
379 isempty_RL(s
)) break;
382 if (s
->state
== BZ_S_INPUT
) {
383 progress_in
|= copy_input_until_stop ( s
);
384 if (s
->mode
!= BZ_M_RUNNING
&& s
->avail_in_expect
== 0) {
386 BZ2_compressBlock ( s
, (Bool
)(s
->mode
== BZ_M_FINISHING
) );
387 s
->state
= BZ_S_OUTPUT
;
390 if (s
->nblock
>= s
->nblockMAX
) {
391 BZ2_compressBlock ( s
, False
);
392 s
->state
= BZ_S_OUTPUT
;
395 if (s
->strm
->avail_in
== 0) {
402 return progress_in
|| progress_out
;
406 /*---------------------------------------------------*/
407 int BZ_API(BZ2_bzCompress
) ( bz_stream
*strm
, int action
)
411 if (strm
== NULL
) return BZ_PARAM_ERROR
;
413 if (s
== NULL
) return BZ_PARAM_ERROR
;
414 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
420 return BZ_SEQUENCE_ERROR
;
423 if (action
== BZ_RUN
) {
424 progress
= handle_compress ( strm
);
425 return progress
? BZ_RUN_OK
: BZ_PARAM_ERROR
;
428 if (action
== BZ_FLUSH
) {
429 s
->avail_in_expect
= strm
->avail_in
;
430 s
->mode
= BZ_M_FLUSHING
;
434 if (action
== BZ_FINISH
) {
435 s
->avail_in_expect
= strm
->avail_in
;
436 s
->mode
= BZ_M_FINISHING
;
440 return BZ_PARAM_ERROR
;
443 if (action
!= BZ_FLUSH
) return BZ_SEQUENCE_ERROR
;
444 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
445 return BZ_SEQUENCE_ERROR
;
446 progress
= handle_compress ( strm
);
447 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
448 s
->state_out_pos
< s
->numZ
) return BZ_FLUSH_OK
;
449 s
->mode
= BZ_M_RUNNING
;
453 if (action
!= BZ_FINISH
) return BZ_SEQUENCE_ERROR
;
454 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
455 return BZ_SEQUENCE_ERROR
;
456 progress
= handle_compress ( strm
);
457 if (!progress
) return BZ_SEQUENCE_ERROR
;
458 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
459 s
->state_out_pos
< s
->numZ
) return BZ_FINISH_OK
;
461 return BZ_STREAM_END
;
463 return BZ_OK
; /*--not reached--*/
467 /*---------------------------------------------------*/
468 int BZ_API(BZ2_bzCompressEnd
) ( bz_stream
*strm
)
471 if (strm
== NULL
) return BZ_PARAM_ERROR
;
473 if (s
== NULL
) return BZ_PARAM_ERROR
;
474 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
476 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
477 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
478 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
487 /*---------------------------------------------------*/
488 /*--- Decompression stuff ---*/
489 /*---------------------------------------------------*/
491 /*---------------------------------------------------*/
492 int BZ_API(BZ2_bzDecompressInit
)
499 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
501 if (strm
== NULL
) return BZ_PARAM_ERROR
;
502 if (small
!= 0 && small
!= 1) return BZ_PARAM_ERROR
;
503 if (verbosity
< 0 || verbosity
> 4) return BZ_PARAM_ERROR
;
505 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
506 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
508 s
= BZALLOC( sizeof(DState
) );
509 if (s
== NULL
) return BZ_MEM_ERROR
;
512 s
->state
= BZ_X_MAGIC_1
;
515 s
->calculatedCombinedCRC
= 0;
516 strm
->total_in_lo32
= 0;
517 strm
->total_in_hi32
= 0;
518 strm
->total_out_lo32
= 0;
519 strm
->total_out_hi32
= 0;
520 s
->smallDecompress
= (Bool
)small
;
525 s
->verbosity
= verbosity
;
531 /*---------------------------------------------------*/
532 /* Return True iff data corruption is discovered.
533 Returns False if there is no problem.
536 Bool
unRLE_obuf_to_output_FAST ( DState
* s
)
540 if (s
->blockRandomised
) {
543 /* try to finish existing run */
545 if (s
->strm
->avail_out
== 0) return False
;
546 if (s
->state_out_len
== 0) break;
547 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
548 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
551 s
->strm
->avail_out
--;
552 s
->strm
->total_out_lo32
++;
553 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
556 /* can a new run be started? */
557 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
559 /* Only caused by corrupt data stream? */
560 if (s
->nblock_used
> s
->save_nblock
+1)
563 s
->state_out_len
= 1;
564 s
->state_out_ch
= s
->k0
;
565 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
566 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
567 if (s
->nblock_used
== s
->save_nblock
+1) continue;
568 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
570 s
->state_out_len
= 2;
571 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
572 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
573 if (s
->nblock_used
== s
->save_nblock
+1) continue;
574 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
576 s
->state_out_len
= 3;
577 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
578 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
579 if (s
->nblock_used
== s
->save_nblock
+1) continue;
580 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
582 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
583 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
584 s
->state_out_len
= ((Int32
)k1
) + 4;
585 BZ_GET_FAST(s
->k0
); BZ_RAND_UPD_MASK
;
586 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
592 UInt32 c_calculatedBlockCRC
= s
->calculatedBlockCRC
;
593 UChar c_state_out_ch
= s
->state_out_ch
;
594 Int32 c_state_out_len
= s
->state_out_len
;
595 Int32 c_nblock_used
= s
->nblock_used
;
597 UInt32
* c_tt
= s
->tt
;
598 UInt32 c_tPos
= s
->tPos
;
599 char* cs_next_out
= s
->strm
->next_out
;
600 unsigned int cs_avail_out
= s
->strm
->avail_out
;
601 Int32 ro_blockSize100k
= s
->blockSize100k
;
604 UInt32 avail_out_INIT
= cs_avail_out
;
605 Int32 s_save_nblockPP
= s
->save_nblock
+1;
606 unsigned int total_out_lo32_old
;
610 /* try to finish existing run */
611 if (c_state_out_len
> 0) {
613 if (cs_avail_out
== 0) goto return_notr
;
614 if (c_state_out_len
== 1) break;
615 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
616 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
621 s_state_out_len_eq_one
:
623 if (cs_avail_out
== 0) {
624 c_state_out_len
= 1; goto return_notr
;
626 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
627 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
632 /* Only caused by corrupt data stream? */
633 if (c_nblock_used
> s_save_nblockPP
)
636 /* can a new run be started? */
637 if (c_nblock_used
== s_save_nblockPP
) {
638 c_state_out_len
= 0; goto return_notr
;
640 c_state_out_ch
= c_k0
;
641 BZ_GET_FAST_C(k1
); c_nblock_used
++;
643 c_k0
= k1
; goto s_state_out_len_eq_one
;
645 if (c_nblock_used
== s_save_nblockPP
)
646 goto s_state_out_len_eq_one
;
649 BZ_GET_FAST_C(k1
); c_nblock_used
++;
650 if (c_nblock_used
== s_save_nblockPP
) continue;
651 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
654 BZ_GET_FAST_C(k1
); c_nblock_used
++;
655 if (c_nblock_used
== s_save_nblockPP
) continue;
656 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
658 BZ_GET_FAST_C(k1
); c_nblock_used
++;
659 c_state_out_len
= ((Int32
)k1
) + 4;
660 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
664 total_out_lo32_old
= s
->strm
->total_out_lo32
;
665 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
666 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
667 s
->strm
->total_out_hi32
++;
670 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
671 s
->state_out_ch
= c_state_out_ch
;
672 s
->state_out_len
= c_state_out_len
;
673 s
->nblock_used
= c_nblock_used
;
677 s
->strm
->next_out
= cs_next_out
;
678 s
->strm
->avail_out
= cs_avail_out
;
686 /*---------------------------------------------------*/
687 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
693 mid
= (nb
+ na
) >> 1;
694 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
696 while (na
- nb
!= 1);
701 /*---------------------------------------------------*/
702 /* Return True iff data corruption is discovered.
703 Returns False if there is no problem.
706 Bool
unRLE_obuf_to_output_SMALL ( DState
* s
)
710 if (s
->blockRandomised
) {
713 /* try to finish existing run */
715 if (s
->strm
->avail_out
== 0) return False
;
716 if (s
->state_out_len
== 0) break;
717 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
718 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
721 s
->strm
->avail_out
--;
722 s
->strm
->total_out_lo32
++;
723 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
726 /* can a new run be started? */
727 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
729 /* Only caused by corrupt data stream? */
730 if (s
->nblock_used
> s
->save_nblock
+1)
733 s
->state_out_len
= 1;
734 s
->state_out_ch
= s
->k0
;
735 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
736 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
737 if (s
->nblock_used
== s
->save_nblock
+1) continue;
738 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
740 s
->state_out_len
= 2;
741 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
742 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
743 if (s
->nblock_used
== s
->save_nblock
+1) continue;
744 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
746 s
->state_out_len
= 3;
747 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
748 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
749 if (s
->nblock_used
== s
->save_nblock
+1) continue;
750 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
752 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
753 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
754 s
->state_out_len
= ((Int32
)k1
) + 4;
755 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
756 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
762 /* try to finish existing run */
764 if (s
->strm
->avail_out
== 0) return False
;
765 if (s
->state_out_len
== 0) break;
766 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
767 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
770 s
->strm
->avail_out
--;
771 s
->strm
->total_out_lo32
++;
772 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
775 /* can a new run be started? */
776 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
778 /* Only caused by corrupt data stream? */
779 if (s
->nblock_used
> s
->save_nblock
+1)
782 s
->state_out_len
= 1;
783 s
->state_out_ch
= s
->k0
;
784 BZ_GET_SMALL(k1
); s
->nblock_used
++;
785 if (s
->nblock_used
== s
->save_nblock
+1) continue;
786 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
788 s
->state_out_len
= 2;
789 BZ_GET_SMALL(k1
); s
->nblock_used
++;
790 if (s
->nblock_used
== s
->save_nblock
+1) continue;
791 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
793 s
->state_out_len
= 3;
794 BZ_GET_SMALL(k1
); s
->nblock_used
++;
795 if (s
->nblock_used
== s
->save_nblock
+1) continue;
796 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
798 BZ_GET_SMALL(k1
); s
->nblock_used
++;
799 s
->state_out_len
= ((Int32
)k1
) + 4;
800 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
807 /*---------------------------------------------------*/
808 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
812 if (strm
== NULL
) return BZ_PARAM_ERROR
;
814 if (s
== NULL
) return BZ_PARAM_ERROR
;
815 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
818 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
819 if (s
->state
== BZ_X_OUTPUT
) {
820 if (s
->smallDecompress
)
821 corrupt
= unRLE_obuf_to_output_SMALL ( s
); else
822 corrupt
= unRLE_obuf_to_output_FAST ( s
);
823 if (corrupt
) return BZ_DATA_ERROR
;
824 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
825 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
826 if (s
->verbosity
>= 3)
827 VPrintf2 ( " {0x%08x, 0x%08x}", s
->storedBlockCRC
,
828 s
->calculatedBlockCRC
);
829 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
830 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
831 return BZ_DATA_ERROR
;
832 s
->calculatedCombinedCRC
833 = (s
->calculatedCombinedCRC
<< 1) |
834 (s
->calculatedCombinedCRC
>> 31);
835 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
836 s
->state
= BZ_X_BLKHDR_1
;
841 if (s
->state
>= BZ_X_MAGIC_1
) {
842 Int32 r
= BZ2_decompress ( s
);
843 if (r
== BZ_STREAM_END
) {
844 if (s
->verbosity
>= 3)
845 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
846 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
847 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
848 return BZ_DATA_ERROR
;
851 if (s
->state
!= BZ_X_OUTPUT
) return r
;
857 return 0; /*NOTREACHED*/
861 /*---------------------------------------------------*/
862 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
865 if (strm
== NULL
) return BZ_PARAM_ERROR
;
867 if (s
== NULL
) return BZ_PARAM_ERROR
;
868 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
870 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
871 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
872 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
882 /*---------------------------------------------------*/
883 /*--- File I/O stuff ---*/
884 /*---------------------------------------------------*/
886 #define BZ_SETERR(eee) \
888 if (bzerror != NULL) *bzerror = eee; \
889 if (bzf != NULL) bzf->lastErr = eee; \
895 Char buf
[BZ_MAX_UNUSED
];
905 /*---------------------------------------------*/
906 static Bool
myfeof ( FILE* f
)
908 Int32 c
= fgetc ( f
);
909 if (c
== EOF
) return True
;
915 /*---------------------------------------------------*/
916 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
929 (blockSize100k
< 1 || blockSize100k
> 9) ||
930 (workFactor
< 0 || workFactor
> 250) ||
931 (verbosity
< 0 || verbosity
> 4))
932 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
935 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
937 bzf
= malloc ( sizeof(bzFile
) );
939 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
942 bzf
->initialisedOk
= False
;
946 bzf
->strm
.bzalloc
= NULL
;
947 bzf
->strm
.bzfree
= NULL
;
948 bzf
->strm
.opaque
= NULL
;
950 if (workFactor
== 0) workFactor
= 30;
951 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
952 verbosity
, workFactor
);
954 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
956 bzf
->strm
.avail_in
= 0;
957 bzf
->initialisedOk
= True
;
963 /*---------------------------------------------------*/
964 void BZ_API(BZ2_bzWrite
)
971 bzFile
* bzf
= (bzFile
*)b
;
974 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
975 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
977 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
978 if (ferror(bzf
->handle
))
979 { BZ_SETERR(BZ_IO_ERROR
); return; };
982 { BZ_SETERR(BZ_OK
); return; };
984 bzf
->strm
.avail_in
= len
;
985 bzf
->strm
.next_in
= buf
;
988 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
989 bzf
->strm
.next_out
= bzf
->buf
;
990 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
991 if (ret
!= BZ_RUN_OK
)
992 { BZ_SETERR(ret
); return; };
994 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
995 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
996 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
998 if (n
!= n2
|| ferror(bzf
->handle
))
999 { BZ_SETERR(BZ_IO_ERROR
); return; };
1002 if (bzf
->strm
.avail_in
== 0)
1003 { BZ_SETERR(BZ_OK
); return; };
1008 /*---------------------------------------------------*/
1009 void BZ_API(BZ2_bzWriteClose
)
1013 unsigned int* nbytes_in
,
1014 unsigned int* nbytes_out
)
1016 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1017 nbytes_in
, NULL
, nbytes_out
, NULL
);
1021 void BZ_API(BZ2_bzWriteClose64
)
1025 unsigned int* nbytes_in_lo32
,
1026 unsigned int* nbytes_in_hi32
,
1027 unsigned int* nbytes_out_lo32
,
1028 unsigned int* nbytes_out_hi32
)
1031 bzFile
* bzf
= (bzFile
*)b
;
1034 { BZ_SETERR(BZ_OK
); return; };
1035 if (!(bzf
->writing
))
1036 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1037 if (ferror(bzf
->handle
))
1038 { BZ_SETERR(BZ_IO_ERROR
); return; };
1040 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1041 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1042 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1043 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1045 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1047 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1048 bzf
->strm
.next_out
= bzf
->buf
;
1049 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1050 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1051 { BZ_SETERR(ret
); return; };
1053 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1054 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1055 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1057 if (n
!= n2
|| ferror(bzf
->handle
))
1058 { BZ_SETERR(BZ_IO_ERROR
); return; };
1061 if (ret
== BZ_STREAM_END
) break;
1065 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1066 fflush ( bzf
->handle
);
1067 if (ferror(bzf
->handle
))
1068 { BZ_SETERR(BZ_IO_ERROR
); return; };
1071 if (nbytes_in_lo32
!= NULL
)
1072 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1073 if (nbytes_in_hi32
!= NULL
)
1074 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1075 if (nbytes_out_lo32
!= NULL
)
1076 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1077 if (nbytes_out_hi32
!= NULL
)
1078 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1081 BZ2_bzCompressEnd ( &(bzf
->strm
) );
1086 /*---------------------------------------------------*/
1087 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1101 (small
!= 0 && small
!= 1) ||
1102 (verbosity
< 0 || verbosity
> 4) ||
1103 (unused
== NULL
&& nUnused
!= 0) ||
1104 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1105 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1108 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1110 bzf
= malloc ( sizeof(bzFile
) );
1112 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1116 bzf
->initialisedOk
= False
;
1119 bzf
->writing
= False
;
1120 bzf
->strm
.bzalloc
= NULL
;
1121 bzf
->strm
.bzfree
= NULL
;
1122 bzf
->strm
.opaque
= NULL
;
1124 while (nUnused
> 0) {
1125 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1126 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1130 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1132 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1134 bzf
->strm
.avail_in
= bzf
->bufN
;
1135 bzf
->strm
.next_in
= bzf
->buf
;
1137 bzf
->initialisedOk
= True
;
1142 /*---------------------------------------------------*/
1143 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1145 bzFile
* bzf
= (bzFile
*)b
;
1149 { BZ_SETERR(BZ_OK
); return; };
1152 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1154 if (bzf
->initialisedOk
)
1155 (void)BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1160 /*---------------------------------------------------*/
1161 int BZ_API(BZ2_bzRead
)
1168 bzFile
* bzf
= (bzFile
*)b
;
1172 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1173 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1176 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1179 { BZ_SETERR(BZ_OK
); return 0; };
1181 bzf
->strm
.avail_out
= len
;
1182 bzf
->strm
.next_out
= buf
;
1186 if (ferror(bzf
->handle
))
1187 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1189 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1190 n
= fread ( bzf
->buf
, sizeof(UChar
),
1191 BZ_MAX_UNUSED
, bzf
->handle
);
1192 if (ferror(bzf
->handle
))
1193 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1195 bzf
->strm
.avail_in
= bzf
->bufN
;
1196 bzf
->strm
.next_in
= bzf
->buf
;
1199 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1201 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1202 { BZ_SETERR(ret
); return 0; };
1204 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1205 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1206 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1208 if (ret
== BZ_STREAM_END
)
1209 { BZ_SETERR(BZ_STREAM_END
);
1210 return len
- bzf
->strm
.avail_out
; };
1211 if (bzf
->strm
.avail_out
== 0)
1212 { BZ_SETERR(BZ_OK
); return len
; };
1216 return 0; /*not reached*/
1220 /*---------------------------------------------------*/
1221 void BZ_API(BZ2_bzReadGetUnused
)
1227 bzFile
* bzf
= (bzFile
*)b
;
1229 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1230 if (bzf
->lastErr
!= BZ_STREAM_END
)
1231 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1232 if (unused
== NULL
|| nUnused
== NULL
)
1233 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1236 *nUnused
= bzf
->strm
.avail_in
;
1237 *unused
= bzf
->strm
.next_in
;
1242 /*---------------------------------------------------*/
1243 /*--- Misc convenience stuff ---*/
1244 /*---------------------------------------------------*/
1246 /*---------------------------------------------------*/
1247 int BZ_API(BZ2_bzBuffToBuffCompress
)
1249 unsigned int* destLen
,
1251 unsigned int sourceLen
,
1259 if (dest
== NULL
|| destLen
== NULL
||
1261 blockSize100k
< 1 || blockSize100k
> 9 ||
1262 verbosity
< 0 || verbosity
> 4 ||
1263 workFactor
< 0 || workFactor
> 250)
1264 return BZ_PARAM_ERROR
;
1266 if (workFactor
== 0) workFactor
= 30;
1267 strm
.bzalloc
= NULL
;
1270 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1271 verbosity
, workFactor
);
1272 if (ret
!= BZ_OK
) return ret
;
1274 strm
.next_in
= source
;
1275 strm
.next_out
= dest
;
1276 strm
.avail_in
= sourceLen
;
1277 strm
.avail_out
= *destLen
;
1279 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1280 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1281 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1283 /* normal termination */
1284 *destLen
-= strm
.avail_out
;
1285 BZ2_bzCompressEnd ( &strm
);
1289 BZ2_bzCompressEnd ( &strm
);
1290 return BZ_OUTBUFF_FULL
;
1293 BZ2_bzCompressEnd ( &strm
);
1298 /*---------------------------------------------------*/
1299 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1301 unsigned int* destLen
,
1303 unsigned int sourceLen
,
1310 if (dest
== NULL
|| destLen
== NULL
||
1312 (small
!= 0 && small
!= 1) ||
1313 verbosity
< 0 || verbosity
> 4)
1314 return BZ_PARAM_ERROR
;
1316 strm
.bzalloc
= NULL
;
1319 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1320 if (ret
!= BZ_OK
) return ret
;
1322 strm
.next_in
= source
;
1323 strm
.next_out
= dest
;
1324 strm
.avail_in
= sourceLen
;
1325 strm
.avail_out
= *destLen
;
1327 ret
= BZ2_bzDecompress ( &strm
);
1328 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1329 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1331 /* normal termination */
1332 *destLen
-= strm
.avail_out
;
1333 BZ2_bzDecompressEnd ( &strm
);
1336 output_overflow_or_eof
:
1337 if (strm
.avail_out
> 0) {
1338 BZ2_bzDecompressEnd ( &strm
);
1339 return BZ_UNEXPECTED_EOF
;
1341 BZ2_bzDecompressEnd ( &strm
);
1342 return BZ_OUTBUFF_FULL
;
1346 BZ2_bzDecompressEnd ( &strm
);
1351 /*---------------------------------------------------*/
1353 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1354 to support better zlib compatibility.
1355 This code is not _officially_ part of libbzip2 (yet);
1356 I haven't tested it, documented it, or considered the
1357 threading-safeness of it.
1358 If this code breaks, please contact both Yoshioka and me.
1360 /*---------------------------------------------------*/
1362 /*---------------------------------------------------*/
1364 return version like "0.9.5d, 4-Sept-1999".
1366 const char * BZ_API(BZ2_bzlibVersion
)(void)
1373 /*---------------------------------------------------*/
1375 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1378 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1380 # define SET_BINARY_MODE(file)
1383 BZFILE
* bzopen_or_bzdopen
1384 ( const char *path
, /* no use when bzdopen */
1385 int fd
, /* no use when bzdopen */
1387 int open_mode
) /* bzopen: 0, bzdopen:1 */
1390 char unused
[BZ_MAX_UNUSED
];
1391 int blockSize100k
= 9;
1393 char mode2
[10] = "";
1395 BZFILE
*bzfp
= NULL
;
1397 int workFactor
= 30;
1401 if (mode
== NULL
) return NULL
;
1409 smallMode
= 1; break;
1411 if (isdigit((int)(*mode
))) {
1412 blockSize100k
= *mode
-BZ_HDR_0
;
1417 strcat(mode2
, writing
? "w" : "r" );
1418 strcat(mode2
,"b"); /* binary mode */
1421 if (path
==NULL
|| strcmp(path
,"")==0) {
1422 fp
= (writing
? stdout
: stdin
);
1423 SET_BINARY_MODE(fp
);
1425 fp
= fopen(path
,mode2
);
1428 #ifdef BZ_STRICT_ANSI
1431 fp
= fdopen(fd
,mode2
);
1434 if (fp
== NULL
) return NULL
;
1437 /* Guard against total chaos and anarchy -- JRS */
1438 if (blockSize100k
< 1) blockSize100k
= 1;
1439 if (blockSize100k
> 9) blockSize100k
= 9;
1440 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1441 verbosity
,workFactor
);
1443 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1447 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1454 /*---------------------------------------------------*/
1456 open file for read or write.
1457 ex) bzopen("file","w9")
1458 case path="" or NULL => use stdin or stdout.
1460 BZFILE
* BZ_API(BZ2_bzopen
)
1464 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1468 /*---------------------------------------------------*/
1469 BZFILE
* BZ_API(BZ2_bzdopen
)
1473 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1477 /*---------------------------------------------------*/
1478 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1481 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1482 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1483 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1491 /*---------------------------------------------------*/
1492 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1496 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1505 /*---------------------------------------------------*/
1506 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1508 /* do nothing now... */
1513 /*---------------------------------------------------*/
1514 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1519 if (b
==NULL
) {return;}
1520 fp
= ((bzFile
*)b
)->handle
;
1521 if(((bzFile
*)b
)->writing
){
1522 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1524 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1527 BZ2_bzReadClose(&bzerr
,b
);
1529 if(fp
!=stdin
&& fp
!=stdout
){
1535 /*---------------------------------------------------*/
1537 return last error code
1539 static const char *bzerrorstrings
[] = {
1550 ,"???" /* for future */
1551 ,"???" /* for future */
1552 ,"???" /* for future */
1553 ,"???" /* for future */
1554 ,"???" /* for future */
1555 ,"???" /* for future */
1559 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1561 int err
= ((bzFile
*)b
)->lastErr
;
1565 return bzerrorstrings
[err
*-1];
1570 /*-------------------------------------------------------------*/
1571 /*--- end bzlib.c ---*/
1572 /*-------------------------------------------------------------*/