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"
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, 15 February 2005.\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"
88
void BZ2_bz__AssertH__fail ( int errcode ) { (void)errcode; }
89
void bz_internal_error ( int errcode ) { (void)errcode; }
93
/*---------------------------------------------------*/
95
int bz_config_ok ( void )
97
if (sizeof(int) != 4) return 0;
98
if (sizeof(short) != 2) return 0;
99
if (sizeof(char) != 1) return 0;
104
/*---------------------------------------------------*/
106
void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
108
void* v = malloc ( items * size );
109
(void)opaque; /* Ferret modification to remove compile warning */
114
void default_bzfree ( void* opaque, void* addr )
116
if (addr != NULL) free ( addr );
117
(void)opaque; /* Ferret modification to remove compile warning */
121
/*---------------------------------------------------*/
123
void prepare_new_block ( EState* s )
128
s->state_out_pos = 0;
129
BZ_INITIALISE_CRC ( s->blockCRC );
130
for (i = 0; i < 256; i++) s->inUse[i] = False;
135
/*---------------------------------------------------*/
137
void init_RL ( EState* s )
139
s->state_in_ch = 256;
145
Bool isempty_RL ( EState* s )
147
if (s->state_in_ch < 256 && s->state_in_len > 0)
153
/*---------------------------------------------------*/
154
int BZ_API(BZ2_bzCompressInit)
163
if (!bz_config_ok()) return BZ_CONFIG_ERROR;
166
blockSize100k < 1 || blockSize100k > 9 ||
167
workFactor < 0 || workFactor > 250)
168
return BZ_PARAM_ERROR;
170
if (workFactor == 0) workFactor = 30;
171
if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
172
if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
174
s = BZALLOC( sizeof(EState) );
175
if (s == NULL) return BZ_MEM_ERROR;
182
n = 100000 * blockSize100k;
183
s->arr1 = BZALLOC( n * sizeof(UInt32) );
184
s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
185
s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
187
if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
188
if (s->arr1 != NULL) BZFREE(s->arr1);
189
if (s->arr2 != NULL) BZFREE(s->arr2);
190
if (s->ftab != NULL) BZFREE(s->ftab);
191
if (s != NULL) BZFREE(s);
196
s->state = BZ_S_INPUT;
197
s->mode = BZ_M_RUNNING;
199
s->blockSize100k = blockSize100k;
200
s->nblockMAX = 100000 * blockSize100k - 19;
201
s->verbosity = verbosity;
202
s->workFactor = workFactor;
204
s->block = (UChar*)s->arr2;
205
s->mtfv = (UInt16*)s->arr1;
207
s->ptr = (UInt32*)s->arr1;
210
strm->total_in_lo32 = 0;
211
strm->total_in_hi32 = 0;
212
strm->total_out_lo32 = 0;
213
strm->total_out_hi32 = 0;
215
prepare_new_block ( s );
220
/*---------------------------------------------------*/
222
void add_pair_to_block ( EState* s )
225
UChar ch = (UChar)(s->state_in_ch);
226
for (i = 0; i < s->state_in_len; i++) {
227
BZ_UPDATE_CRC( s->blockCRC, ch );
229
s->inUse[s->state_in_ch] = True;
230
switch (s->state_in_len) {
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++;
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++;
244
s->inUse[s->state_in_len-4] = True;
245
s->block[s->nblock] = (UChar)ch; s->nblock++;
246
s->block[s->nblock] = (UChar)ch; s->nblock++;
247
s->block[s->nblock] = (UChar)ch; s->nblock++;
248
s->block[s->nblock] = (UChar)ch; s->nblock++;
249
s->block[s->nblock] = ((UChar)(s->state_in_len-4));
256
/*---------------------------------------------------*/
258
void flush_RL ( EState* s )
260
if (s->state_in_ch < 256) add_pair_to_block ( s );
265
/*---------------------------------------------------*/
266
#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
268
UInt32 zchh = (UInt32)(zchh0); \
269
/*-- fast track the common case --*/ \
270
if (zchh != zs->state_in_ch && \
271
zs->state_in_len == 1) { \
272
UChar ch = (UChar)(zs->state_in_ch); \
273
BZ_UPDATE_CRC( zs->blockCRC, ch ); \
274
zs->inUse[zs->state_in_ch] = True; \
275
zs->block[zs->nblock] = (UChar)ch; \
277
zs->state_in_ch = zchh; \
280
/*-- general, uncommon cases --*/ \
281
if (zchh != zs->state_in_ch || \
282
zs->state_in_len == 255) { \
283
if (zs->state_in_ch < 256) \
284
add_pair_to_block ( zs ); \
285
zs->state_in_ch = zchh; \
286
zs->state_in_len = 1; \
288
zs->state_in_len++; \
293
/*---------------------------------------------------*/
295
Bool copy_input_until_stop ( EState* s )
297
Bool progress_in = False;
299
if (s->mode == BZ_M_RUNNING) {
301
/*-- fast track the common case --*/
303
/*-- block full? --*/
304
if (s->nblock >= s->nblockMAX) break;
306
if (s->strm->avail_in == 0) break;
308
ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
311
s->strm->total_in_lo32++;
312
if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
317
/*-- general, uncommon case --*/
319
/*-- block full? --*/
320
if (s->nblock >= s->nblockMAX) break;
322
if (s->strm->avail_in == 0) break;
323
/*-- flush/finish end? --*/
324
if (s->avail_in_expect == 0) break;
326
ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
329
s->strm->total_in_lo32++;
330
if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
331
s->avail_in_expect--;
338
/*---------------------------------------------------*/
340
Bool copy_output_until_stop ( EState* s )
342
Bool progress_out = False;
346
/*-- no output space? --*/
347
if (s->strm->avail_out == 0) break;
349
/*-- block done? --*/
350
if (s->state_out_pos >= s->numZ) break;
353
*(s->strm->next_out) = s->zbits[s->state_out_pos];
355
s->strm->avail_out--;
357
s->strm->total_out_lo32++;
358
if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
365
/*---------------------------------------------------*/
367
Bool handle_compress ( bz_stream* strm )
369
Bool progress_in = False;
370
Bool progress_out = False;
371
EState* s = strm->state;
375
if (s->state == BZ_S_OUTPUT) {
376
progress_out |= copy_output_until_stop ( s );
377
if (s->state_out_pos < s->numZ) break;
378
if (s->mode == BZ_M_FINISHING &&
379
s->avail_in_expect == 0 &&
380
isempty_RL(s)) break;
381
prepare_new_block ( s );
382
s->state = BZ_S_INPUT;
383
if (s->mode == BZ_M_FLUSHING &&
384
s->avail_in_expect == 0 &&
385
isempty_RL(s)) break;
388
if (s->state == BZ_S_INPUT) {
389
progress_in |= copy_input_until_stop ( s );
390
if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
392
BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
393
s->state = BZ_S_OUTPUT;
396
if (s->nblock >= s->nblockMAX) {
397
BZ2_compressBlock ( s, False );
398
s->state = BZ_S_OUTPUT;
401
if (s->strm->avail_in == 0) {
408
return progress_in || progress_out;
412
/*---------------------------------------------------*/
413
int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
417
if (strm == NULL) return BZ_PARAM_ERROR;
419
if (s == NULL) return BZ_PARAM_ERROR;
420
if (s->strm != strm) return BZ_PARAM_ERROR;
426
return BZ_SEQUENCE_ERROR;
429
if (action == BZ_RUN) {
430
progress = handle_compress ( strm );
431
return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
434
if (action == BZ_FLUSH) {
435
s->avail_in_expect = strm->avail_in;
436
s->mode = BZ_M_FLUSHING;
440
if (action == BZ_FINISH) {
441
s->avail_in_expect = strm->avail_in;
442
s->mode = BZ_M_FINISHING;
446
return BZ_PARAM_ERROR;
449
if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
450
if (s->avail_in_expect != s->strm->avail_in)
451
return BZ_SEQUENCE_ERROR;
452
progress = handle_compress ( strm );
453
if (s->avail_in_expect > 0 || !isempty_RL(s) ||
454
s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
455
s->mode = BZ_M_RUNNING;
459
if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
460
if (s->avail_in_expect != s->strm->avail_in)
461
return BZ_SEQUENCE_ERROR;
462
progress = handle_compress ( strm );
463
if (!progress) return BZ_SEQUENCE_ERROR;
464
if (s->avail_in_expect > 0 || !isempty_RL(s) ||
465
s->state_out_pos < s->numZ) return BZ_FINISH_OK;
467
return BZ_STREAM_END;
469
return BZ_OK; /*--not reached--*/
473
/*---------------------------------------------------*/
474
int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
477
if (strm == NULL) return BZ_PARAM_ERROR;
479
if (s == NULL) return BZ_PARAM_ERROR;
480
if (s->strm != strm) return BZ_PARAM_ERROR;
482
if (s->arr1 != NULL) BZFREE(s->arr1);
483
if (s->arr2 != NULL) BZFREE(s->arr2);
484
if (s->ftab != NULL) BZFREE(s->ftab);
493
/*---------------------------------------------------*/
494
/*--- Decompression stuff ---*/
495
/*---------------------------------------------------*/
497
/*---------------------------------------------------*/
498
int BZ_API(BZ2_bzDecompressInit)
505
if (!bz_config_ok()) return BZ_CONFIG_ERROR;
507
if (strm == NULL) return BZ_PARAM_ERROR;
508
if (small != 0 && small != 1) return BZ_PARAM_ERROR;
509
if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
511
if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
512
if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
514
s = BZALLOC( sizeof(DState) );
515
if (s == NULL) return BZ_MEM_ERROR;
518
s->state = BZ_X_MAGIC_1;
521
s->calculatedCombinedCRC = 0;
522
strm->total_in_lo32 = 0;
523
strm->total_in_hi32 = 0;
524
strm->total_out_lo32 = 0;
525
strm->total_out_hi32 = 0;
526
s->smallDecompress = (Bool)small;
531
s->verbosity = verbosity;
537
/*---------------------------------------------------*/
538
/* Return True iff data corruption is discovered.
539
Returns False if there is no problem.
542
Bool unRLE_obuf_to_output_FAST ( DState* s )
546
if (s->blockRandomised) {
549
/* try to finish existing run */
551
if (s->strm->avail_out == 0) return False;
552
if (s->state_out_len == 0) break;
553
*( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
554
BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
557
s->strm->avail_out--;
558
s->strm->total_out_lo32++;
559
if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
562
/* can a new run be started? */
563
if (s->nblock_used == s->save_nblock+1) return False;
565
/* Only caused by corrupt data stream? */
566
if (s->nblock_used > s->save_nblock+1)
569
s->state_out_len = 1;
570
s->state_out_ch = s->k0;
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 = 2;
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
s->state_out_len = 3;
583
BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
584
k1 ^= BZ_RAND_MASK; s->nblock_used++;
585
if (s->nblock_used == s->save_nblock+1) continue;
586
if (k1 != s->k0) { s->k0 = k1; continue; };
588
BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
589
k1 ^= BZ_RAND_MASK; s->nblock_used++;
590
s->state_out_len = ((Int32)k1) + 4;
591
BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
592
s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
598
UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
599
UChar c_state_out_ch = s->state_out_ch;
600
Int32 c_state_out_len = s->state_out_len;
601
Int32 c_nblock_used = s->nblock_used;
603
UInt32* c_tt = s->tt;
604
UInt32 c_tPos = s->tPos;
605
char* cs_next_out = s->strm->next_out;
606
unsigned int cs_avail_out = s->strm->avail_out;
609
UInt32 avail_out_INIT = cs_avail_out;
610
Int32 s_save_nblockPP = s->save_nblock+1;
611
unsigned int total_out_lo32_old;
615
/* try to finish existing run */
616
if (c_state_out_len > 0) {
618
if (cs_avail_out == 0) goto return_notr;
619
if (c_state_out_len == 1) break;
620
*( (UChar*)(cs_next_out) ) = c_state_out_ch;
621
BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
626
s_state_out_len_eq_one:
628
if (cs_avail_out == 0) {
629
c_state_out_len = 1; goto return_notr;
631
*( (UChar*)(cs_next_out) ) = c_state_out_ch;
632
BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
637
/* Only caused by corrupt data stream? */
638
if (c_nblock_used > s_save_nblockPP)
641
/* can a new run be started? */
642
if (c_nblock_used == s_save_nblockPP) {
643
c_state_out_len = 0; goto return_notr;
645
c_state_out_ch = c_k0;
646
BZ_GET_FAST_C(k1); c_nblock_used++;
648
c_k0 = k1; goto s_state_out_len_eq_one;
650
if (c_nblock_used == s_save_nblockPP)
651
goto s_state_out_len_eq_one;
654
BZ_GET_FAST_C(k1); c_nblock_used++;
655
if (c_nblock_used == s_save_nblockPP) continue;
656
if (k1 != c_k0) { c_k0 = k1; continue; };
659
BZ_GET_FAST_C(k1); c_nblock_used++;
660
if (c_nblock_used == s_save_nblockPP) continue;
661
if (k1 != c_k0) { c_k0 = k1; continue; };
663
BZ_GET_FAST_C(k1); c_nblock_used++;
664
c_state_out_len = ((Int32)k1) + 4;
665
BZ_GET_FAST_C(c_k0); c_nblock_used++;
669
total_out_lo32_old = s->strm->total_out_lo32;
670
s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
671
if (s->strm->total_out_lo32 < total_out_lo32_old)
672
s->strm->total_out_hi32++;
675
s->calculatedBlockCRC = c_calculatedBlockCRC;
676
s->state_out_ch = c_state_out_ch;
677
s->state_out_len = c_state_out_len;
678
s->nblock_used = c_nblock_used;
682
s->strm->next_out = cs_next_out;
683
s->strm->avail_out = cs_avail_out;
691
/*---------------------------------------------------*/
692
__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
698
mid = (nb + na) >> 1;
699
if (indx >= cftab[mid]) nb = mid; else na = mid;
701
while (na - nb != 1);
706
/*---------------------------------------------------*/
707
/* Return True iff data corruption is discovered.
708
Returns False if there is no problem.
711
Bool unRLE_obuf_to_output_SMALL ( DState* s )
715
if (s->blockRandomised) {
718
/* try to finish existing run */
720
if (s->strm->avail_out == 0) return False;
721
if (s->state_out_len == 0) break;
722
*( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
723
BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
726
s->strm->avail_out--;
727
s->strm->total_out_lo32++;
728
if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
731
/* can a new run be started? */
732
if (s->nblock_used == s->save_nblock+1) return False;
734
/* Only caused by corrupt data stream? */
735
if (s->nblock_used > s->save_nblock+1)
738
s->state_out_len = 1;
739
s->state_out_ch = s->k0;
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 = 2;
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
s->state_out_len = 3;
752
BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
753
k1 ^= BZ_RAND_MASK; s->nblock_used++;
754
if (s->nblock_used == s->save_nblock+1) continue;
755
if (k1 != s->k0) { s->k0 = k1; continue; };
757
BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
758
k1 ^= BZ_RAND_MASK; s->nblock_used++;
759
s->state_out_len = ((Int32)k1) + 4;
760
BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
761
s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
767
/* try to finish existing run */
769
if (s->strm->avail_out == 0) return False;
770
if (s->state_out_len == 0) break;
771
*( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
772
BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
775
s->strm->avail_out--;
776
s->strm->total_out_lo32++;
777
if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
780
/* can a new run be started? */
781
if (s->nblock_used == s->save_nblock+1) return False;
783
/* Only caused by corrupt data stream? */
784
if (s->nblock_used > s->save_nblock+1)
787
s->state_out_len = 1;
788
s->state_out_ch = s->k0;
789
BZ_GET_SMALL(k1); s->nblock_used++;
790
if (s->nblock_used == s->save_nblock+1) continue;
791
if (k1 != s->k0) { s->k0 = k1; continue; };
793
s->state_out_len = 2;
794
BZ_GET_SMALL(k1); s->nblock_used++;
795
if (s->nblock_used == s->save_nblock+1) continue;
796
if (k1 != s->k0) { s->k0 = k1; continue; };
798
s->state_out_len = 3;
799
BZ_GET_SMALL(k1); s->nblock_used++;
800
if (s->nblock_used == s->save_nblock+1) continue;
801
if (k1 != s->k0) { s->k0 = k1; continue; };
803
BZ_GET_SMALL(k1); s->nblock_used++;
804
s->state_out_len = ((Int32)k1) + 4;
805
BZ_GET_SMALL(s->k0); s->nblock_used++;
812
/*---------------------------------------------------*/
813
int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
817
if (strm == NULL) return BZ_PARAM_ERROR;
819
if (s == NULL) return BZ_PARAM_ERROR;
820
if (s->strm != strm) return BZ_PARAM_ERROR;
823
if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
824
if (s->state == BZ_X_OUTPUT) {
825
if (s->smallDecompress)
826
corrupt = unRLE_obuf_to_output_SMALL ( s ); else
827
corrupt = unRLE_obuf_to_output_FAST ( s );
828
if (corrupt) return BZ_DATA_ERROR;
829
if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
830
BZ_FINALISE_CRC ( s->calculatedBlockCRC );
831
if (s->verbosity >= 3)
832
VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
833
s->calculatedBlockCRC );
834
if (s->verbosity >= 2) VPrintf0 ( "]" );
835
if (s->calculatedBlockCRC != s->storedBlockCRC)
836
return BZ_DATA_ERROR;
837
s->calculatedCombinedCRC
838
= (s->calculatedCombinedCRC << 1) |
839
(s->calculatedCombinedCRC >> 31);
840
s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
841
s->state = BZ_X_BLKHDR_1;
846
if (s->state >= BZ_X_MAGIC_1) {
847
Int32 r = BZ2_decompress ( s );
848
if (r == BZ_STREAM_END) {
849
if (s->verbosity >= 3)
850
VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
851
s->storedCombinedCRC, s->calculatedCombinedCRC );
852
if (s->calculatedCombinedCRC != s->storedCombinedCRC)
853
return BZ_DATA_ERROR;
856
if (s->state != BZ_X_OUTPUT) return r;
862
return 0; /*NOTREACHED*/
866
/*---------------------------------------------------*/
867
int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
870
if (strm == NULL) return BZ_PARAM_ERROR;
872
if (s == NULL) return BZ_PARAM_ERROR;
873
if (s->strm != strm) return BZ_PARAM_ERROR;
875
if (s->tt != NULL) BZFREE(s->tt);
876
if (s->ll16 != NULL) BZFREE(s->ll16);
877
if (s->ll4 != NULL) BZFREE(s->ll4);
887
/*---------------------------------------------------*/
888
/*--- File I/O stuff ---*/
889
/*---------------------------------------------------*/
891
#define BZ_SETERR(eee) \
893
if (bzerror != NULL) *bzerror = eee; \
894
if (bzf != NULL) bzf->lastErr = eee; \
900
Char buf[BZ_MAX_UNUSED];
910
/*---------------------------------------------*/
911
static Bool myfeof ( FILE* f )
913
Int32 c = fgetc ( f );
914
if (c == EOF) return True;
920
/*---------------------------------------------------*/
921
BZFILE* BZ_API(BZ2_bzWriteOpen)
934
(blockSize100k < 1 || blockSize100k > 9) ||
935
(workFactor < 0 || workFactor > 250) ||
936
(verbosity < 0 || verbosity > 4))
937
{ BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
940
{ BZ_SETERR(BZ_IO_ERROR); return NULL; };
942
bzf = malloc ( sizeof(bzFile) );
944
{ BZ_SETERR(BZ_MEM_ERROR); return NULL; };
947
bzf->initialisedOk = False;
951
bzf->strm.bzalloc = NULL;
952
bzf->strm.bzfree = NULL;
953
bzf->strm.opaque = NULL;
955
if (workFactor == 0) workFactor = 30;
956
ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
957
verbosity, workFactor );
959
{ BZ_SETERR(ret); free(bzf); return NULL; };
961
bzf->strm.avail_in = 0;
962
bzf->initialisedOk = True;
968
/*---------------------------------------------------*/
969
void BZ_API(BZ2_bzWrite)
976
bzFile* bzf = (bzFile*)b;
979
if (bzf == NULL || buf == NULL || len < 0)
980
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
982
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
983
if (ferror(bzf->handle))
984
{ BZ_SETERR(BZ_IO_ERROR); return; };
987
{ BZ_SETERR(BZ_OK); return; };
989
bzf->strm.avail_in = len;
990
bzf->strm.next_in = buf;
993
bzf->strm.avail_out = BZ_MAX_UNUSED;
994
bzf->strm.next_out = bzf->buf;
995
ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
996
if (ret != BZ_RUN_OK)
997
{ BZ_SETERR(ret); return; };
999
if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1000
n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1001
n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1003
if (n != n2 || ferror(bzf->handle))
1004
{ BZ_SETERR(BZ_IO_ERROR); return; };
1007
if (bzf->strm.avail_in == 0)
1008
{ BZ_SETERR(BZ_OK); return; };
1013
/*---------------------------------------------------*/
1014
void BZ_API(BZ2_bzWriteClose)
1018
unsigned int* nbytes_in,
1019
unsigned int* nbytes_out )
1021
BZ2_bzWriteClose64 ( bzerror, b, abandon,
1022
nbytes_in, NULL, nbytes_out, NULL );
1026
void BZ_API(BZ2_bzWriteClose64)
1030
unsigned int* nbytes_in_lo32,
1031
unsigned int* nbytes_in_hi32,
1032
unsigned int* nbytes_out_lo32,
1033
unsigned int* nbytes_out_hi32 )
1036
bzFile* bzf = (bzFile*)b;
1039
{ BZ_SETERR(BZ_OK); return; };
1040
if (!(bzf->writing))
1041
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1042
if (ferror(bzf->handle))
1043
{ BZ_SETERR(BZ_IO_ERROR); return; };
1045
if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1046
if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1047
if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1048
if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1050
if ((!abandon) && bzf->lastErr == BZ_OK) {
1052
bzf->strm.avail_out = BZ_MAX_UNUSED;
1053
bzf->strm.next_out = bzf->buf;
1054
ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1055
if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1056
{ BZ_SETERR(ret); return; };
1058
if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1059
n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1060
n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1062
if (n != n2 || ferror(bzf->handle))
1063
{ BZ_SETERR(BZ_IO_ERROR); return; };
1066
if (ret == BZ_STREAM_END) break;
1070
if ( !abandon && !ferror ( bzf->handle ) ) {
1071
fflush ( bzf->handle );
1072
if (ferror(bzf->handle))
1073
{ BZ_SETERR(BZ_IO_ERROR); return; };
1076
if (nbytes_in_lo32 != NULL)
1077
*nbytes_in_lo32 = bzf->strm.total_in_lo32;
1078
if (nbytes_in_hi32 != NULL)
1079
*nbytes_in_hi32 = bzf->strm.total_in_hi32;
1080
if (nbytes_out_lo32 != NULL)
1081
*nbytes_out_lo32 = bzf->strm.total_out_lo32;
1082
if (nbytes_out_hi32 != NULL)
1083
*nbytes_out_hi32 = bzf->strm.total_out_hi32;
1086
BZ2_bzCompressEnd ( &(bzf->strm) );
1091
/*---------------------------------------------------*/
1092
BZFILE* BZ_API(BZ2_bzReadOpen)
1106
(small != 0 && small != 1) ||
1107
(verbosity < 0 || verbosity > 4) ||
1108
(unused == NULL && nUnused != 0) ||
1109
(unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1110
{ BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1113
{ BZ_SETERR(BZ_IO_ERROR); return NULL; };
1115
bzf = malloc ( sizeof(bzFile) );
1117
{ BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1121
bzf->initialisedOk = False;
1124
bzf->writing = False;
1125
bzf->strm.bzalloc = NULL;
1126
bzf->strm.bzfree = NULL;
1127
bzf->strm.opaque = NULL;
1129
while (nUnused > 0) {
1130
bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1131
unused = ((void*)( 1 + ((UChar*)(unused)) ));
1135
ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1137
{ BZ_SETERR(ret); free(bzf); return NULL; };
1139
bzf->strm.avail_in = bzf->bufN;
1140
bzf->strm.next_in = bzf->buf;
1142
bzf->initialisedOk = True;
1147
/*---------------------------------------------------*/
1148
void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1150
bzFile* bzf = (bzFile*)b;
1154
{ BZ_SETERR(BZ_OK); return; };
1157
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1159
if (bzf->initialisedOk)
1160
(void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1165
/*---------------------------------------------------*/
1166
int BZ_API(BZ2_bzRead)
1173
bzFile* bzf = (bzFile*)b;
1177
if (bzf == NULL || buf == NULL || len < 0)
1178
{ BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1181
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1184
{ BZ_SETERR(BZ_OK); return 0; };
1186
bzf->strm.avail_out = len;
1187
bzf->strm.next_out = buf;
1191
if (ferror(bzf->handle))
1192
{ BZ_SETERR(BZ_IO_ERROR); return 0; };
1194
if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1195
n = fread ( bzf->buf, sizeof(UChar),
1196
BZ_MAX_UNUSED, bzf->handle );
1197
if (ferror(bzf->handle))
1198
{ BZ_SETERR(BZ_IO_ERROR); return 0; };
1200
bzf->strm.avail_in = bzf->bufN;
1201
bzf->strm.next_in = bzf->buf;
1204
ret = BZ2_bzDecompress ( &(bzf->strm) );
1206
if (ret != BZ_OK && ret != BZ_STREAM_END)
1207
{ BZ_SETERR(ret); return 0; };
1209
if (ret == BZ_OK && myfeof(bzf->handle) &&
1210
bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1211
{ BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1213
if (ret == BZ_STREAM_END)
1214
{ BZ_SETERR(BZ_STREAM_END);
1215
return len - bzf->strm.avail_out; };
1216
if (bzf->strm.avail_out == 0)
1217
{ BZ_SETERR(BZ_OK); return len; };
1221
return 0; /*not reached*/
1225
/*---------------------------------------------------*/
1226
void BZ_API(BZ2_bzReadGetUnused)
1232
bzFile* bzf = (bzFile*)b;
1234
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
1235
if (bzf->lastErr != BZ_STREAM_END)
1236
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1237
if (unused == NULL || nUnused == NULL)
1238
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
1241
*nUnused = bzf->strm.avail_in;
1242
*unused = bzf->strm.next_in;
1247
/*---------------------------------------------------*/
1248
/*--- Misc convenience stuff ---*/
1249
/*---------------------------------------------------*/
1251
/*---------------------------------------------------*/
1252
int BZ_API(BZ2_bzBuffToBuffCompress)
1254
unsigned int* destLen,
1256
unsigned int sourceLen,
1264
if (dest == NULL || destLen == NULL ||
1266
blockSize100k < 1 || blockSize100k > 9 ||
1267
verbosity < 0 || verbosity > 4 ||
1268
workFactor < 0 || workFactor > 250)
1269
return BZ_PARAM_ERROR;
1271
if (workFactor == 0) workFactor = 30;
1272
strm.bzalloc = NULL;
1275
ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1276
verbosity, workFactor );
1277
if (ret != BZ_OK) return ret;
1279
strm.next_in = source;
1280
strm.next_out = dest;
1281
strm.avail_in = sourceLen;
1282
strm.avail_out = *destLen;
1284
ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1285
if (ret == BZ_FINISH_OK) goto output_overflow;
1286
if (ret != BZ_STREAM_END) goto errhandler;
1288
/* normal termination */
1289
*destLen -= strm.avail_out;
1290
BZ2_bzCompressEnd ( &strm );
1294
BZ2_bzCompressEnd ( &strm );
1295
return BZ_OUTBUFF_FULL;
1298
BZ2_bzCompressEnd ( &strm );
1303
/*---------------------------------------------------*/
1304
int BZ_API(BZ2_bzBuffToBuffDecompress)
1306
unsigned int* destLen,
1308
unsigned int sourceLen,
1315
if (dest == NULL || destLen == NULL ||
1317
(small != 0 && small != 1) ||
1318
verbosity < 0 || verbosity > 4)
1319
return BZ_PARAM_ERROR;
1321
strm.bzalloc = NULL;
1324
ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1325
if (ret != BZ_OK) return ret;
1327
strm.next_in = source;
1328
strm.next_out = dest;
1329
strm.avail_in = sourceLen;
1330
strm.avail_out = *destLen;
1332
ret = BZ2_bzDecompress ( &strm );
1333
if (ret == BZ_OK) goto output_overflow_or_eof;
1334
if (ret != BZ_STREAM_END) goto errhandler;
1336
/* normal termination */
1337
*destLen -= strm.avail_out;
1338
BZ2_bzDecompressEnd ( &strm );
1341
output_overflow_or_eof:
1342
if (strm.avail_out > 0) {
1343
BZ2_bzDecompressEnd ( &strm );
1344
return BZ_UNEXPECTED_EOF;
1346
BZ2_bzDecompressEnd ( &strm );
1347
return BZ_OUTBUFF_FULL;
1351
BZ2_bzDecompressEnd ( &strm );
1356
/*---------------------------------------------------*/
1358
Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1359
to support better zlib compatibility.
1360
This code is not _officially_ part of libbzip2 (yet);
1361
I haven't tested it, documented it, or considered the
1362
threading-safeness of it.
1363
If this code breaks, please contact both Yoshioka and me.
1365
/*---------------------------------------------------*/
1367
/*---------------------------------------------------*/
1369
return version like "0.9.5d, 4-Sept-1999".
1371
const char * BZ_API(BZ2_bzlibVersion)(void)
1378
/*---------------------------------------------------*/
1380
#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1383
# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1385
# define SET_BINARY_MODE(file)
1388
BZFILE * bzopen_or_bzdopen
1389
( const char *path, /* no use when bzdopen */
1390
int fd, /* no use when bzdopen */
1392
int open_mode) /* bzopen: 0, bzdopen:1 */
1395
char unused[BZ_MAX_UNUSED];
1396
int blockSize100k = 9;
1398
char mode2[10] = "";
1400
BZFILE *bzfp = NULL;
1402
int workFactor = 30;
1406
if (mode == NULL) return NULL;
1414
smallMode = 1; break;
1416
if (isdigit((int)(*mode))) {
1417
blockSize100k = *mode-BZ_HDR_0;
1422
strcat(mode2, writing ? "w" : "r" );
1423
strcat(mode2,"b"); /* binary mode */
1426
if (path==NULL || strcmp(path,"")==0) {
1427
fp = (writing ? stdout : stdin);
1428
SET_BINARY_MODE(fp);
1430
fp = fopen(path,mode2);
1433
#ifdef BZ_STRICT_ANSI
1436
fp = fdopen(fd,mode2);
1439
if (fp == NULL) return NULL;
1442
/* Guard against total chaos and anarchy -- JRS */
1443
if (blockSize100k < 1) blockSize100k = 1;
1444
if (blockSize100k > 9) blockSize100k = 9;
1445
bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1446
verbosity,workFactor);
1448
bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1452
if (fp != stdin && fp != stdout) fclose(fp);
1459
/*---------------------------------------------------*/
1461
open file for read or write.
1462
ex) bzopen("file","w9")
1463
case path="" or NULL => use stdin or stdout.
1465
BZFILE * BZ_API(BZ2_bzopen)
1469
return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1473
/*---------------------------------------------------*/
1474
BZFILE * BZ_API(BZ2_bzdopen)
1478
return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1482
/*---------------------------------------------------*/
1483
int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1486
if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1487
nread = BZ2_bzRead(&bzerr,b,buf,len);
1488
if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1496
/*---------------------------------------------------*/
1497
int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1501
BZ2_bzWrite(&bzerr,b,buf,len);
1510
/*---------------------------------------------------*/
1511
int BZ_API(BZ2_bzflush) (BZFILE *b)
1513
/* do nothing now... */
1514
(void)b; /* Ferret modification to remove compile warning */
1519
/*---------------------------------------------------*/
1520
void BZ_API(BZ2_bzclose) (BZFILE* b)
1525
if (b==NULL) {return;}
1526
fp = ((bzFile *)b)->handle;
1527
if(((bzFile*)b)->writing){
1528
BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1530
BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1533
BZ2_bzReadClose(&bzerr,b);
1535
if(fp!=stdin && fp!=stdout){
1541
/*---------------------------------------------------*/
1543
return last error code
1545
static const char *bzerrorstrings[] = {
1556
,"???" /* for future */
1557
,"???" /* for future */
1558
,"???" /* for future */
1559
,"???" /* for future */
1560
,"???" /* for future */
1561
,"???" /* for future */
1565
const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1567
int err = ((bzFile *)b)->lastErr;
1571
return bzerrorstrings[err*-1];
1576
/*-------------------------------------------------------------*/
1577
/*--- end bzlib.c ---*/
1578
/*-------------------------------------------------------------*/