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.6 of 6 September 2010
12 Copyright (C) 1996-2010 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"
33 #ifndef BZ_NO_COMPRESS
35 /*---------------------------------------------------*/
36 /*--- Compression stuff ---*/
37 /*---------------------------------------------------*/
40 /*---------------------------------------------------*/
42 void BZ2_bz__AssertH__fail ( int errcode
)
45 "\n\nbzip2/libbzip2: internal error number %d.\n"
46 "This is a bug in bzip2/libbzip2, %s.\n"
47 "Please report it to me at: jseward@bzip.org. If this happened\n"
48 "when you were using some program which uses libbzip2 as a\n"
49 "component, you should also report this bug to the author(s)\n"
50 "of that program. Please make an effort to report this bug;\n"
51 "timely and accurate bug reports eventually lead to higher\n"
52 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
57 if (errcode
== 1007) {
59 "\n*** A special note about internal error number 1007 ***\n"
61 "Experience suggests that a common cause of i.e. 1007\n"
62 "is unreliable memory or other hardware. The 1007 assertion\n"
63 "just happens to cross-check the results of huge numbers of\n"
64 "memory reads/writes, and so acts (unintendedly) as a stress\n"
65 "test of your memory system.\n"
67 "I suggest the following: try compressing the file again,\n"
68 "possibly monitoring progress in detail with the -vv flag.\n"
70 "* If the error cannot be reproduced, and/or happens at different\n"
71 " points in compression, you may have a flaky memory system.\n"
72 " Try a memory-test program. I have used Memtest86\n"
73 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
74 " Memtest86 tests memory much more thorougly than your BIOSs\n"
75 " power-on test, and may find failures that the BIOS doesn't.\n"
77 "* If the error can be repeatably reproduced, this is a bug in\n"
78 " bzip2, and I would very much like to hear about it. Please\n"
79 " let me know, and, ideally, save a copy of the file causing the\n"
80 " problem -- without which I will be unable to investigate it.\n"
89 #endif /* BZ_NO_COMPRESS */
91 /*---------------------------------------------------*/
93 int bz_config_ok ( void )
95 if (sizeof(int) != 4) return 0;
96 if (sizeof(short) != 2) return 0;
97 if (sizeof(char) != 1) return 0;
102 * Added for Solaris kernel
110 BZE(BZ_SEQUENCE_ERROR) \
111 BZE(BZ_PARAM_ERROR) \
114 BZE(BZ_DATA_ERROR_MAGIC) \
116 BZE(BZ_UNEXPECTED_EOF) \
117 BZE(BZ_OUTBUFF_FULL) \
120 BZ_EXTERN
const char * BZ_API(BZ2_bzErrorString
) (
126 #define BZE(x) case x: return (#x);
130 return ("BZ_UNKNOWN_ERROR");
134 #include <sys/sysmacros.h>
139 #include <sys/types.h>
140 #include <sys/cmn_err.h>
141 #include <sys/kmem.h>
144 bz_internal_error(int errcode
)
146 panic("bzip2 internal error: %s\n", BZ2_bzErrorString(errcode
));
149 /*---------------------------------------------------*/
156 void* default_bzalloc ( void* opaque
, Int32 items
, Int32 size
)
158 size_t sz
= sizeof (bzap
) + BZ2_BZALLOC_ALIGN
+ (items
* size
);
159 uintptr_t p
= (uintptr_t)kmem_alloc(sz
, KM_SLEEP
);
162 bzap
*pp
= (bzap
*)((p
+ sizeof (bzap
) + BZ2_BZALLOC_ALIGN
- 1) &
164 pp
[-1].buf
= (void *)p
;
172 void default_bzfree ( void* opaque
, void* addr
)
175 bzap
*pp
= (bzap
*)addr
- 1;
176 kmem_free(pp
->buf
, pp
->sz
);
182 /*---------------------------------------------------*/
184 void* default_bzalloc ( void* opaque
, Int32 items
, Int32 size
)
186 void* v
= malloc ( items
* size
);
191 void default_bzfree ( void* opaque
, void* addr
)
193 if (addr
!= NULL
) free ( addr
);
197 /*---------------------------------------------------*/
198 #ifndef BZ_NO_COMPRESS
200 void prepare_new_block ( EState
* s
)
205 s
->state_out_pos
= 0;
206 BZ_INITIALISE_CRC ( s
->blockCRC
);
207 for (i
= 0; i
< 256; i
++) s
->inUse
[i
] = False
;
212 /*---------------------------------------------------*/
214 void init_RL ( EState
* s
)
216 s
->state_in_ch
= 256;
222 Bool
isempty_RL ( EState
* s
)
224 if (s
->state_in_ch
< 256 && s
->state_in_len
> 0)
230 /*---------------------------------------------------*/
231 int BZ_API(BZ2_bzCompressInit
)
240 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
243 blockSize100k
< 1 || blockSize100k
> 9 ||
244 workFactor
< 0 || workFactor
> 250)
245 return BZ_PARAM_ERROR
;
247 if (workFactor
== 0) workFactor
= 30;
248 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
249 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
251 s
= BZALLOC( sizeof(EState
) );
252 if (s
== NULL
) return BZ_MEM_ERROR
;
259 n
= 100000 * blockSize100k
;
260 s
->arr1
= BZALLOC( n
* sizeof(UInt32
) );
261 s
->arr2
= BZALLOC( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
262 s
->ftab
= BZALLOC( 65537 * sizeof(UInt32
) );
264 if (s
->arr1
== NULL
|| s
->arr2
== NULL
|| s
->ftab
== NULL
) {
265 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
266 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
267 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
268 if (s
!= NULL
) BZFREE(s
);
273 s
->state
= BZ_S_INPUT
;
274 s
->mode
= BZ_M_RUNNING
;
276 s
->blockSize100k
= blockSize100k
;
277 s
->nblockMAX
= 100000 * blockSize100k
- 19;
278 s
->verbosity
= verbosity
;
279 s
->workFactor
= workFactor
;
281 s
->block
= (UChar
*)s
->arr2
;
282 s
->mtfv
= (UInt16
*)s
->arr1
;
284 s
->ptr
= (UInt32
*)s
->arr1
;
287 strm
->total_in_lo32
= 0;
288 strm
->total_in_hi32
= 0;
289 strm
->total_out_lo32
= 0;
290 strm
->total_out_hi32
= 0;
292 prepare_new_block ( s
);
296 /*---------------------------------------------------*/
298 * returns the BZALLOC size needed for bzCompressInit
300 int BZ_API(BZ2_bzCompressInitSize
) (
305 n
= 100000 * blockSize100k
;
307 t
+= ( sizeof(EState
) );
308 t
= P2ROUNDUP(t
, BZ2_BZALLOC_ALIGN
);
309 t
+= ( n
* sizeof(UInt32
) );
310 t
= P2ROUNDUP(t
, BZ2_BZALLOC_ALIGN
);
311 t
+= ( (n
+BZ_N_OVERSHOOT
) * sizeof(UInt32
) );
312 t
= P2ROUNDUP(t
, BZ2_BZALLOC_ALIGN
);
313 t
+= ( 65537 * sizeof(UInt32
) );
314 t
= P2ROUNDUP(t
, BZ2_BZALLOC_ALIGN
);
318 /*---------------------------------------------------*/
320 * added to allow reuse of bz_stream without malloc/free
322 int BZ_API(BZ2_bzCompressReset
) ( bz_stream
*strm
)
324 EState
* s
= strm
->state
;
326 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
328 if (s
== NULL
) return BZ_MEM_ERROR
;
332 s
->state
= BZ_S_INPUT
;
333 s
->mode
= BZ_M_RUNNING
;
335 s
->nblockMAX
= 100000 * s
->blockSize100k
- 19;
337 s
->block
= (UChar
*)s
->arr2
;
338 s
->mtfv
= (UInt16
*)s
->arr1
;
340 s
->ptr
= (UInt32
*)s
->arr1
;
343 strm
->total_in_lo32
= 0;
344 strm
->total_in_hi32
= 0;
345 strm
->total_out_lo32
= 0;
346 strm
->total_out_hi32
= 0;
348 prepare_new_block ( s
);
353 /*---------------------------------------------------*/
355 void add_pair_to_block ( EState
* s
)
358 UChar ch
= (UChar
)(s
->state_in_ch
);
359 for (i
= 0; i
< s
->state_in_len
; i
++) {
360 BZ_UPDATE_CRC( s
->blockCRC
, ch
);
362 s
->inUse
[s
->state_in_ch
] = True
;
363 switch (s
->state_in_len
) {
365 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
368 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
369 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
372 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
373 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
374 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
377 s
->inUse
[s
->state_in_len
-4] = True
;
378 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
379 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
380 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
381 s
->block
[s
->nblock
] = (UChar
)ch
; s
->nblock
++;
382 s
->block
[s
->nblock
] = ((UChar
)(s
->state_in_len
-4));
389 /*---------------------------------------------------*/
391 void flush_RL ( EState
* s
)
393 if (s
->state_in_ch
< 256) add_pair_to_block ( s
);
398 /*---------------------------------------------------*/
399 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
401 UInt32 zchh = (UInt32)(zchh0); \
402 /*-- fast track the common case --*/ \
403 if (zchh != zs->state_in_ch && \
404 zs->state_in_len == 1) { \
405 UChar ch = (UChar)(zs->state_in_ch); \
406 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
407 zs->inUse[zs->state_in_ch] = True; \
408 zs->block[zs->nblock] = (UChar)ch; \
410 zs->state_in_ch = zchh; \
413 /*-- general, uncommon cases --*/ \
414 if (zchh != zs->state_in_ch || \
415 zs->state_in_len == 255) { \
416 if (zs->state_in_ch < 256) \
417 add_pair_to_block ( zs ); \
418 zs->state_in_ch = zchh; \
419 zs->state_in_len = 1; \
421 zs->state_in_len++; \
426 /*---------------------------------------------------*/
428 Bool
copy_input_until_stop ( EState
* s
)
430 Bool progress_in
= False
;
432 if (s
->mode
== BZ_M_RUNNING
) {
434 /*-- fast track the common case --*/
436 /*-- block full? --*/
437 if (s
->nblock
>= s
->nblockMAX
) break;
439 if (s
->strm
->avail_in
== 0) break;
441 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
444 s
->strm
->total_in_lo32
++;
445 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
450 /*-- general, uncommon case --*/
452 /*-- block full? --*/
453 if (s
->nblock
>= s
->nblockMAX
) break;
455 if (s
->strm
->avail_in
== 0) break;
456 /*-- flush/finish end? --*/
457 if (s
->avail_in_expect
== 0) break;
459 ADD_CHAR_TO_BLOCK ( s
, (UInt32
)(*((UChar
*)(s
->strm
->next_in
))) );
462 s
->strm
->total_in_lo32
++;
463 if (s
->strm
->total_in_lo32
== 0) s
->strm
->total_in_hi32
++;
464 s
->avail_in_expect
--;
471 /*---------------------------------------------------*/
473 Bool
copy_output_until_stop ( EState
* s
)
475 Bool progress_out
= False
;
479 /*-- no output space? --*/
480 if (s
->strm
->avail_out
== 0) break;
482 /*-- block done? --*/
483 if (s
->state_out_pos
>= s
->numZ
) break;
486 *(s
->strm
->next_out
) = s
->zbits
[s
->state_out_pos
];
488 s
->strm
->avail_out
--;
490 s
->strm
->total_out_lo32
++;
491 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
498 /*---------------------------------------------------*/
500 Bool
handle_compress ( bz_stream
* strm
)
502 Bool progress_in
= False
;
503 Bool progress_out
= False
;
504 EState
* s
= strm
->state
;
508 if (s
->state
== BZ_S_OUTPUT
) {
509 progress_out
|= copy_output_until_stop ( s
);
510 if (s
->state_out_pos
< s
->numZ
) break;
511 if (s
->mode
== BZ_M_FINISHING
&&
512 s
->avail_in_expect
== 0 &&
513 isempty_RL(s
)) break;
514 prepare_new_block ( s
);
515 s
->state
= BZ_S_INPUT
;
516 if (s
->mode
== BZ_M_FLUSHING
&&
517 s
->avail_in_expect
== 0 &&
518 isempty_RL(s
)) break;
521 if (s
->state
== BZ_S_INPUT
) {
522 progress_in
|= copy_input_until_stop ( s
);
523 if (s
->mode
!= BZ_M_RUNNING
&& s
->avail_in_expect
== 0) {
525 BZ2_compressBlock ( s
, (Bool
)(s
->mode
== BZ_M_FINISHING
) );
526 s
->state
= BZ_S_OUTPUT
;
529 if (s
->nblock
>= s
->nblockMAX
) {
530 BZ2_compressBlock ( s
, False
);
531 s
->state
= BZ_S_OUTPUT
;
534 if (s
->strm
->avail_in
== 0) {
541 return progress_in
|| progress_out
;
545 /*---------------------------------------------------*/
546 int BZ_API(BZ2_bzCompress
) ( bz_stream
*strm
, int action
)
550 if (strm
== NULL
) return BZ_PARAM_ERROR
;
552 if (s
== NULL
) return BZ_PARAM_ERROR
;
553 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
559 return BZ_SEQUENCE_ERROR
;
562 if (action
== BZ_RUN
) {
563 progress
= handle_compress ( strm
);
564 return progress
? BZ_RUN_OK
: BZ_PARAM_ERROR
;
567 if (action
== BZ_FLUSH
) {
568 s
->avail_in_expect
= strm
->avail_in
;
569 s
->mode
= BZ_M_FLUSHING
;
573 if (action
== BZ_FINISH
) {
574 s
->avail_in_expect
= strm
->avail_in
;
575 s
->mode
= BZ_M_FINISHING
;
579 return BZ_PARAM_ERROR
;
582 if (action
!= BZ_FLUSH
) return BZ_SEQUENCE_ERROR
;
583 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
584 return BZ_SEQUENCE_ERROR
;
585 progress
= handle_compress ( strm
);
586 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
587 s
->state_out_pos
< s
->numZ
) return BZ_FLUSH_OK
;
588 s
->mode
= BZ_M_RUNNING
;
592 if (action
!= BZ_FINISH
) return BZ_SEQUENCE_ERROR
;
593 if (s
->avail_in_expect
!= s
->strm
->avail_in
)
594 return BZ_SEQUENCE_ERROR
;
595 progress
= handle_compress ( strm
);
596 if (!progress
) return BZ_SEQUENCE_ERROR
;
597 if (s
->avail_in_expect
> 0 || !isempty_RL(s
) ||
598 s
->state_out_pos
< s
->numZ
) return BZ_FINISH_OK
;
600 return BZ_STREAM_END
;
602 return BZ_OK
; /*--not reached--*/
606 /*---------------------------------------------------*/
607 int BZ_API(BZ2_bzCompressEnd
) ( bz_stream
*strm
)
610 if (strm
== NULL
) return BZ_PARAM_ERROR
;
612 if (s
== NULL
) return BZ_PARAM_ERROR
;
613 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
615 if (s
->arr1
!= NULL
) BZFREE(s
->arr1
);
616 if (s
->arr2
!= NULL
) BZFREE(s
->arr2
);
617 if (s
->ftab
!= NULL
) BZFREE(s
->ftab
);
625 #endif /* BZ_NO_COMPRESS */
627 /*---------------------------------------------------*/
628 /*--- Decompression stuff ---*/
629 /*---------------------------------------------------*/
631 /*---------------------------------------------------*/
632 int BZ_API(BZ2_bzDecompressInit
)
639 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
641 if (strm
== NULL
) return BZ_PARAM_ERROR
;
642 if (small
!= 0 && small
!= 1) return BZ_PARAM_ERROR
;
643 if (verbosity
< 0 || verbosity
> 4) return BZ_PARAM_ERROR
;
645 if (strm
->bzalloc
== NULL
) strm
->bzalloc
= default_bzalloc
;
646 if (strm
->bzfree
== NULL
) strm
->bzfree
= default_bzfree
;
648 s
= BZALLOC( sizeof(DState
) );
649 if (s
== NULL
) return BZ_MEM_ERROR
;
652 s
->state
= BZ_X_MAGIC_1
;
655 s
->calculatedCombinedCRC
= 0;
656 strm
->total_in_lo32
= 0;
657 strm
->total_in_hi32
= 0;
658 strm
->total_out_lo32
= 0;
659 strm
->total_out_hi32
= 0;
660 s
->smallDecompress
= (Bool
)small
;
665 s
->verbosity
= verbosity
;
670 /*---------------------------------------------------*/
672 * added to allow reuse of bz_stream without malloc/free
674 int BZ_API(BZ2_bzDecompressReset
) ( bz_stream
* strm
)
676 DState
* s
= strm
->state
;
678 if (!bz_config_ok()) return BZ_CONFIG_ERROR
;
680 if (strm
== NULL
) return BZ_PARAM_ERROR
;
684 s
->state
= BZ_X_MAGIC_1
;
687 s
->calculatedCombinedCRC
= 0;
688 strm
->total_in_lo32
= 0;
689 strm
->total_in_hi32
= 0;
690 strm
->total_out_lo32
= 0;
691 strm
->total_out_hi32
= 0;
703 /*---------------------------------------------------*/
704 /* Return True iff data corruption is discovered.
705 Returns False if there is no problem.
708 Bool
unRLE_obuf_to_output_FAST ( 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_FAST(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_FAST(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_FAST(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_FAST(k1
); BZ_RAND_UPD_MASK
;
755 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
756 s
->state_out_len
= ((Int32
)k1
) + 4;
757 BZ_GET_FAST(s
->k0
); BZ_RAND_UPD_MASK
;
758 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
764 UInt32 c_calculatedBlockCRC
= s
->calculatedBlockCRC
;
765 UChar c_state_out_ch
= s
->state_out_ch
;
766 Int32 c_state_out_len
= s
->state_out_len
;
767 Int32 c_nblock_used
= s
->nblock_used
;
769 UInt32
* c_tt
= s
->tt
;
770 UInt32 c_tPos
= s
->tPos
;
771 char* cs_next_out
= s
->strm
->next_out
;
772 unsigned int cs_avail_out
= s
->strm
->avail_out
;
773 Int32 ro_blockSize100k
= s
->blockSize100k
;
776 UInt32 avail_out_INIT
= cs_avail_out
;
777 Int32 s_save_nblockPP
= s
->save_nblock
+1;
778 unsigned int total_out_lo32_old
;
782 /* try to finish existing run */
783 if (c_state_out_len
> 0) {
785 if (cs_avail_out
== 0) goto return_notr
;
786 if (c_state_out_len
== 1) break;
787 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
788 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
793 s_state_out_len_eq_one
:
795 if (cs_avail_out
== 0) {
796 c_state_out_len
= 1; goto return_notr
;
798 *( (UChar
*)(cs_next_out
) ) = c_state_out_ch
;
799 BZ_UPDATE_CRC ( c_calculatedBlockCRC
, c_state_out_ch
);
804 /* Only caused by corrupt data stream? */
805 if (c_nblock_used
> s_save_nblockPP
)
808 /* can a new run be started? */
809 if (c_nblock_used
== s_save_nblockPP
) {
810 c_state_out_len
= 0; goto return_notr
;
812 c_state_out_ch
= c_k0
;
813 BZ_GET_FAST_C(k1
); c_nblock_used
++;
815 c_k0
= k1
; goto s_state_out_len_eq_one
;
817 if (c_nblock_used
== s_save_nblockPP
)
818 goto s_state_out_len_eq_one
;
821 BZ_GET_FAST_C(k1
); c_nblock_used
++;
822 if (c_nblock_used
== s_save_nblockPP
) continue;
823 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
826 BZ_GET_FAST_C(k1
); c_nblock_used
++;
827 if (c_nblock_used
== s_save_nblockPP
) continue;
828 if (k1
!= c_k0
) { c_k0
= k1
; continue; };
830 BZ_GET_FAST_C(k1
); c_nblock_used
++;
831 c_state_out_len
= ((Int32
)k1
) + 4;
832 BZ_GET_FAST_C(c_k0
); c_nblock_used
++;
836 total_out_lo32_old
= s
->strm
->total_out_lo32
;
837 s
->strm
->total_out_lo32
+= (avail_out_INIT
- cs_avail_out
);
838 if (s
->strm
->total_out_lo32
< total_out_lo32_old
)
839 s
->strm
->total_out_hi32
++;
842 s
->calculatedBlockCRC
= c_calculatedBlockCRC
;
843 s
->state_out_ch
= c_state_out_ch
;
844 s
->state_out_len
= c_state_out_len
;
845 s
->nblock_used
= c_nblock_used
;
849 s
->strm
->next_out
= cs_next_out
;
850 s
->strm
->avail_out
= cs_avail_out
;
858 /*---------------------------------------------------*/
859 __inline__ Int32
BZ2_indexIntoF ( Int32 indx
, Int32
*cftab
)
865 mid
= (nb
+ na
) >> 1;
866 if (indx
>= cftab
[mid
]) nb
= mid
; else na
= mid
;
868 while (na
- nb
!= 1);
873 /*---------------------------------------------------*/
874 /* Return True iff data corruption is discovered.
875 Returns False if there is no problem.
878 Bool
unRLE_obuf_to_output_SMALL ( DState
* s
)
882 if (s
->blockRandomised
) {
885 /* try to finish existing run */
887 if (s
->strm
->avail_out
== 0) return False
;
888 if (s
->state_out_len
== 0) break;
889 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
890 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
893 s
->strm
->avail_out
--;
894 s
->strm
->total_out_lo32
++;
895 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
898 /* can a new run be started? */
899 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
901 /* Only caused by corrupt data stream? */
902 if (s
->nblock_used
> s
->save_nblock
+1)
905 s
->state_out_len
= 1;
906 s
->state_out_ch
= s
->k0
;
907 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
908 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
909 if (s
->nblock_used
== s
->save_nblock
+1) continue;
910 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
912 s
->state_out_len
= 2;
913 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
914 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
915 if (s
->nblock_used
== s
->save_nblock
+1) continue;
916 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
918 s
->state_out_len
= 3;
919 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
920 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
921 if (s
->nblock_used
== s
->save_nblock
+1) continue;
922 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
924 BZ_GET_SMALL(k1
); BZ_RAND_UPD_MASK
;
925 k1
^= BZ_RAND_MASK
; s
->nblock_used
++;
926 s
->state_out_len
= ((Int32
)k1
) + 4;
927 BZ_GET_SMALL(s
->k0
); BZ_RAND_UPD_MASK
;
928 s
->k0
^= BZ_RAND_MASK
; s
->nblock_used
++;
934 /* try to finish existing run */
936 if (s
->strm
->avail_out
== 0) return False
;
937 if (s
->state_out_len
== 0) break;
938 *( (UChar
*)(s
->strm
->next_out
) ) = s
->state_out_ch
;
939 BZ_UPDATE_CRC ( s
->calculatedBlockCRC
, s
->state_out_ch
);
942 s
->strm
->avail_out
--;
943 s
->strm
->total_out_lo32
++;
944 if (s
->strm
->total_out_lo32
== 0) s
->strm
->total_out_hi32
++;
947 /* can a new run be started? */
948 if (s
->nblock_used
== s
->save_nblock
+1) return False
;
950 /* Only caused by corrupt data stream? */
951 if (s
->nblock_used
> s
->save_nblock
+1)
954 s
->state_out_len
= 1;
955 s
->state_out_ch
= s
->k0
;
956 BZ_GET_SMALL(k1
); s
->nblock_used
++;
957 if (s
->nblock_used
== s
->save_nblock
+1) continue;
958 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
960 s
->state_out_len
= 2;
961 BZ_GET_SMALL(k1
); s
->nblock_used
++;
962 if (s
->nblock_used
== s
->save_nblock
+1) continue;
963 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
965 s
->state_out_len
= 3;
966 BZ_GET_SMALL(k1
); s
->nblock_used
++;
967 if (s
->nblock_used
== s
->save_nblock
+1) continue;
968 if (k1
!= s
->k0
) { s
->k0
= k1
; continue; };
970 BZ_GET_SMALL(k1
); s
->nblock_used
++;
971 s
->state_out_len
= ((Int32
)k1
) + 4;
972 BZ_GET_SMALL(s
->k0
); s
->nblock_used
++;
979 /*---------------------------------------------------*/
980 int BZ_API(BZ2_bzDecompress
) ( bz_stream
*strm
)
984 if (strm
== NULL
) return BZ_PARAM_ERROR
;
986 if (s
== NULL
) return BZ_PARAM_ERROR
;
987 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
990 if (s
->state
== BZ_X_IDLE
) return BZ_SEQUENCE_ERROR
;
991 if (s
->state
== BZ_X_OUTPUT
) {
992 if (s
->smallDecompress
)
993 corrupt
= unRLE_obuf_to_output_SMALL ( s
); else
994 corrupt
= unRLE_obuf_to_output_FAST ( s
);
995 if (corrupt
) return BZ_DATA_ERROR
;
996 if (s
->nblock_used
== s
->save_nblock
+1 && s
->state_out_len
== 0) {
997 BZ_FINALISE_CRC ( s
->calculatedBlockCRC
);
998 if (s
->verbosity
>= 3)
999 VPrintf2 ( " {0x%08x, 0x%08x}", s
->storedBlockCRC
,
1000 s
->calculatedBlockCRC
);
1001 if (s
->verbosity
>= 2) VPrintf0 ( "]" );
1002 if (s
->calculatedBlockCRC
!= s
->storedBlockCRC
)
1003 return BZ_DATA_ERROR
;
1004 s
->calculatedCombinedCRC
1005 = (s
->calculatedCombinedCRC
<< 1) |
1006 (s
->calculatedCombinedCRC
>> 31);
1007 s
->calculatedCombinedCRC
^= s
->calculatedBlockCRC
;
1008 s
->state
= BZ_X_BLKHDR_1
;
1013 if (s
->state
>= BZ_X_MAGIC_1
) {
1014 Int32 r
= BZ2_decompress ( s
);
1015 if (r
== BZ_STREAM_END
) {
1016 if (s
->verbosity
>= 3)
1017 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
1018 s
->storedCombinedCRC
, s
->calculatedCombinedCRC
);
1019 if (s
->calculatedCombinedCRC
!= s
->storedCombinedCRC
)
1020 return BZ_DATA_ERROR
;
1023 if (s
->state
!= BZ_X_OUTPUT
) return r
;
1028 AssertH ( 0, 6001 );
1030 return 0; /*NOTREACHED*/
1035 /*---------------------------------------------------*/
1036 int BZ_API(BZ2_bzDecompressEnd
) ( bz_stream
*strm
)
1039 if (strm
== NULL
) return BZ_PARAM_ERROR
;
1041 if (s
== NULL
) return BZ_PARAM_ERROR
;
1042 if (s
->strm
!= strm
) return BZ_PARAM_ERROR
;
1044 if (s
->tt
!= NULL
) BZFREE(s
->tt
);
1045 if (s
->ll16
!= NULL
) BZFREE(s
->ll16
);
1046 if (s
->ll4
!= NULL
) BZFREE(s
->ll4
);
1048 BZFREE(strm
->state
);
1054 #ifndef BZ_NO_COMPRESS
1057 /*---------------------------------------------------*/
1058 /*--- File I/O stuff ---*/
1059 /*---------------------------------------------------*/
1061 #define BZ_SETERR(eee) \
1063 if (bzerror != NULL) *bzerror = eee; \
1064 if (bzf != NULL) bzf->lastErr = eee; \
1070 Char buf
[BZ_MAX_UNUSED
];
1080 /*---------------------------------------------*/
1081 static Bool
myfeof ( FILE* f
)
1083 Int32 c
= fgetc ( f
);
1084 if (c
== EOF
) return True
;
1090 /*---------------------------------------------------*/
1091 BZFILE
* BZ_API(BZ2_bzWriteOpen
)
1104 (blockSize100k
< 1 || blockSize100k
> 9) ||
1105 (workFactor
< 0 || workFactor
> 250) ||
1106 (verbosity
< 0 || verbosity
> 4))
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
; };
1117 bzf
->initialisedOk
= False
;
1120 bzf
->writing
= True
;
1121 bzf
->strm
.bzalloc
= NULL
;
1122 bzf
->strm
.bzfree
= NULL
;
1123 bzf
->strm
.opaque
= NULL
;
1125 if (workFactor
== 0) workFactor
= 30;
1126 ret
= BZ2_bzCompressInit ( &(bzf
->strm
), blockSize100k
,
1127 verbosity
, workFactor
);
1129 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1131 bzf
->strm
.avail_in
= 0;
1132 bzf
->initialisedOk
= True
;
1138 /*---------------------------------------------------*/
1139 void BZ_API(BZ2_bzWrite
)
1146 bzFile
* bzf
= (bzFile
*)b
;
1149 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1150 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1151 if (!(bzf
->writing
))
1152 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1153 if (ferror(bzf
->handle
))
1154 { BZ_SETERR(BZ_IO_ERROR
); return; };
1157 { BZ_SETERR(BZ_OK
); return; };
1159 bzf
->strm
.avail_in
= len
;
1160 bzf
->strm
.next_in
= buf
;
1163 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1164 bzf
->strm
.next_out
= bzf
->buf
;
1165 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_RUN
);
1166 if (ret
!= BZ_RUN_OK
)
1167 { BZ_SETERR(ret
); return; };
1169 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1170 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1171 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1173 if (n
!= n2
|| ferror(bzf
->handle
))
1174 { BZ_SETERR(BZ_IO_ERROR
); return; };
1177 if (bzf
->strm
.avail_in
== 0)
1178 { BZ_SETERR(BZ_OK
); return; };
1183 /*---------------------------------------------------*/
1184 void BZ_API(BZ2_bzWriteClose
)
1188 unsigned int* nbytes_in
,
1189 unsigned int* nbytes_out
)
1191 BZ2_bzWriteClose64 ( bzerror
, b
, abandon
,
1192 nbytes_in
, NULL
, nbytes_out
, NULL
);
1196 void BZ_API(BZ2_bzWriteClose64
)
1200 unsigned int* nbytes_in_lo32
,
1201 unsigned int* nbytes_in_hi32
,
1202 unsigned int* nbytes_out_lo32
,
1203 unsigned int* nbytes_out_hi32
)
1206 bzFile
* bzf
= (bzFile
*)b
;
1209 { BZ_SETERR(BZ_OK
); return; };
1210 if (!(bzf
->writing
))
1211 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1212 if (ferror(bzf
->handle
))
1213 { BZ_SETERR(BZ_IO_ERROR
); return; };
1215 if (nbytes_in_lo32
!= NULL
) *nbytes_in_lo32
= 0;
1216 if (nbytes_in_hi32
!= NULL
) *nbytes_in_hi32
= 0;
1217 if (nbytes_out_lo32
!= NULL
) *nbytes_out_lo32
= 0;
1218 if (nbytes_out_hi32
!= NULL
) *nbytes_out_hi32
= 0;
1220 if ((!abandon
) && bzf
->lastErr
== BZ_OK
) {
1222 bzf
->strm
.avail_out
= BZ_MAX_UNUSED
;
1223 bzf
->strm
.next_out
= bzf
->buf
;
1224 ret
= BZ2_bzCompress ( &(bzf
->strm
), BZ_FINISH
);
1225 if (ret
!= BZ_FINISH_OK
&& ret
!= BZ_STREAM_END
)
1226 { BZ_SETERR(ret
); return; };
1228 if (bzf
->strm
.avail_out
< BZ_MAX_UNUSED
) {
1229 n
= BZ_MAX_UNUSED
- bzf
->strm
.avail_out
;
1230 n2
= fwrite ( (void*)(bzf
->buf
), sizeof(UChar
),
1232 if (n
!= n2
|| ferror(bzf
->handle
))
1233 { BZ_SETERR(BZ_IO_ERROR
); return; };
1236 if (ret
== BZ_STREAM_END
) break;
1240 if ( !abandon
&& !ferror ( bzf
->handle
) ) {
1241 fflush ( bzf
->handle
);
1242 if (ferror(bzf
->handle
))
1243 { BZ_SETERR(BZ_IO_ERROR
); return; };
1246 if (nbytes_in_lo32
!= NULL
)
1247 *nbytes_in_lo32
= bzf
->strm
.total_in_lo32
;
1248 if (nbytes_in_hi32
!= NULL
)
1249 *nbytes_in_hi32
= bzf
->strm
.total_in_hi32
;
1250 if (nbytes_out_lo32
!= NULL
)
1251 *nbytes_out_lo32
= bzf
->strm
.total_out_lo32
;
1252 if (nbytes_out_hi32
!= NULL
)
1253 *nbytes_out_hi32
= bzf
->strm
.total_out_hi32
;
1256 (void) BZ2_bzCompressEnd ( &(bzf
->strm
) );
1261 /*---------------------------------------------------*/
1262 BZFILE
* BZ_API(BZ2_bzReadOpen
)
1276 (small
!= 0 && small
!= 1) ||
1277 (verbosity
< 0 || verbosity
> 4) ||
1278 (unused
== NULL
&& nUnused
!= 0) ||
1279 (unused
!= NULL
&& (nUnused
< 0 || nUnused
> BZ_MAX_UNUSED
)))
1280 { BZ_SETERR(BZ_PARAM_ERROR
); return NULL
; };
1283 { BZ_SETERR(BZ_IO_ERROR
); return NULL
; };
1285 bzf
= malloc ( sizeof(bzFile
) );
1287 { BZ_SETERR(BZ_MEM_ERROR
); return NULL
; };
1291 bzf
->initialisedOk
= False
;
1294 bzf
->writing
= False
;
1295 bzf
->strm
.bzalloc
= NULL
;
1296 bzf
->strm
.bzfree
= NULL
;
1297 bzf
->strm
.opaque
= NULL
;
1299 while (nUnused
> 0) {
1300 bzf
->buf
[bzf
->bufN
] = *((UChar
*)(unused
)); bzf
->bufN
++;
1301 unused
= ((void*)( 1 + ((UChar
*)(unused
)) ));
1305 ret
= BZ2_bzDecompressInit ( &(bzf
->strm
), verbosity
, small
);
1307 { BZ_SETERR(ret
); free(bzf
); return NULL
; };
1309 bzf
->strm
.avail_in
= bzf
->bufN
;
1310 bzf
->strm
.next_in
= bzf
->buf
;
1312 bzf
->initialisedOk
= True
;
1317 /*---------------------------------------------------*/
1318 void BZ_API(BZ2_bzReadClose
) ( int *bzerror
, BZFILE
*b
)
1320 bzFile
* bzf
= (bzFile
*)b
;
1324 { BZ_SETERR(BZ_OK
); return; };
1327 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1329 if (bzf
->initialisedOk
)
1330 (void) BZ2_bzDecompressEnd ( &(bzf
->strm
) );
1335 /*---------------------------------------------------*/
1336 int BZ_API(BZ2_bzRead
)
1343 bzFile
* bzf
= (bzFile
*)b
;
1347 if (bzf
== NULL
|| buf
== NULL
|| len
< 0)
1348 { BZ_SETERR(BZ_PARAM_ERROR
); return 0; };
1351 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return 0; };
1354 { BZ_SETERR(BZ_OK
); return 0; };
1356 bzf
->strm
.avail_out
= len
;
1357 bzf
->strm
.next_out
= buf
;
1361 if (ferror(bzf
->handle
))
1362 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1364 if (bzf
->strm
.avail_in
== 0 && !myfeof(bzf
->handle
)) {
1365 n
= fread ( bzf
->buf
, sizeof(UChar
),
1366 BZ_MAX_UNUSED
, bzf
->handle
);
1367 if (ferror(bzf
->handle
))
1368 { BZ_SETERR(BZ_IO_ERROR
); return 0; };
1370 bzf
->strm
.avail_in
= bzf
->bufN
;
1371 bzf
->strm
.next_in
= bzf
->buf
;
1374 ret
= BZ2_bzDecompress ( &(bzf
->strm
) );
1376 if (ret
!= BZ_OK
&& ret
!= BZ_STREAM_END
)
1377 { BZ_SETERR(ret
); return 0; };
1379 if (ret
== BZ_OK
&& myfeof(bzf
->handle
) &&
1380 bzf
->strm
.avail_in
== 0 && bzf
->strm
.avail_out
> 0)
1381 { BZ_SETERR(BZ_UNEXPECTED_EOF
); return 0; };
1383 if (ret
== BZ_STREAM_END
)
1384 { BZ_SETERR(BZ_STREAM_END
);
1385 return len
- bzf
->strm
.avail_out
; };
1386 if (bzf
->strm
.avail_out
== 0)
1387 { BZ_SETERR(BZ_OK
); return len
; };
1391 return 0; /*not reached*/
1395 /*---------------------------------------------------*/
1396 void BZ_API(BZ2_bzReadGetUnused
)
1402 bzFile
* bzf
= (bzFile
*)b
;
1404 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1405 if (bzf
->lastErr
!= BZ_STREAM_END
)
1406 { BZ_SETERR(BZ_SEQUENCE_ERROR
); return; };
1407 if (unused
== NULL
|| nUnused
== NULL
)
1408 { BZ_SETERR(BZ_PARAM_ERROR
); return; };
1411 *nUnused
= bzf
->strm
.avail_in
;
1412 *unused
= bzf
->strm
.next_in
;
1417 /*---------------------------------------------------*/
1418 /*--- Misc convenience stuff ---*/
1419 /*---------------------------------------------------*/
1421 /*---------------------------------------------------*/
1422 int BZ_API(BZ2_bzBuffToBuffCompress
)
1424 unsigned int* destLen
,
1426 unsigned int sourceLen
,
1434 if (dest
== NULL
|| destLen
== NULL
||
1436 blockSize100k
< 1 || blockSize100k
> 9 ||
1437 verbosity
< 0 || verbosity
> 4 ||
1438 workFactor
< 0 || workFactor
> 250)
1439 return BZ_PARAM_ERROR
;
1441 if (workFactor
== 0) workFactor
= 30;
1442 strm
.bzalloc
= NULL
;
1445 ret
= BZ2_bzCompressInit ( &strm
, blockSize100k
,
1446 verbosity
, workFactor
);
1447 if (ret
!= BZ_OK
) return ret
;
1449 strm
.next_in
= source
;
1450 strm
.next_out
= dest
;
1451 strm
.avail_in
= sourceLen
;
1452 strm
.avail_out
= *destLen
;
1454 ret
= BZ2_bzCompress ( &strm
, BZ_FINISH
);
1455 if (ret
== BZ_FINISH_OK
) goto output_overflow
;
1456 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1458 /* normal termination */
1459 *destLen
-= strm
.avail_out
;
1460 (void) BZ2_bzCompressEnd ( &strm
);
1464 (void) BZ2_bzCompressEnd ( &strm
);
1465 return BZ_OUTBUFF_FULL
;
1468 (void) BZ2_bzCompressEnd ( &strm
);
1473 /*---------------------------------------------------*/
1474 int BZ_API(BZ2_bzBuffToBuffDecompress
)
1476 unsigned int* destLen
,
1478 unsigned int sourceLen
,
1485 if (dest
== NULL
|| destLen
== NULL
||
1487 (small
!= 0 && small
!= 1) ||
1488 verbosity
< 0 || verbosity
> 4)
1489 return BZ_PARAM_ERROR
;
1491 strm
.bzalloc
= NULL
;
1494 ret
= BZ2_bzDecompressInit ( &strm
, verbosity
, small
);
1495 if (ret
!= BZ_OK
) return ret
;
1497 strm
.next_in
= source
;
1498 strm
.next_out
= dest
;
1499 strm
.avail_in
= sourceLen
;
1500 strm
.avail_out
= *destLen
;
1502 ret
= BZ2_bzDecompress ( &strm
);
1503 if (ret
== BZ_OK
) goto output_overflow_or_eof
;
1504 if (ret
!= BZ_STREAM_END
) goto errhandler
;
1506 /* normal termination */
1507 *destLen
-= strm
.avail_out
;
1508 (void) BZ2_bzDecompressEnd ( &strm
);
1511 output_overflow_or_eof
:
1512 if (strm
.avail_out
> 0) {
1513 (void) BZ2_bzDecompressEnd ( &strm
);
1514 return BZ_UNEXPECTED_EOF
;
1516 (void) BZ2_bzDecompressEnd ( &strm
);
1517 return BZ_OUTBUFF_FULL
;
1521 (void) BZ2_bzDecompressEnd ( &strm
);
1526 /*---------------------------------------------------*/
1528 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1529 to support better zlib compatibility.
1530 This code is not _officially_ part of libbzip2 (yet);
1531 I haven't tested it, documented it, or considered the
1532 threading-safeness of it.
1533 If this code breaks, please contact both Yoshioka and me.
1535 /*---------------------------------------------------*/
1537 /*---------------------------------------------------*/
1539 return version like "0.9.5d, 4-Sept-1999".
1541 const char * BZ_API(BZ2_bzlibVersion
)(void)
1548 /*---------------------------------------------------*/
1550 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1553 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1555 # define SET_BINARY_MODE(file)
1558 BZFILE
* bzopen_or_bzdopen
1559 ( const char *path
, /* no use when bzdopen */
1560 int fd
, /* no use when bzdopen */
1562 int open_mode
) /* bzopen: 0, bzdopen:1 */
1565 char unused
[BZ_MAX_UNUSED
];
1566 int blockSize100k
= 9;
1568 char mode2
[10] = "";
1570 BZFILE
*bzfp
= NULL
;
1572 int workFactor
= 30;
1576 if (mode
== NULL
) return NULL
;
1584 smallMode
= 1; break;
1586 if (isdigit((int)(*mode
))) {
1587 blockSize100k
= *mode
-BZ_HDR_0
;
1592 strcat(mode2
, writing
? "w" : "r" );
1593 strcat(mode2
,"b"); /* binary mode */
1596 if (path
==NULL
|| strcmp(path
,"")==0) {
1597 fp
= (writing
? stdout
: stdin
);
1598 SET_BINARY_MODE(fp
);
1600 fp
= fopen(path
,mode2
);
1603 #ifdef BZ_STRICT_ANSI
1606 fp
= fdopen(fd
,mode2
);
1609 if (fp
== NULL
) return NULL
;
1612 /* Guard against total chaos and anarchy -- JRS */
1613 if (blockSize100k
< 1) blockSize100k
= 1;
1614 if (blockSize100k
> 9) blockSize100k
= 9;
1615 bzfp
= BZ2_bzWriteOpen(&bzerr
,fp
,blockSize100k
,
1616 verbosity
,workFactor
);
1618 bzfp
= BZ2_bzReadOpen(&bzerr
,fp
,verbosity
,smallMode
,
1622 if (fp
!= stdin
&& fp
!= stdout
) fclose(fp
);
1629 /*---------------------------------------------------*/
1631 open file for read or write.
1632 ex) bzopen("file","w9")
1633 case path="" or NULL => use stdin or stdout.
1635 BZFILE
* BZ_API(BZ2_bzopen
)
1639 return bzopen_or_bzdopen(path
,-1,mode
,/*bzopen*/0);
1643 /*---------------------------------------------------*/
1644 BZFILE
* BZ_API(BZ2_bzdopen
)
1648 return bzopen_or_bzdopen(NULL
,fd
,mode
,/*bzdopen*/1);
1652 /*---------------------------------------------------*/
1653 int BZ_API(BZ2_bzread
) (BZFILE
* b
, void* buf
, int len
)
1656 if (((bzFile
*)b
)->lastErr
== BZ_STREAM_END
) return 0;
1657 nread
= BZ2_bzRead(&bzerr
,b
,buf
,len
);
1658 if (bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) {
1666 /*---------------------------------------------------*/
1667 int BZ_API(BZ2_bzwrite
) (BZFILE
* b
, void* buf
, int len
)
1671 BZ2_bzWrite(&bzerr
,b
,buf
,len
);
1680 /*---------------------------------------------------*/
1681 int BZ_API(BZ2_bzflush
) (BZFILE
*b
)
1683 /* do nothing now... */
1688 /*---------------------------------------------------*/
1689 void BZ_API(BZ2_bzclose
) (BZFILE
* b
)
1694 if (b
==NULL
) {return;}
1695 fp
= ((bzFile
*)b
)->handle
;
1696 if(((bzFile
*)b
)->writing
){
1697 BZ2_bzWriteClose(&bzerr
,b
,0,NULL
,NULL
);
1699 BZ2_bzWriteClose(NULL
,b
,1,NULL
,NULL
);
1702 BZ2_bzReadClose(&bzerr
,b
);
1704 if(fp
!=stdin
&& fp
!=stdout
){
1710 /*---------------------------------------------------*/
1712 return last error code
1714 static const char *bzerrorstrings
[] = {
1725 ,"???" /* for future */
1726 ,"???" /* for future */
1727 ,"???" /* for future */
1728 ,"???" /* for future */
1729 ,"???" /* for future */
1730 ,"???" /* for future */
1734 const char * BZ_API(BZ2_bzerror
) (BZFILE
*b
, int *errnum
)
1736 int err
= ((bzFile
*)b
)->lastErr
;
1740 return bzerrorstrings
[err
*-1];
1744 #endif /* BZ_NO_COMPRESS */
1746 /*-------------------------------------------------------------*/
1747 /*--- end bzlib.c ---*/
1748 /*-------------------------------------------------------------*/