1 /* $NetBSD: bzlib.c,v 1.4 2008/03/18 14:47:07 christos Exp $ */
4 /*-------------------------------------------------------------*/
5 /*--- Library top-level functions. ---*/
7 /*-------------------------------------------------------------*/
9 /* ------------------------------------------------------------------
10 This file is part of bzip2/libbzip2, a program and library for
11 lossless, block-sorting data compression.
13 bzip2/libbzip2 version 1.0.5 of 10 December 2007
14 Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
16 Please read the WARNING, DISCLAIMER and PATENTS sections in the
19 This program is released under the terms of the license contained
21 ------------------------------------------------------------------ */
24 0.9.0 -- original version.
25 0.9.0a/b -- no changes in this file.
26 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress().
27 fixed bzWrite/bzRead to ignore zero-length requests.
28 fixed bzread to correctly handle read requests after EOF.
29 wrong parameter order in call to bzDecompressInit in
30 bzBuffToBuffDecompress. Fixed.
33 #include "bzlib_private.h"
36 /*---------------------------------------------------*/
37 /*--- Compression stuff ---*/
38 /*---------------------------------------------------*/
41 /*---------------------------------------------------*/
43 void BZ2_bz__AssertH__fail ( int errcode
)
46 "\n\nbzip2/libbzip2: internal error number %d.\n"
47 "This is a bug in bzip2/libbzip2, %s.\n"
48 "Please report it to me at: jseward@bzip.org. If this happened\n"
49 "when you were using some program which uses libbzip2 as a\n"
50 "component, you should also report this bug to the author(s)\n"
51 "of that program. Please make an effort to report this bug;\n"
52 "timely and accurate bug reports eventually lead to higher\n"
53 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
58 if (errcode
== 1007) {
60 "\n*** A special note about internal error number 1007 ***\n"
62 "Experience suggests that a common cause of i.e. 1007\n"
63 "is unreliable memory or other hardware. The 1007 assertion\n"
64 "just happens to cross-check the results of huge numbers of\n"
65 "memory reads/writes, and so acts (unintendedly) as a stress\n"
66 "test of your memory system.\n"
68 "I suggest the following: try compressing the file again,\n"
69 "possibly monitoring progress in detail with the -vv flag.\n"
71 "* If the error cannot be reproduced, and/or happens at different\n"
72 " points in compression, you may have a flaky memory system.\n"
73 " Try a memory-test program. I have used Memtest86\n"
74 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
75 " Memtest86 tests memory much more thorougly than your BIOSs\n"
76 " power-on test, and may find failures that the BIOS doesn't.\n"
78 "* If the error can be repeatably reproduced, this is a bug in\n"
79 " bzip2, and I would very much like to hear about it. Please\n"
80 " let me know, and, ideally, save a copy of the file causing the\n"
81 " problem -- without which I will be unable to investigate it.\n"
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
);
117 /*---------------------------------------------------*/
119 void prepare_new_block ( EState
* s
)
124 s
->state_out_pos
= 0;
125 BZ_INITIALISE_CRC ( s
->blockCRC
);
126 for (i
= 0; i
< 256; i
++) s
->inUse
[i
] = False
;
131 /*---------------------------------------------------*/
133 void init_RL ( EState
* s
)
135 s
->state_in_ch
= 256;
141 Bool
isempty_RL ( EState
* s
)
143 if (s
->state_in_ch
< 256 && s
->state_in_len
> 0)
149 /*---------------------------------------------------*/
150 int BZ_API(BZ2_bzCompressInit
)
159 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
162 blockSize100k
< 1 || blockSize100k
> 9 ||
163 workFactor
< 0 || workFactor
> 250)
164 return BZ_PARAM_ERROR
;
166 if (workFactor
== 0) workFactor
= 30;
167 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
168 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
170 s
= BZALLOC( sizeof(EState
) );
171 if (s
== NULL
) return BZ_MEM_ERROR
;
178 n
= 100000 * blockSize100k
;
179 s
->arr1
= BZALLOC( n
* sizeof(UInt32
) );
180 s
->arr2
= BZALLOC( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
181 s
->ftab
= BZALLOC( 65537 * sizeof(UInt32
) );
183 if (s
->arr1
== NULL
|| s
->arr2
== NULL
|| s
->ftab
== NULL
) {
184 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
185 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
186 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
187 if (s
!= NULL
) BZFREE(s
);
192 s
->state
= BZ_S_INPUT
;
193 s
->mode
= BZ_M_RUNNING
;
195 s
->blockSize100k
= blockSize100k
;
196 s
->nblockMAX
= 100000 * blockSize100k
- 19;
197 s
->verbosity
= verbosity
;
198 s
->workFactor
= workFactor
;
200 s
->block
= (UChar
*)s
->arr2
;
201 s
->mtfv
= (UInt16
*)s
->arr1
;
203 s
->ptr
= (UInt32
*)s
->arr1
;
206 strm
->total_in_lo32
= 0;
207 strm
->total_in_hi32
= 0;
208 strm
->total_out_lo32
= 0;
209 strm
->total_out_hi32
= 0;
211 prepare_new_block ( s
);
216 /*---------------------------------------------------*/
218 void add_pair_to_block ( EState
* s
)
221 UChar ch
= (UChar
)(s
->state_in_ch
);
222 for (i
= 0; i
< s
->state_in_len
; i
++) {
223 BZ_UPDATE_CRC( s
->blockCRC
, ch
);
225 s
->inUse
[s
->state_in_ch
] = True
;
226 switch (s
->state_in_len
) {
228 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
231 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
232 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
235 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
236 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
237 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
240 s
->inUse
[s
->state_in_len
-4] = True
;
241 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
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
)(s
->state_in_len
-4));
252 /*---------------------------------------------------*/
254 void flush_RL ( EState
* s
)
256 if (s
->state_in_ch
< 256) add_pair_to_block ( s
);
261 /*---------------------------------------------------*/
262 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
264 UInt32 zchh = (UInt32)(zchh0); \
265 /*-- fast track the common case --*/ \
266 if (zchh != zs->state_in_ch && \
267 zs->state_in_len == 1) { \
268 UChar ch = (UChar)(zs->state_in_ch); \
269 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
270 zs->inUse[zs->state_in_ch] = True; \
271 zs->block[zs->nblock] = (UChar)ch; \
273 zs->state_in_ch = zchh; \
276 /*-- general, uncommon cases --*/ \
277 if (zchh != zs->state_in_ch || \
278 zs->state_in_len == 255) { \
279 if (zs->state_in_ch < 256) \
280 add_pair_to_block ( zs ); \
281 zs->state_in_ch = zchh; \
282 zs->state_in_len = 1; \
284 zs->state_in_len++; \
289 /*---------------------------------------------------*/
291 Bool
copy_input_until_stop ( EState
* s
)
293 Bool progress_in
= False
;
295 if (s
->mode
== BZ_M_RUNNING
) {
297 /*-- fast track the common case --*/
299 /*-- block full? --*/
300 if (s
->nblock
>= s
->nblockMAX
) break;
302 if (s
->strm
->avail_in
== 0) break;
304 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
307 s
->strm
->total_in_lo32
++;
308 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
313 /*-- general, uncommon case --*/
315 /*-- block full? --*/
316 if (s
->nblock
>= s
->nblockMAX
) break;
318 if (s
->strm
->avail_in
== 0) break;
319 /*-- flush/finish end? --*/
320 if (s
->avail_in_expect
== 0) break;
322 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
325 s
->strm
->total_in_lo32
++;
326 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
327 s
->avail_in_expect
--;
334 /*---------------------------------------------------*/
336 Bool
copy_output_until_stop ( EState
* s
)
338 Bool progress_out
= False
;
342 /*-- no output space? --*/
343 if (s
->strm
->avail_out
== 0) break;
345 /*-- block done? --*/
346 if (s
->state_out_pos
>= s
->numZ
) break;
349 *(s
->strm
->next_out
) = s
->zbits
[s
->state_out_pos
];
351 s
->strm
->avail_out
--;
353 s
->strm
->total_out_lo32
++;
354 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
361 /*---------------------------------------------------*/
363 Bool
handle_compress ( bz_stream
* strm
)
365 Bool progress_in
= False
;
366 Bool progress_out
= False
;
367 EState
* s
= strm
->state
;
371 if (s
->state
== BZ_S_OUTPUT
) {
372 progress_out
|= copy_output_until_stop ( s
);
373 if (s
->state_out_pos
< s
->numZ
) break;
374 if (s
->mode
== BZ_M_FINISHING
&&
375 s
->avail_in_expect
== 0 &&
376 isempty_RL(s
)) break;
377 prepare_new_block ( s
);
378 s
->state
= BZ_S_INPUT
;
379 if (s
->mode
== BZ_M_FLUSHING
&&
380 s
->avail_in_expect
== 0 &&
381 isempty_RL(s
)) break;
384 if (s
->state
== BZ_S_INPUT
) {
385 progress_in
|= copy_input_until_stop ( s
);
386 if (s
->mode
!= BZ_M_RUNNING
&& s
->avail_in_expect
== 0) {
388 BZ2_compressBlock ( s
, (Bool
)(s
->mode
== BZ_M_FINISHING
) );
389 s
->state
= BZ_S_OUTPUT
;
392 if (s
->nblock
>= s
->nblockMAX
) {
393 BZ2_compressBlock ( s
, False
);
394 s
->state
= BZ_S_OUTPUT
;
397 if (s
->strm
->avail_in
== 0) {
404 return progress_in
|| progress_out
;
408 /*---------------------------------------------------*/
409 int BZ_API(BZ2_bzCompress
) ( bz_stream
*strm
, int action
)
413 if (strm
== NULL
) return BZ_PARAM_ERROR
;
415 if (s
== NULL
) return BZ_PARAM_ERROR
;
416 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
422 return BZ_SEQUENCE_ERROR
;
425 if (action
== BZ_RUN
) {
426 progress
= handle_compress ( strm
);
427 return progress
? BZ_RUN_OK
: BZ_PARAM_ERROR
;
430 if (action
== BZ_FLUSH
) {
431 s
->avail_in_expect
= strm
->avail_in
;
432 s
->mode
= BZ_M_FLUSHING
;
436 if (action
== BZ_FINISH
) {
437 s
->avail_in_expect
= strm
->avail_in
;
438 s
->mode
= BZ_M_FINISHING
;
442 return BZ_PARAM_ERROR
;
445 if (action
!= BZ_FLUSH
) return BZ_SEQUENCE_ERROR
;
446 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
447 return BZ_SEQUENCE_ERROR
;
448 progress
= handle_compress ( strm
);
449 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
450 s
->state_out_pos
< s
->numZ
) return BZ_FLUSH_OK
;
451 s
->mode
= BZ_M_RUNNING
;
455 if (action
!= BZ_FINISH
) return BZ_SEQUENCE_ERROR
;
456 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
457 return BZ_SEQUENCE_ERROR
;
458 progress
= handle_compress ( strm
);
459 if (!progress
) return BZ_SEQUENCE_ERROR
;
460 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
461 s
->state_out_pos
< s
->numZ
) return BZ_FINISH_OK
;
463 return BZ_STREAM_END
;
465 return BZ_OK
; /*--not reached--*/
469 /*---------------------------------------------------*/
470 int BZ_API(BZ2_bzCompressEnd
) ( bz_stream
*strm
)
473 if (strm
== NULL
) return BZ_PARAM_ERROR
;
475 if (s
== NULL
) return BZ_PARAM_ERROR
;
476 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
478 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
479 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
480 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
489 /*---------------------------------------------------*/
490 /*--- Decompression stuff ---*/
491 /*---------------------------------------------------*/
493 /*---------------------------------------------------*/
494 int BZ_API(BZ2_bzDecompressInit
)
501 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
503 if (strm
== NULL
) return BZ_PARAM_ERROR
;
504 if (small
!= 0 && small
!= 1) return BZ_PARAM_ERROR
;
505 if (verbosity
< 0 || verbosity
> 4) return BZ_PARAM_ERROR
;
507 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
508 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
510 s
= BZALLOC( sizeof(DState
) );
511 if (s
== NULL
) return BZ_MEM_ERROR
;
514 s
->state
= BZ_X_MAGIC_1
;
517 s
->calculatedCombinedCRC
= 0;
518 strm
->total_in_lo32
= 0;
519 strm
->total_in_hi32
= 0;
520 strm
->total_out_lo32
= 0;
521 strm
->total_out_hi32
= 0;
522 s
->smallDecompress
= (Bool
)small
;
527 s
->verbosity
= verbosity
;
533 /*---------------------------------------------------*/
534 /* Return True iff data corruption is discovered.
535 Returns False if there is no problem.
538 Bool
unRLE_obuf_to_output_FAST ( DState
* s
)
542 if (s
->blockRandomised
) {
545 /* try to finish existing run */
547 if (s
->strm
->avail_out
== 0) return False
;
548 if (s
->state_out_len
== 0) break;
549 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
550 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
553 s
->strm
->avail_out
--;
554 s
->strm
->total_out_lo32
++;
555 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
558 /* can a new run be started? */
559 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
561 /* Only caused by corrupt data stream? */
562 if (s
->nblock_used
> s
->save_nblock
+1)
565 s
->state_out_len
= 1;
566 s
->state_out_ch
= s
->k0
;
567 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
568 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
569 if (s
->nblock_used
== s
->save_nblock
+1) continue;
570 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
572 s
->state_out_len
= 2;
573 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
574 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
575 if (s
->nblock_used
== s
->save_nblock
+1) continue;
576 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
578 s
->state_out_len
= 3;
579 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
580 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
581 if (s
->nblock_used
== s
->save_nblock
+1) continue;
582 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
584 BZ_GET_FAST(k1
); BZ_RAND_UPD_MASK
;
585 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
586 s
->state_out_len
= ((Int32
)k1
) + 4;
587 BZ_GET_FAST(s
->k0
); BZ_RAND_UPD_MASK
;
588 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
594 UInt32 c_calculatedBlockCRC
= s
->calculatedBlockCRC
;
595 UChar c_state_out_ch
= s
->state_out_ch
;
596 Int32 c_state_out_len
= s
->state_out_len
;
597 Int32 c_nblock_used
= s
->nblock_used
;
599 UInt32
* c_tt
= s
->tt
;
600 UInt32 c_tPos
= s
->tPos
;
601 char* cs_next_out
= s
->strm
->next_out
;
602 unsigned int cs_avail_out
= s
->strm
->avail_out
;
603 Int32 ro_blockSize100k
= s
->blockSize100k
;
606 UInt32 avail_out_INIT
= cs_avail_out
;
607 Int32 s_save_nblockPP
= s
->save_nblock
+1;
608 unsigned int total_out_lo32_old
;
612 /* try to finish existing run */
613 if (c_state_out_len
> 0) {
615 if (cs_avail_out
== 0) goto return_notr
;
616 if (c_state_out_len
== 1) break;
617 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
618 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
623 s_state_out_len_eq_one
:
625 if (cs_avail_out
== 0) {
626 c_state_out_len
= 1; goto return_notr
;
628 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
629 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
634 /* Only caused by corrupt data stream? */
635 if (c_nblock_used
> s_save_nblockPP
)
638 /* can a new run be started? */
639 if (c_nblock_used
== s_save_nblockPP
) {
640 c_state_out_len
= 0; goto return_notr
;
642 c_state_out_ch
= c_k0
;
643 BZ_GET_FAST_C(k1
); c_nblock_used
++;
645 c_k0
= k1
; goto s_state_out_len_eq_one
;
647 if (c_nblock_used
== s_save_nblockPP
)
648 goto s_state_out_len_eq_one
;
651 BZ_GET_FAST_C(k1
); c_nblock_used
++;
652 if (c_nblock_used
== s_save_nblockPP
) continue;
653 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
656 BZ_GET_FAST_C(k1
); c_nblock_used
++;
657 if (c_nblock_used
== s_save_nblockPP
) continue;
658 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
660 BZ_GET_FAST_C(k1
); c_nblock_used
++;
661 c_state_out_len
= ((Int32
)k1
) + 4;
662 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
666 total_out_lo32_old
= s
->strm
->total_out_lo32
;
667 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
668 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
669 s
->strm
->total_out_hi32
++;
672 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
673 s
->state_out_ch
= c_state_out_ch
;
674 s
->state_out_len
= c_state_out_len
;
675 s
->nblock_used
= c_nblock_used
;
679 s
->strm
->next_out
= cs_next_out
;
680 s
->strm
->avail_out
= cs_avail_out
;
688 /*---------------------------------------------------*/
689 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
695 mid
= (nb
+ na
) >> 1;
696 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
698 while (na
- nb
!= 1);
703 /*---------------------------------------------------*/
704 /* Return True iff data corruption is discovered.
705 Returns False if there is no problem.
708 Bool
unRLE_obuf_to_output_SMALL ( DState
* s
)
712 if (s
->blockRandomised
) {
715 /* try to finish existing run */
717 if (s
->strm
->avail_out
== 0) return False
;
718 if (s
->state_out_len
== 0) break;
719 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
720 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
723 s
->strm
->avail_out
--;
724 s
->strm
->total_out_lo32
++;
725 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
728 /* can a new run be started? */
729 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
731 /* Only caused by corrupt data stream? */
732 if (s
->nblock_used
> s
->save_nblock
+1)
735 s
->state_out_len
= 1;
736 s
->state_out_ch
= s
->k0
;
737 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
738 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
739 if (s
->nblock_used
== s
->save_nblock
+1) continue;
740 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
742 s
->state_out_len
= 2;
743 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
744 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
745 if (s
->nblock_used
== s
->save_nblock
+1) continue;
746 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
748 s
->state_out_len
= 3;
749 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
750 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
751 if (s
->nblock_used
== s
->save_nblock
+1) continue;
752 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
754 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
755 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
756 s
->state_out_len
= ((Int32
)k1
) + 4;
757 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
758 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
764 /* try to finish existing run */
766 if (s
->strm
->avail_out
== 0) return False
;
767 if (s
->state_out_len
== 0) break;
768 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
769 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
772 s
->strm
->avail_out
--;
773 s
->strm
->total_out_lo32
++;
774 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
777 /* can a new run be started? */
778 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
780 /* Only caused by corrupt data stream? */
781 if (s
->nblock_used
> s
->save_nblock
+1)
784 s
->state_out_len
= 1;
785 s
->state_out_ch
= s
->k0
;
786 BZ_GET_SMALL(k1
); s
->nblock_used
++;
787 if (s
->nblock_used
== s
->save_nblock
+1) continue;
788 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
790 s
->state_out_len
= 2;
791 BZ_GET_SMALL(k1
); s
->nblock_used
++;
792 if (s
->nblock_used
== s
->save_nblock
+1) continue;
793 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
795 s
->state_out_len
= 3;
796 BZ_GET_SMALL(k1
); s
->nblock_used
++;
797 if (s
->nblock_used
== s
->save_nblock
+1) continue;
798 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
800 BZ_GET_SMALL(k1
); s
->nblock_used
++;
801 s
->state_out_len
= ((Int32
)k1
) + 4;
802 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
809 /*---------------------------------------------------*/
810 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
814 if (strm
== NULL
) return BZ_PARAM_ERROR
;
816 if (s
== NULL
) return BZ_PARAM_ERROR
;
817 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
820 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
821 if (s
->state
== BZ_X_OUTPUT
) {
822 if (s
->smallDecompress
)
823 corrupt
= unRLE_obuf_to_output_SMALL ( s
); else
824 corrupt
= unRLE_obuf_to_output_FAST ( s
);
825 if (corrupt
) return BZ_DATA_ERROR
;
826 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
827 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
828 if (s
->verbosity
>= 3)
829 VPrintf2 ( " {0x%08x, 0x%08x}", s
->storedBlockCRC
,
830 s
->calculatedBlockCRC
);
831 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
832 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
833 return BZ_DATA_ERROR
;
834 s
->calculatedCombinedCRC
835 = (s
->calculatedCombinedCRC
<< 1) |
836 (s
->calculatedCombinedCRC
>> 31);
837 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
838 s
->state
= BZ_X_BLKHDR_1
;
843 if (s
->state
>= BZ_X_MAGIC_1
) {
844 Int32 r
= BZ2_decompress ( s
);
845 if (r
== BZ_STREAM_END
) {
846 if (s
->verbosity
>= 3)
847 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
848 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
849 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
850 return BZ_DATA_ERROR
;
853 if (s
->state
!= BZ_X_OUTPUT
) return r
;
859 return 0; /*NOTREACHED*/
863 /*---------------------------------------------------*/
864 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
867 if (strm
== NULL
) return BZ_PARAM_ERROR
;
869 if (s
== NULL
) return BZ_PARAM_ERROR
;
870 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
872 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
873 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
874 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
884 /*---------------------------------------------------*/
885 /*--- File I/O stuff ---*/
886 /*---------------------------------------------------*/
888 #define BZ_SETERR(eee) \
890 if (bzerror != NULL) *bzerror = eee; \
891 if (bzf != NULL) bzf->lastErr = eee; \
897 Char buf
[BZ_MAX_UNUSED
];
907 /*---------------------------------------------*/
908 static Bool
myfeof ( FILE* f
)
910 Int32 c
= fgetc ( f
);
911 if (c
== EOF
) return True
;
917 /*---------------------------------------------------*/
918 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
931 (blockSize100k
< 1 || blockSize100k
> 9) ||
932 (workFactor
< 0 || workFactor
> 250) ||
933 (verbosity
< 0 || verbosity
> 4))
934 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
937 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
939 bzf
= malloc ( sizeof(bzFile
) );
941 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
944 bzf
->initialisedOk
= False
;
948 bzf
->strm
.bzalloc
= NULL
;
949 bzf
->strm
.bzfree
= NULL
;
950 bzf
->strm
.opaque
= NULL
;
952 if (workFactor
== 0) workFactor
= 30;
953 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
954 verbosity
, workFactor
);
956 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
958 bzf
->strm
.avail_in
= 0;
959 bzf
->initialisedOk
= True
;
965 /*---------------------------------------------------*/
966 void BZ_API(BZ2_bzWrite
)
973 bzFile
* bzf
= (bzFile
*)b
;
976 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
977 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
979 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
980 if (ferror(bzf
->handle
))
981 { BZ_SETERR(BZ_IO_ERROR
); return; };
984 { BZ_SETERR(BZ_OK
); return; };
986 bzf
->strm
.avail_in
= len
;
987 bzf
->strm
.next_in
= buf
;
990 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
991 bzf
->strm
.next_out
= bzf
->buf
;
992 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
993 if (ret
!= BZ_RUN_OK
)
994 { BZ_SETERR(ret
); return; };
996 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
997 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
998 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1000 if (n
!= n2
|| ferror(bzf
->handle
))
1001 { BZ_SETERR(BZ_IO_ERROR
); return; };
1004 if (bzf
->strm
.avail_in
== 0)
1005 { BZ_SETERR(BZ_OK
); return; };
1010 /*---------------------------------------------------*/
1011 void BZ_API(BZ2_bzWriteClose
)
1015 unsigned int* nbytes_in
,
1016 unsigned int* nbytes_out
)
1018 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1019 nbytes_in
, NULL
, nbytes_out
, NULL
);
1023 void BZ_API(BZ2_bzWriteClose64
)
1027 unsigned int* nbytes_in_lo32
,
1028 unsigned int* nbytes_in_hi32
,
1029 unsigned int* nbytes_out_lo32
,
1030 unsigned int* nbytes_out_hi32
)
1033 bzFile
* bzf
= (bzFile
*)b
;
1036 { BZ_SETERR(BZ_OK
); return; };
1037 if (!(bzf
->writing
))
1038 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1039 if (ferror(bzf
->handle
))
1040 { BZ_SETERR(BZ_IO_ERROR
); return; };
1042 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1043 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1044 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1045 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1047 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1049 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1050 bzf
->strm
.next_out
= bzf
->buf
;
1051 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1052 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1053 { BZ_SETERR(ret
); return; };
1055 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1056 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1057 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1059 if (n
!= n2
|| ferror(bzf
->handle
))
1060 { BZ_SETERR(BZ_IO_ERROR
); return; };
1063 if (ret
== BZ_STREAM_END
) break;
1067 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1068 fflush ( bzf
->handle
);
1069 if (ferror(bzf
->handle
))
1070 { BZ_SETERR(BZ_IO_ERROR
); return; };
1073 if (nbytes_in_lo32
!= NULL
)
1074 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1075 if (nbytes_in_hi32
!= NULL
)
1076 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1077 if (nbytes_out_lo32
!= NULL
)
1078 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1079 if (nbytes_out_hi32
!= NULL
)
1080 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1083 BZ2_bzCompressEnd ( &(bzf
->strm
) );
1088 /*---------------------------------------------------*/
1089 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1103 (small
!= 0 && small
!= 1) ||
1104 (verbosity
< 0 || verbosity
> 4) ||
1105 (unused
== NULL
&& nUnused
!= 0) ||
1106 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1107 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1110 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1112 bzf
= malloc ( sizeof(bzFile
) );
1114 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1118 bzf
->initialisedOk
= False
;
1121 bzf
->writing
= False
;
1122 bzf
->strm
.bzalloc
= NULL
;
1123 bzf
->strm
.bzfree
= NULL
;
1124 bzf
->strm
.opaque
= NULL
;
1126 while (nUnused
> 0) {
1127 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1128 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1132 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1134 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1136 bzf
->strm
.avail_in
= bzf
->bufN
;
1137 bzf
->strm
.next_in
= bzf
->buf
;
1139 bzf
->initialisedOk
= True
;
1144 /*---------------------------------------------------*/
1145 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1147 bzFile
* bzf
= (bzFile
*)b
;
1151 { BZ_SETERR(BZ_OK
); return; };
1154 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1156 if (bzf
->initialisedOk
)
1157 (void)BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1162 /*---------------------------------------------------*/
1163 int BZ_API(BZ2_bzRead
)
1170 bzFile
* bzf
= (bzFile
*)b
;
1174 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1175 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1178 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1181 { BZ_SETERR(BZ_OK
); return 0; };
1183 bzf
->strm
.avail_out
= len
;
1184 bzf
->strm
.next_out
= buf
;
1188 if (ferror(bzf
->handle
))
1189 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1191 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1192 n
= fread ( bzf
->buf
, sizeof(UChar
),
1193 BZ_MAX_UNUSED
, bzf
->handle
);
1194 if (ferror(bzf
->handle
))
1195 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1197 bzf
->strm
.avail_in
= bzf
->bufN
;
1198 bzf
->strm
.next_in
= bzf
->buf
;
1201 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1203 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1204 { BZ_SETERR(ret
); return 0; };
1206 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1207 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1208 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1210 if (ret
== BZ_STREAM_END
)
1211 { BZ_SETERR(BZ_STREAM_END
);
1212 return len
- bzf
->strm
.avail_out
; };
1213 if (bzf
->strm
.avail_out
== 0)
1214 { BZ_SETERR(BZ_OK
); return len
; };
1218 return 0; /*not reached*/
1222 /*---------------------------------------------------*/
1223 void BZ_API(BZ2_bzReadGetUnused
)
1229 bzFile
* bzf
= (bzFile
*)b
;
1231 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1232 if (bzf
->lastErr
!= BZ_STREAM_END
)
1233 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1234 if (unused
== NULL
|| nUnused
== NULL
)
1235 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1238 *nUnused
= bzf
->strm
.avail_in
;
1239 *unused
= bzf
->strm
.next_in
;
1244 /*---------------------------------------------------*/
1245 /*--- Misc convenience stuff ---*/
1246 /*---------------------------------------------------*/
1248 /*---------------------------------------------------*/
1249 int BZ_API(BZ2_bzBuffToBuffCompress
)
1251 unsigned int* destLen
,
1253 unsigned int sourceLen
,
1261 if (dest
== NULL
|| destLen
== NULL
||
1263 blockSize100k
< 1 || blockSize100k
> 9 ||
1264 verbosity
< 0 || verbosity
> 4 ||
1265 workFactor
< 0 || workFactor
> 250)
1266 return BZ_PARAM_ERROR
;
1268 if (workFactor
== 0) workFactor
= 30;
1269 strm
.bzalloc
= NULL
;
1272 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1273 verbosity
, workFactor
);
1274 if (ret
!= BZ_OK
) return ret
;
1276 strm
.next_in
= source
;
1277 strm
.next_out
= dest
;
1278 strm
.avail_in
= sourceLen
;
1279 strm
.avail_out
= *destLen
;
1281 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1282 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1283 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1285 /* normal termination */
1286 *destLen
-= strm
.avail_out
;
1287 BZ2_bzCompressEnd ( &strm
);
1291 BZ2_bzCompressEnd ( &strm
);
1292 return BZ_OUTBUFF_FULL
;
1295 BZ2_bzCompressEnd ( &strm
);
1300 /*---------------------------------------------------*/
1301 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1303 unsigned int* destLen
,
1305 unsigned int sourceLen
,
1312 if (dest
== NULL
|| destLen
== NULL
||
1314 (small
!= 0 && small
!= 1) ||
1315 verbosity
< 0 || verbosity
> 4)
1316 return BZ_PARAM_ERROR
;
1318 strm
.bzalloc
= NULL
;
1321 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1322 if (ret
!= BZ_OK
) return ret
;
1324 strm
.next_in
= source
;
1325 strm
.next_out
= dest
;
1326 strm
.avail_in
= sourceLen
;
1327 strm
.avail_out
= *destLen
;
1329 ret
= BZ2_bzDecompress ( &strm
);
1330 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1331 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1333 /* normal termination */
1334 *destLen
-= strm
.avail_out
;
1335 BZ2_bzDecompressEnd ( &strm
);
1338 output_overflow_or_eof
:
1339 if (strm
.avail_out
> 0) {
1340 BZ2_bzDecompressEnd ( &strm
);
1341 return BZ_UNEXPECTED_EOF
;
1343 BZ2_bzDecompressEnd ( &strm
);
1344 return BZ_OUTBUFF_FULL
;
1348 BZ2_bzDecompressEnd ( &strm
);
1353 /*---------------------------------------------------*/
1355 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1356 to support better zlib compatibility.
1357 This code is not _officially_ part of libbzip2 (yet);
1358 I haven't tested it, documented it, or considered the
1359 threading-safeness of it.
1360 If this code breaks, please contact both Yoshioka and me.
1362 /*---------------------------------------------------*/
1364 /*---------------------------------------------------*/
1366 return version like "0.9.5d, 4-Sept-1999".
1368 const char * BZ_API(BZ2_bzlibVersion
)(void)
1375 /*---------------------------------------------------*/
1377 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1380 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1382 # define SET_BINARY_MODE(file)
1385 BZFILE
* bzopen_or_bzdopen
1386 ( const char *path
, /* no use when bzdopen */
1387 int fd
, /* no use when bzdopen */
1389 int open_mode
) /* bzopen: 0, bzdopen:1 */
1392 char unused
[BZ_MAX_UNUSED
];
1393 int blockSize100k
= 9;
1395 char mode2
[10] = "";
1397 BZFILE
*bzfp
= NULL
;
1399 int workFactor
= 30;
1403 if (mode
== NULL
) return NULL
;
1411 smallMode
= 1; break;
1413 if (isdigit((unsigned char)(*mode
))) {
1414 blockSize100k
= *mode
-BZ_HDR_0
;
1419 strcat(mode2
, writing
? "w" : "r" );
1420 strcat(mode2
,"b"); /* binary mode */
1423 if (path
==NULL
|| strcmp(path
,"")==0) {
1424 fp
= (writing
? stdout
: stdin
);
1425 SET_BINARY_MODE(fp
);
1427 fp
= fopen(path
,mode2
);
1430 #ifdef BZ_STRICT_ANSI
1433 fp
= fdopen(fd
,mode2
);
1436 if (fp
== NULL
) return NULL
;
1439 /* Guard against total chaos and anarchy -- JRS */
1440 if (blockSize100k
< 1) blockSize100k
= 1;
1441 if (blockSize100k
> 9) blockSize100k
= 9;
1442 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1443 verbosity
,workFactor
);
1445 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1449 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1456 /*---------------------------------------------------*/
1458 open file for read or write.
1459 ex) bzopen("file","w9")
1460 case path="" or NULL => use stdin or stdout.
1462 BZFILE
* BZ_API(BZ2_bzopen
)
1466 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1470 /*---------------------------------------------------*/
1471 BZFILE
* BZ_API(BZ2_bzdopen
)
1475 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1479 /*---------------------------------------------------*/
1480 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1483 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1484 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1485 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1493 /*---------------------------------------------------*/
1494 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1498 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1507 /*---------------------------------------------------*/
1508 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1510 /* do nothing now... */
1515 /*---------------------------------------------------*/
1516 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1521 if (b
==NULL
) {return;}
1522 fp
= ((bzFile
*)b
)->handle
;
1523 if(((bzFile
*)b
)->writing
){
1524 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1526 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1529 BZ2_bzReadClose(&bzerr
,b
);
1531 if(fp
!=stdin
&& fp
!=stdout
){
1537 /*---------------------------------------------------*/
1539 return last error code
1541 static const char *bzerrorstrings
[] = {
1552 ,"???" /* for future */
1553 ,"???" /* for future */
1554 ,"???" /* for future */
1555 ,"???" /* for future */
1556 ,"???" /* for future */
1557 ,"???" /* for future */
1561 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1563 int err
= ((bzFile
*)b
)->lastErr
;
1567 return bzerrorstrings
[err
*-1];
1572 /*-------------------------------------------------------------*/
1573 /*--- end bzlib.c ---*/
1574 /*-------------------------------------------------------------*/