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.4 of 20 December 2006
12 Copyright (C) 1996-2006 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, 15 February 2005.\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
;
603 UInt32 avail_out_INIT
= cs_avail_out
;
604 Int32 s_save_nblockPP
= s
->save_nblock
+1;
605 unsigned int total_out_lo32_old
;
609 /* try to finish existing run */
610 if (c_state_out_len
> 0) {
612 if (cs_avail_out
== 0) goto return_notr
;
613 if (c_state_out_len
== 1) break;
614 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
615 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
620 s_state_out_len_eq_one
:
622 if (cs_avail_out
== 0) {
623 c_state_out_len
= 1; goto return_notr
;
625 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
626 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
631 /* Only caused by corrupt data stream? */
632 if (c_nblock_used
> s_save_nblockPP
)
635 /* can a new run be started? */
636 if (c_nblock_used
== s_save_nblockPP
) {
637 c_state_out_len
= 0; goto return_notr
;
639 c_state_out_ch
= c_k0
;
640 BZ_GET_FAST_C(k1
); c_nblock_used
++;
642 c_k0
= k1
; goto s_state_out_len_eq_one
;
644 if (c_nblock_used
== s_save_nblockPP
)
645 goto s_state_out_len_eq_one
;
648 BZ_GET_FAST_C(k1
); c_nblock_used
++;
649 if (c_nblock_used
== s_save_nblockPP
) continue;
650 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
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; };
657 BZ_GET_FAST_C(k1
); c_nblock_used
++;
658 c_state_out_len
= ((Int32
)k1
) + 4;
659 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
663 total_out_lo32_old
= s
->strm
->total_out_lo32
;
664 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
665 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
666 s
->strm
->total_out_hi32
++;
669 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
670 s
->state_out_ch
= c_state_out_ch
;
671 s
->state_out_len
= c_state_out_len
;
672 s
->nblock_used
= c_nblock_used
;
676 s
->strm
->next_out
= cs_next_out
;
677 s
->strm
->avail_out
= cs_avail_out
;
685 /*---------------------------------------------------*/
686 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
692 mid
= (nb
+ na
) >> 1;
693 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
695 while (na
- nb
!= 1);
700 /*---------------------------------------------------*/
701 /* Return True iff data corruption is discovered.
702 Returns False if there is no problem.
705 Bool
unRLE_obuf_to_output_SMALL ( DState
* s
)
709 if (s
->blockRandomised
) {
712 /* try to finish existing run */
714 if (s
->strm
->avail_out
== 0) return False
;
715 if (s
->state_out_len
== 0) break;
716 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
717 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
720 s
->strm
->avail_out
--;
721 s
->strm
->total_out_lo32
++;
722 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
725 /* can a new run be started? */
726 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
728 /* Only caused by corrupt data stream? */
729 if (s
->nblock_used
> s
->save_nblock
+1)
732 s
->state_out_len
= 1;
733 s
->state_out_ch
= s
->k0
;
734 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
735 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
736 if (s
->nblock_used
== s
->save_nblock
+1) continue;
737 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
739 s
->state_out_len
= 2;
740 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
741 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
742 if (s
->nblock_used
== s
->save_nblock
+1) continue;
743 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
745 s
->state_out_len
= 3;
746 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
747 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
748 if (s
->nblock_used
== s
->save_nblock
+1) continue;
749 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
751 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
752 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
753 s
->state_out_len
= ((Int32
)k1
) + 4;
754 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
755 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
761 /* try to finish existing run */
763 if (s
->strm
->avail_out
== 0) return False
;
764 if (s
->state_out_len
== 0) break;
765 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
766 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
769 s
->strm
->avail_out
--;
770 s
->strm
->total_out_lo32
++;
771 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
774 /* can a new run be started? */
775 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
777 /* Only caused by corrupt data stream? */
778 if (s
->nblock_used
> s
->save_nblock
+1)
781 s
->state_out_len
= 1;
782 s
->state_out_ch
= s
->k0
;
783 BZ_GET_SMALL(k1
); s
->nblock_used
++;
784 if (s
->nblock_used
== s
->save_nblock
+1) continue;
785 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
787 s
->state_out_len
= 2;
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
= 3;
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 BZ_GET_SMALL(k1
); s
->nblock_used
++;
798 s
->state_out_len
= ((Int32
)k1
) + 4;
799 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
806 /*---------------------------------------------------*/
807 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
811 if (strm
== NULL
) return BZ_PARAM_ERROR
;
813 if (s
== NULL
) return BZ_PARAM_ERROR
;
814 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
817 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
818 if (s
->state
== BZ_X_OUTPUT
) {
819 if (s
->smallDecompress
)
820 corrupt
= unRLE_obuf_to_output_SMALL ( s
); else
821 corrupt
= unRLE_obuf_to_output_FAST ( s
);
822 if (corrupt
) return BZ_DATA_ERROR
;
823 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
824 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
825 if (s
->verbosity
>= 3)
826 VPrintf2 ( " {0x%08x, 0x%08x}", s
->storedBlockCRC
,
827 s
->calculatedBlockCRC
);
828 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
829 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
830 return BZ_DATA_ERROR
;
831 s
->calculatedCombinedCRC
832 = (s
->calculatedCombinedCRC
<< 1) |
833 (s
->calculatedCombinedCRC
>> 31);
834 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
835 s
->state
= BZ_X_BLKHDR_1
;
840 if (s
->state
>= BZ_X_MAGIC_1
) {
841 Int32 r
= BZ2_decompress ( s
);
842 if (r
== BZ_STREAM_END
) {
843 if (s
->verbosity
>= 3)
844 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
845 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
846 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
847 return BZ_DATA_ERROR
;
850 if (s
->state
!= BZ_X_OUTPUT
) return r
;
856 return 0; /*NOTREACHED*/
860 /*---------------------------------------------------*/
861 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
864 if (strm
== NULL
) return BZ_PARAM_ERROR
;
866 if (s
== NULL
) return BZ_PARAM_ERROR
;
867 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
869 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
870 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
871 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
881 /*---------------------------------------------------*/
882 /*--- File I/O stuff ---*/
883 /*---------------------------------------------------*/
885 #define BZ_SETERR(eee) \
887 if (bzerror != NULL) *bzerror = eee; \
888 if (bzf != NULL) bzf->lastErr = eee; \
894 Char buf
[BZ_MAX_UNUSED
];
904 /*---------------------------------------------*/
905 static Bool
myfeof ( FILE* f
)
907 Int32 c
= fgetc ( f
);
908 if (c
== EOF
) return True
;
914 /*---------------------------------------------------*/
915 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
928 (blockSize100k
< 1 || blockSize100k
> 9) ||
929 (workFactor
< 0 || workFactor
> 250) ||
930 (verbosity
< 0 || verbosity
> 4))
931 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
934 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
936 bzf
= malloc ( sizeof(bzFile
) );
938 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
941 bzf
->initialisedOk
= False
;
945 bzf
->strm
.bzalloc
= NULL
;
946 bzf
->strm
.bzfree
= NULL
;
947 bzf
->strm
.opaque
= NULL
;
949 if (workFactor
== 0) workFactor
= 30;
950 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
951 verbosity
, workFactor
);
953 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
955 bzf
->strm
.avail_in
= 0;
956 bzf
->initialisedOk
= True
;
962 /*---------------------------------------------------*/
963 void BZ_API(BZ2_bzWrite
)
970 bzFile
* bzf
= (bzFile
*)b
;
973 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
974 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
976 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
977 if (ferror(bzf
->handle
))
978 { BZ_SETERR(BZ_IO_ERROR
); return; };
981 { BZ_SETERR(BZ_OK
); return; };
983 bzf
->strm
.avail_in
= len
;
984 bzf
->strm
.next_in
= buf
;
987 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
988 bzf
->strm
.next_out
= bzf
->buf
;
989 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
990 if (ret
!= BZ_RUN_OK
)
991 { BZ_SETERR(ret
); return; };
993 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
994 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
995 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
997 if (n
!= n2
|| ferror(bzf
->handle
))
998 { BZ_SETERR(BZ_IO_ERROR
); return; };
1001 if (bzf
->strm
.avail_in
== 0)
1002 { BZ_SETERR(BZ_OK
); return; };
1007 /*---------------------------------------------------*/
1008 void BZ_API(BZ2_bzWriteClose
)
1012 unsigned int* nbytes_in
,
1013 unsigned int* nbytes_out
)
1015 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1016 nbytes_in
, NULL
, nbytes_out
, NULL
);
1020 void BZ_API(BZ2_bzWriteClose64
)
1024 unsigned int* nbytes_in_lo32
,
1025 unsigned int* nbytes_in_hi32
,
1026 unsigned int* nbytes_out_lo32
,
1027 unsigned int* nbytes_out_hi32
)
1030 bzFile
* bzf
= (bzFile
*)b
;
1033 { BZ_SETERR(BZ_OK
); return; };
1034 if (!(bzf
->writing
))
1035 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1036 if (ferror(bzf
->handle
))
1037 { BZ_SETERR(BZ_IO_ERROR
); return; };
1039 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1040 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1041 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1042 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1044 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1046 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1047 bzf
->strm
.next_out
= bzf
->buf
;
1048 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1049 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1050 { BZ_SETERR(ret
); return; };
1052 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1053 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1054 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1056 if (n
!= n2
|| ferror(bzf
->handle
))
1057 { BZ_SETERR(BZ_IO_ERROR
); return; };
1060 if (ret
== BZ_STREAM_END
) break;
1064 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1065 fflush ( bzf
->handle
);
1066 if (ferror(bzf
->handle
))
1067 { BZ_SETERR(BZ_IO_ERROR
); return; };
1070 if (nbytes_in_lo32
!= NULL
)
1071 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1072 if (nbytes_in_hi32
!= NULL
)
1073 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1074 if (nbytes_out_lo32
!= NULL
)
1075 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1076 if (nbytes_out_hi32
!= NULL
)
1077 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1080 BZ2_bzCompressEnd ( &(bzf
->strm
) );
1085 /*---------------------------------------------------*/
1086 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1100 (small
!= 0 && small
!= 1) ||
1101 (verbosity
< 0 || verbosity
> 4) ||
1102 (unused
== NULL
&& nUnused
!= 0) ||
1103 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1104 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1107 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1109 bzf
= malloc ( sizeof(bzFile
) );
1111 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1115 bzf
->initialisedOk
= False
;
1118 bzf
->writing
= False
;
1119 bzf
->strm
.bzalloc
= NULL
;
1120 bzf
->strm
.bzfree
= NULL
;
1121 bzf
->strm
.opaque
= NULL
;
1123 while (nUnused
> 0) {
1124 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1125 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1129 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1131 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1133 bzf
->strm
.avail_in
= bzf
->bufN
;
1134 bzf
->strm
.next_in
= bzf
->buf
;
1136 bzf
->initialisedOk
= True
;
1141 /*---------------------------------------------------*/
1142 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1144 bzFile
* bzf
= (bzFile
*)b
;
1148 { BZ_SETERR(BZ_OK
); return; };
1151 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1153 if (bzf
->initialisedOk
)
1154 (void)BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1159 /*---------------------------------------------------*/
1160 int BZ_API(BZ2_bzRead
)
1167 bzFile
* bzf
= (bzFile
*)b
;
1171 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1172 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1175 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1178 { BZ_SETERR(BZ_OK
); return 0; };
1180 bzf
->strm
.avail_out
= len
;
1181 bzf
->strm
.next_out
= buf
;
1185 if (ferror(bzf
->handle
))
1186 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1188 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1189 n
= fread ( bzf
->buf
, sizeof(UChar
),
1190 BZ_MAX_UNUSED
, bzf
->handle
);
1191 if (ferror(bzf
->handle
))
1192 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1194 bzf
->strm
.avail_in
= bzf
->bufN
;
1195 bzf
->strm
.next_in
= bzf
->buf
;
1198 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1200 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1201 { BZ_SETERR(ret
); return 0; };
1203 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1204 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1205 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1207 if (ret
== BZ_STREAM_END
)
1208 { BZ_SETERR(BZ_STREAM_END
);
1209 return len
- bzf
->strm
.avail_out
; };
1210 if (bzf
->strm
.avail_out
== 0)
1211 { BZ_SETERR(BZ_OK
); return len
; };
1215 return 0; /*not reached*/
1219 /*---------------------------------------------------*/
1220 void BZ_API(BZ2_bzReadGetUnused
)
1226 bzFile
* bzf
= (bzFile
*)b
;
1228 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1229 if (bzf
->lastErr
!= BZ_STREAM_END
)
1230 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1231 if (unused
== NULL
|| nUnused
== NULL
)
1232 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1235 *nUnused
= bzf
->strm
.avail_in
;
1236 *unused
= bzf
->strm
.next_in
;
1241 /*---------------------------------------------------*/
1242 /*--- Misc convenience stuff ---*/
1243 /*---------------------------------------------------*/
1245 /*---------------------------------------------------*/
1246 int BZ_API(BZ2_bzBuffToBuffCompress
)
1248 unsigned int* destLen
,
1250 unsigned int sourceLen
,
1258 if (dest
== NULL
|| destLen
== NULL
||
1260 blockSize100k
< 1 || blockSize100k
> 9 ||
1261 verbosity
< 0 || verbosity
> 4 ||
1262 workFactor
< 0 || workFactor
> 250)
1263 return BZ_PARAM_ERROR
;
1265 if (workFactor
== 0) workFactor
= 30;
1266 strm
.bzalloc
= NULL
;
1269 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1270 verbosity
, workFactor
);
1271 if (ret
!= BZ_OK
) return ret
;
1273 strm
.next_in
= source
;
1274 strm
.next_out
= dest
;
1275 strm
.avail_in
= sourceLen
;
1276 strm
.avail_out
= *destLen
;
1278 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1279 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1280 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1282 /* normal termination */
1283 *destLen
-= strm
.avail_out
;
1284 BZ2_bzCompressEnd ( &strm
);
1288 BZ2_bzCompressEnd ( &strm
);
1289 return BZ_OUTBUFF_FULL
;
1292 BZ2_bzCompressEnd ( &strm
);
1297 /*---------------------------------------------------*/
1298 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1300 unsigned int* destLen
,
1302 unsigned int sourceLen
,
1309 if (dest
== NULL
|| destLen
== NULL
||
1311 (small
!= 0 && small
!= 1) ||
1312 verbosity
< 0 || verbosity
> 4)
1313 return BZ_PARAM_ERROR
;
1315 strm
.bzalloc
= NULL
;
1318 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1319 if (ret
!= BZ_OK
) return ret
;
1321 strm
.next_in
= source
;
1322 strm
.next_out
= dest
;
1323 strm
.avail_in
= sourceLen
;
1324 strm
.avail_out
= *destLen
;
1326 ret
= BZ2_bzDecompress ( &strm
);
1327 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1328 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1330 /* normal termination */
1331 *destLen
-= strm
.avail_out
;
1332 BZ2_bzDecompressEnd ( &strm
);
1335 output_overflow_or_eof
:
1336 if (strm
.avail_out
> 0) {
1337 BZ2_bzDecompressEnd ( &strm
);
1338 return BZ_UNEXPECTED_EOF
;
1340 BZ2_bzDecompressEnd ( &strm
);
1341 return BZ_OUTBUFF_FULL
;
1345 BZ2_bzDecompressEnd ( &strm
);
1350 /*---------------------------------------------------*/
1352 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1353 to support better zlib compatibility.
1354 This code is not _officially_ part of libbzip2 (yet);
1355 I haven't tested it, documented it, or considered the
1356 threading-safeness of it.
1357 If this code breaks, please contact both Yoshioka and me.
1359 /*---------------------------------------------------*/
1361 /*---------------------------------------------------*/
1363 return version like "0.9.5d, 4-Sept-1999".
1365 const char * BZ_API(BZ2_bzlibVersion
)(void)
1372 /*---------------------------------------------------*/
1374 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1377 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1379 # define SET_BINARY_MODE(file)
1382 BZFILE
* bzopen_or_bzdopen
1383 ( const char *path
, /* no use when bzdopen */
1384 int fd
, /* no use when bzdopen */
1386 int open_mode
) /* bzopen: 0, bzdopen:1 */
1389 char unused
[BZ_MAX_UNUSED
];
1390 int blockSize100k
= 9;
1392 char mode2
[10] = "";
1394 BZFILE
*bzfp
= NULL
;
1396 int workFactor
= 30;
1400 if (mode
== NULL
) return NULL
;
1408 smallMode
= 1; break;
1410 if (isdigit((int)(*mode
))) {
1411 blockSize100k
= *mode
-BZ_HDR_0
;
1416 strcat(mode2
, writing
? "w" : "r" );
1417 strcat(mode2
,"b"); /* binary mode */
1420 if (path
==NULL
|| strcmp(path
,"")==0) {
1421 fp
= (writing
? stdout
: stdin
);
1422 SET_BINARY_MODE(fp
);
1424 fp
= fopen(path
,mode2
);
1427 #ifdef BZ_STRICT_ANSI
1430 fp
= fdopen(fd
,mode2
);
1433 if (fp
== NULL
) return NULL
;
1436 /* Guard against total chaos and anarchy -- JRS */
1437 if (blockSize100k
< 1) blockSize100k
= 1;
1438 if (blockSize100k
> 9) blockSize100k
= 9;
1439 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1440 verbosity
,workFactor
);
1442 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1446 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1453 /*---------------------------------------------------*/
1455 open file for read or write.
1456 ex) bzopen("file","w9")
1457 case path="" or NULL => use stdin or stdout.
1459 BZFILE
* BZ_API(BZ2_bzopen
)
1463 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1467 /*---------------------------------------------------*/
1468 BZFILE
* BZ_API(BZ2_bzdopen
)
1472 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1476 /*---------------------------------------------------*/
1477 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1480 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1481 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1482 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1490 /*---------------------------------------------------*/
1491 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1495 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1504 /*---------------------------------------------------*/
1505 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1507 /* do nothing now... */
1512 /*---------------------------------------------------*/
1513 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1518 if (b
==NULL
) {return;}
1519 fp
= ((bzFile
*)b
)->handle
;
1520 if(((bzFile
*)b
)->writing
){
1521 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1523 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1526 BZ2_bzReadClose(&bzerr
,b
);
1528 if(fp
!=stdin
&& fp
!=stdout
){
1534 /*---------------------------------------------------*/
1536 return last error code
1538 static const char *bzerrorstrings
[] = {
1549 ,"???" /* for future */
1550 ,"???" /* for future */
1551 ,"???" /* for future */
1552 ,"???" /* for future */
1553 ,"???" /* for future */
1554 ,"???" /* for future */
1558 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1560 int err
= ((bzFile
*)b
)->lastErr
;
1564 return bzerrorstrings
[err
*-1];
1569 /*-------------------------------------------------------------*/
1570 /*--- end bzlib.c ---*/
1571 /*-------------------------------------------------------------*/