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