1
2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
4 /*--- bzlib.c ---*/
5 /*-------------------------------------------------------------*/
6
7 /* ------------------------------------------------------------------
8 This file is part of bzip2/libbzip2, a program and library for
9 lossless, block-sorting data compression.
10
11 bzip2/libbzip2 version 1.0.8 of 13 July 2019
12 Copyright (C) 1996-2019 Julian Seward <[email protected]>
13
14 Please read the WARNING, DISCLAIMER and PATENTS sections in the
15 README file.
16
17 This program is released under the terms of the license contained
18 in the file LICENSE.
19 ------------------------------------------------------------------ */
20
21 /* CHANGES
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.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "bzlib_private.h"
35
36 #ifndef BZ_NO_COMPRESS
37
38 /*---------------------------------------------------*/
39 /*--- Compression stuff ---*/
40 /*---------------------------------------------------*/
41
42
43 /*---------------------------------------------------*/
44 #ifndef BZ_NO_STDIO
BZ2_bz__AssertH__fail(int errcode)45 void BZ2_bz__AssertH__fail ( int errcode )
46 {
47 fprintf(stderr,
48 "\n\nbzip2/libbzip2: internal error number %d.\n"
49 "This is a bug in bzip2/libbzip2, %s.\n"
50 "Please report it to: [email protected]. If this happened\n"
51 "when you were using some program which uses libbzip2 as a\n"
52 "component, you should also report this bug to the author(s)\n"
53 "of that program. Please make an effort to report this bug;\n"
54 "timely and accurate bug reports eventually lead to higher\n"
55 "quality software. Thanks.\n\n",
56 errcode,
57 BZ2_bzlibVersion()
58 );
59
60 if (errcode == 1007) {
61 fprintf(stderr,
62 "\n*** A special note about internal error number 1007 ***\n"
63 "\n"
64 "Experience suggests that a common cause of i.e. 1007\n"
65 "is unreliable memory or other hardware. The 1007 assertion\n"
66 "just happens to cross-check the results of huge numbers of\n"
67 "memory reads/writes, and so acts (unintendedly) as a stress\n"
68 "test of your memory system.\n"
69 "\n"
70 "I suggest the following: try compressing the file again,\n"
71 "possibly monitoring progress in detail with the -vv flag.\n"
72 "\n"
73 "* If the error cannot be reproduced, and/or happens at different\n"
74 " points in compression, you may have a flaky memory system.\n"
75 " Try a memory-test program. I have used Memtest86\n"
76 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
77 " Memtest86 tests memory much more thorougly than your BIOSs\n"
78 " power-on test, and may find failures that the BIOS doesn't.\n"
79 "\n"
80 "* If the error can be repeatably reproduced, this is a bug in\n"
81 " bzip2, and I would very much like to hear about it. Please\n"
82 " let me know, and, ideally, save a copy of the file causing the\n"
83 " problem -- without which I will be unable to investigate it.\n"
84 "\n"
85 );
86 }
87
88 exit(3);
89 }
90 #endif
91
92 #endif /* BZ_NO_COMPRESS */
93
94 /*---------------------------------------------------*/
95 static
bz_config_ok(void)96 int bz_config_ok ( void )
97 {
98 if (sizeof(int) != 4) return 0;
99 if (sizeof(short) != 2) return 0;
100 if (sizeof(char) != 1) return 0;
101 return 1;
102 }
103
104
105 /*---------------------------------------------------*/
106 static
default_bzalloc(void * opaque,Int32 items,Int32 size)107 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
108 {
109 void* v = malloc ( items * size );
110 return v;
111 }
112
113 static
default_bzfree(void * opaque,void * addr)114 void default_bzfree ( void* opaque, void* addr )
115 {
116 if (addr != NULL) free ( addr );
117 }
118
119 #ifndef BZ_NO_COMPRESS
120
121 /*---------------------------------------------------*/
122 static
prepare_new_block(EState * s)123 void prepare_new_block ( EState* s )
124 {
125 Int32 i;
126 s->nblock = 0;
127 s->numZ = 0;
128 s->state_out_pos = 0;
129 BZ_INITIALISE_CRC ( s->blockCRC );
130 for (i = 0; i < 256; i++) s->inUse[i] = False;
131 s->blockNo++;
132 }
133
134
135 /*---------------------------------------------------*/
136 static
init_RL(EState * s)137 void init_RL ( EState* s )
138 {
139 s->state_in_ch = 256;
140 s->state_in_len = 0;
141 }
142
143
144 static
isempty_RL(EState * s)145 Bool isempty_RL ( EState* s )
146 {
147 if (s->state_in_ch < 256 && s->state_in_len > 0)
148 return False; else
149 return True;
150 }
151
152
153 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressInit)154 int BZ_API(BZ2_bzCompressInit)
155 ( bz_stream* strm,
156 int blockSize100k,
157 int verbosity,
158 int workFactor )
159 {
160 Int32 n;
161 EState* s;
162
163 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
164
165 if (strm == NULL ||
166 blockSize100k < 1 || blockSize100k > 9 ||
167 workFactor < 0 || workFactor > 250)
168 return BZ_PARAM_ERROR;
169
170 if (workFactor == 0) workFactor = 30;
171 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
172 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
173
174 s = BZALLOC( sizeof(EState) );
175 if (s == NULL) return BZ_MEM_ERROR;
176 s->strm = strm;
177
178 s->arr1 = NULL;
179 s->arr2 = NULL;
180 s->ftab = NULL;
181
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) );
186
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);
192 return BZ_MEM_ERROR;
193 }
194
195 s->blockNo = 0;
196 s->state = BZ_S_INPUT;
197 s->mode = BZ_M_RUNNING;
198 s->combinedCRC = 0;
199 s->blockSize100k = blockSize100k;
200 s->nblockMAX = 100000 * blockSize100k - 19;
201 s->verbosity = verbosity;
202 s->workFactor = workFactor;
203
204 s->block = (UChar*)s->arr2;
205 s->mtfv = (UInt16*)s->arr1;
206 s->zbits = NULL;
207 s->ptr = (UInt32*)s->arr1;
208
209 strm->state = s;
210 strm->total_in_lo32 = 0;
211 strm->total_in_hi32 = 0;
212 strm->total_out_lo32 = 0;
213 strm->total_out_hi32 = 0;
214 init_RL ( s );
215 prepare_new_block ( s );
216 return BZ_OK;
217 }
218
219
220 /*---------------------------------------------------*/
221 static
add_pair_to_block(EState * s)222 void add_pair_to_block ( EState* s )
223 {
224 Int32 i;
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 );
228 }
229 s->inUse[s->state_in_ch] = True;
230 switch (s->state_in_len) {
231 case 1:
232 s->block[s->nblock] = (UChar)ch; s->nblock++;
233 break;
234 case 2:
235 s->block[s->nblock] = (UChar)ch; s->nblock++;
236 s->block[s->nblock] = (UChar)ch; s->nblock++;
237 break;
238 case 3:
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 break;
243 default:
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));
250 s->nblock++;
251 break;
252 }
253 }
254
255
256 /*---------------------------------------------------*/
257 static
flush_RL(EState * s)258 void flush_RL ( EState* s )
259 {
260 if (s->state_in_ch < 256) add_pair_to_block ( s );
261 init_RL ( s );
262 }
263
264
265 /*---------------------------------------------------*/
266 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
267 { \
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; \
276 zs->nblock++; \
277 zs->state_in_ch = zchh; \
278 } \
279 else \
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; \
287 } else { \
288 zs->state_in_len++; \
289 } \
290 }
291
292
293 /*---------------------------------------------------*/
294 static
copy_input_until_stop(EState * s)295 Bool copy_input_until_stop ( EState* s )
296 {
297 Bool progress_in = False;
298
299 if (s->mode == BZ_M_RUNNING) {
300
301 /*-- fast track the common case --*/
302 while (True) {
303 /*-- block full? --*/
304 if (s->nblock >= s->nblockMAX) break;
305 /*-- no input? --*/
306 if (s->strm->avail_in == 0) break;
307 progress_in = True;
308 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
309 s->strm->next_in++;
310 s->strm->avail_in--;
311 s->strm->total_in_lo32++;
312 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
313 }
314
315 } else {
316
317 /*-- general, uncommon case --*/
318 while (True) {
319 /*-- block full? --*/
320 if (s->nblock >= s->nblockMAX) break;
321 /*-- no input? --*/
322 if (s->strm->avail_in == 0) break;
323 /*-- flush/finish end? --*/
324 if (s->avail_in_expect == 0) break;
325 progress_in = True;
326 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
327 s->strm->next_in++;
328 s->strm->avail_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--;
332 }
333 }
334 return progress_in;
335 }
336
337
338 /*---------------------------------------------------*/
339 static
copy_output_until_stop(EState * s)340 Bool copy_output_until_stop ( EState* s )
341 {
342 Bool progress_out = False;
343
344 while (True) {
345
346 /*-- no output space? --*/
347 if (s->strm->avail_out == 0) break;
348
349 /*-- block done? --*/
350 if (s->state_out_pos >= s->numZ) break;
351
352 progress_out = True;
353 *(s->strm->next_out) = s->zbits[s->state_out_pos];
354 s->state_out_pos++;
355 s->strm->avail_out--;
356 s->strm->next_out++;
357 s->strm->total_out_lo32++;
358 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
359 }
360
361 return progress_out;
362 }
363
364
365 /*---------------------------------------------------*/
366 static
handle_compress(bz_stream * strm)367 Bool handle_compress ( bz_stream* strm )
368 {
369 Bool progress_in = False;
370 Bool progress_out = False;
371 EState* s = strm->state;
372
373 while (True) {
374
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;
386 }
387
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) {
391 flush_RL ( s );
392 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
393 s->state = BZ_S_OUTPUT;
394 }
395 else
396 if (s->nblock >= s->nblockMAX) {
397 BZ2_compressBlock ( s, False );
398 s->state = BZ_S_OUTPUT;
399 }
400 else
401 if (s->strm->avail_in == 0) {
402 break;
403 }
404 }
405
406 }
407
408 return progress_in || progress_out;
409 }
410
411
412 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompress)413 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
414 {
415 Bool progress;
416 EState* s;
417 if (strm == NULL) return BZ_PARAM_ERROR;
418 s = strm->state;
419 if (s == NULL) return BZ_PARAM_ERROR;
420 if (s->strm != strm) return BZ_PARAM_ERROR;
421
422 preswitch:
423 switch (s->mode) {
424
425 case BZ_M_IDLE:
426 return BZ_SEQUENCE_ERROR;
427
428 case BZ_M_RUNNING:
429 if (action == BZ_RUN) {
430 progress = handle_compress ( strm );
431 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
432 }
433 else
434 if (action == BZ_FLUSH) {
435 s->avail_in_expect = strm->avail_in;
436 s->mode = BZ_M_FLUSHING;
437 goto preswitch;
438 }
439 else
440 if (action == BZ_FINISH) {
441 s->avail_in_expect = strm->avail_in;
442 s->mode = BZ_M_FINISHING;
443 goto preswitch;
444 }
445 else
446 return BZ_PARAM_ERROR;
447
448 case BZ_M_FLUSHING:
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;
456 return BZ_RUN_OK;
457
458 case BZ_M_FINISHING:
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;
466 s->mode = BZ_M_IDLE;
467 return BZ_STREAM_END;
468 }
469 return BZ_OK; /*--not reached--*/
470 }
471
472
473 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressEnd)474 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
475 {
476 EState* s;
477 if (strm == NULL) return BZ_PARAM_ERROR;
478 s = strm->state;
479 if (s == NULL) return BZ_PARAM_ERROR;
480 if (s->strm != strm) return BZ_PARAM_ERROR;
481
482 if (s->arr1 != NULL) BZFREE(s->arr1);
483 if (s->arr2 != NULL) BZFREE(s->arr2);
484 if (s->ftab != NULL) BZFREE(s->ftab);
485 BZFREE(strm->state);
486
487 strm->state = NULL;
488
489 return BZ_OK;
490 }
491
492 #endif /* BZ_NO_COMPRESS */
493
494 /*---------------------------------------------------*/
495 /*--- Decompression stuff ---*/
496 /*---------------------------------------------------*/
497
498 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressInit)499 int BZ_API(BZ2_bzDecompressInit)
500 ( bz_stream* strm,
501 int verbosity,
502 int small )
503 {
504 DState* s;
505
506 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
507
508 if (strm == NULL) return BZ_PARAM_ERROR;
509 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
510 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
511
512 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
513 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
514
515 s = BZALLOC( sizeof(DState) );
516 if (s == NULL) return BZ_MEM_ERROR;
517 s->strm = strm;
518 strm->state = s;
519 s->state = BZ_X_MAGIC_1;
520 s->bsLive = 0;
521 s->bsBuff = 0;
522 s->calculatedCombinedCRC = 0;
523 strm->total_in_lo32 = 0;
524 strm->total_in_hi32 = 0;
525 strm->total_out_lo32 = 0;
526 strm->total_out_hi32 = 0;
527 s->smallDecompress = (Bool)small;
528 s->ll4 = NULL;
529 s->ll16 = NULL;
530 s->tt = NULL;
531 s->currBlockNo = 0;
532 s->verbosity = verbosity;
533
534 return BZ_OK;
535 }
536
537
538 /*---------------------------------------------------*/
539 /* Return True iff data corruption is discovered.
540 Returns False if there is no problem.
541 */
542 static
unRLE_obuf_to_output_FAST(DState * s)543 Bool unRLE_obuf_to_output_FAST ( DState* s )
544 {
545 UChar k1;
546
547 if (s->blockRandomised) {
548
549 while (True) {
550 /* try to finish existing run */
551 while (True) {
552 if (s->strm->avail_out == 0) return False;
553 if (s->state_out_len == 0) break;
554 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
555 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
556 s->state_out_len--;
557 s->strm->next_out++;
558 s->strm->avail_out--;
559 s->strm->total_out_lo32++;
560 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
561 }
562
563 /* can a new run be started? */
564 if (s->nblock_used == s->save_nblock+1) return False;
565
566 /* Only caused by corrupt data stream? */
567 if (s->nblock_used > s->save_nblock+1)
568 return True;
569
570 s->state_out_len = 1;
571 s->state_out_ch = s->k0;
572 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
573 k1 ^= BZ_RAND_MASK; s->nblock_used++;
574 if (s->nblock_used == s->save_nblock+1) continue;
575 if (k1 != s->k0) { s->k0 = k1; continue; };
576
577 s->state_out_len = 2;
578 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
579 k1 ^= BZ_RAND_MASK; s->nblock_used++;
580 if (s->nblock_used == s->save_nblock+1) continue;
581 if (k1 != s->k0) { s->k0 = k1; continue; };
582
583 s->state_out_len = 3;
584 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
585 k1 ^= BZ_RAND_MASK; s->nblock_used++;
586 if (s->nblock_used == s->save_nblock+1) continue;
587 if (k1 != s->k0) { s->k0 = k1; continue; };
588
589 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
590 k1 ^= BZ_RAND_MASK; s->nblock_used++;
591 s->state_out_len = ((Int32)k1) + 4;
592 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
593 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
594 }
595
596 } else {
597
598 /* restore */
599 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
600 UChar c_state_out_ch = s->state_out_ch;
601 Int32 c_state_out_len = s->state_out_len;
602 Int32 c_nblock_used = s->nblock_used;
603 Int32 c_k0 = s->k0;
604 UInt32* c_tt = s->tt;
605 UInt32 c_tPos = s->tPos;
606 char* cs_next_out = s->strm->next_out;
607 unsigned int cs_avail_out = s->strm->avail_out;
608 Int32 ro_blockSize100k = s->blockSize100k;
609 /* end restore */
610
611 UInt32 avail_out_INIT = cs_avail_out;
612 Int32 s_save_nblockPP = s->save_nblock+1;
613 unsigned int total_out_lo32_old;
614
615 while (True) {
616
617 /* try to finish existing run */
618 if (c_state_out_len > 0) {
619 while (True) {
620 if (cs_avail_out == 0) goto return_notr;
621 if (c_state_out_len == 1) break;
622 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
623 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
624 c_state_out_len--;
625 cs_next_out++;
626 cs_avail_out--;
627 }
628 s_state_out_len_eq_one:
629 {
630 if (cs_avail_out == 0) {
631 c_state_out_len = 1; goto return_notr;
632 };
633 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
634 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
635 cs_next_out++;
636 cs_avail_out--;
637 }
638 }
639 /* Only caused by corrupt data stream? */
640 if (c_nblock_used > s_save_nblockPP)
641 return True;
642
643 /* can a new run be started? */
644 if (c_nblock_used == s_save_nblockPP) {
645 c_state_out_len = 0; goto return_notr;
646 };
647 c_state_out_ch = c_k0;
648 BZ_GET_FAST_C(k1); c_nblock_used++;
649 if (k1 != c_k0) {
650 c_k0 = k1; goto s_state_out_len_eq_one;
651 };
652 if (c_nblock_used == s_save_nblockPP)
653 goto s_state_out_len_eq_one;
654
655 c_state_out_len = 2;
656 BZ_GET_FAST_C(k1); c_nblock_used++;
657 if (c_nblock_used == s_save_nblockPP) continue;
658 if (k1 != c_k0) { c_k0 = k1; continue; };
659
660 c_state_out_len = 3;
661 BZ_GET_FAST_C(k1); c_nblock_used++;
662 if (c_nblock_used == s_save_nblockPP) continue;
663 if (k1 != c_k0) { c_k0 = k1; continue; };
664
665 BZ_GET_FAST_C(k1); c_nblock_used++;
666 c_state_out_len = ((Int32)k1) + 4;
667 BZ_GET_FAST_C(c_k0); c_nblock_used++;
668 }
669
670 return_notr:
671 total_out_lo32_old = s->strm->total_out_lo32;
672 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
673 if (s->strm->total_out_lo32 < total_out_lo32_old)
674 s->strm->total_out_hi32++;
675
676 /* save */
677 s->calculatedBlockCRC = c_calculatedBlockCRC;
678 s->state_out_ch = c_state_out_ch;
679 s->state_out_len = c_state_out_len;
680 s->nblock_used = c_nblock_used;
681 s->k0 = c_k0;
682 s->tt = c_tt;
683 s->tPos = c_tPos;
684 s->strm->next_out = cs_next_out;
685 s->strm->avail_out = cs_avail_out;
686 /* end save */
687 }
688 return False;
689 }
690
691
692
693 /*---------------------------------------------------*/
BZ2_indexIntoF(Int32 indx,Int32 * cftab)694 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
695 {
696 Int32 nb, na, mid;
697 nb = 0;
698 na = 256;
699 do {
700 mid = (nb + na) >> 1;
701 if (indx >= cftab[mid]) nb = mid; else na = mid;
702 }
703 while (na - nb != 1);
704 return nb;
705 }
706
707
708 /*---------------------------------------------------*/
709 /* Return True iff data corruption is discovered.
710 Returns False if there is no problem.
711 */
712 static
unRLE_obuf_to_output_SMALL(DState * s)713 Bool unRLE_obuf_to_output_SMALL ( DState* s )
714 {
715 UChar k1;
716
717 if (s->blockRandomised) {
718
719 while (True) {
720 /* try to finish existing run */
721 while (True) {
722 if (s->strm->avail_out == 0) return False;
723 if (s->state_out_len == 0) break;
724 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
725 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
726 s->state_out_len--;
727 s->strm->next_out++;
728 s->strm->avail_out--;
729 s->strm->total_out_lo32++;
730 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
731 }
732
733 /* can a new run be started? */
734 if (s->nblock_used == s->save_nblock+1) return False;
735
736 /* Only caused by corrupt data stream? */
737 if (s->nblock_used > s->save_nblock+1)
738 return True;
739
740 s->state_out_len = 1;
741 s->state_out_ch = s->k0;
742 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
743 k1 ^= BZ_RAND_MASK; s->nblock_used++;
744 if (s->nblock_used == s->save_nblock+1) continue;
745 if (k1 != s->k0) { s->k0 = k1; continue; };
746
747 s->state_out_len = 2;
748 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
749 k1 ^= BZ_RAND_MASK; s->nblock_used++;
750 if (s->nblock_used == s->save_nblock+1) continue;
751 if (k1 != s->k0) { s->k0 = k1; continue; };
752
753 s->state_out_len = 3;
754 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
755 k1 ^= BZ_RAND_MASK; s->nblock_used++;
756 if (s->nblock_used == s->save_nblock+1) continue;
757 if (k1 != s->k0) { s->k0 = k1; continue; };
758
759 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
760 k1 ^= BZ_RAND_MASK; s->nblock_used++;
761 s->state_out_len = ((Int32)k1) + 4;
762 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
763 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
764 }
765
766 } else {
767
768 while (True) {
769 /* try to finish existing run */
770 while (True) {
771 if (s->strm->avail_out == 0) return False;
772 if (s->state_out_len == 0) break;
773 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
774 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
775 s->state_out_len--;
776 s->strm->next_out++;
777 s->strm->avail_out--;
778 s->strm->total_out_lo32++;
779 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
780 }
781
782 /* can a new run be started? */
783 if (s->nblock_used == s->save_nblock+1) return False;
784
785 /* Only caused by corrupt data stream? */
786 if (s->nblock_used > s->save_nblock+1)
787 return True;
788
789 s->state_out_len = 1;
790 s->state_out_ch = s->k0;
791 BZ_GET_SMALL(k1); s->nblock_used++;
792 if (s->nblock_used == s->save_nblock+1) continue;
793 if (k1 != s->k0) { s->k0 = k1; continue; };
794
795 s->state_out_len = 2;
796 BZ_GET_SMALL(k1); s->nblock_used++;
797 if (s->nblock_used == s->save_nblock+1) continue;
798 if (k1 != s->k0) { s->k0 = k1; continue; };
799
800 s->state_out_len = 3;
801 BZ_GET_SMALL(k1); s->nblock_used++;
802 if (s->nblock_used == s->save_nblock+1) continue;
803 if (k1 != s->k0) { s->k0 = k1; continue; };
804
805 BZ_GET_SMALL(k1); s->nblock_used++;
806 s->state_out_len = ((Int32)k1) + 4;
807 BZ_GET_SMALL(s->k0); s->nblock_used++;
808 }
809
810 }
811 }
812
813
814 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompress)815 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
816 {
817 Bool corrupt;
818 DState* s;
819 if (strm == NULL) return BZ_PARAM_ERROR;
820 s = strm->state;
821 if (s == NULL) return BZ_PARAM_ERROR;
822 if (s->strm != strm) return BZ_PARAM_ERROR;
823
824 while (True) {
825 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
826 if (s->state == BZ_X_OUTPUT) {
827 if (s->smallDecompress)
828 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
829 corrupt = unRLE_obuf_to_output_FAST ( s );
830 if (corrupt) return BZ_DATA_ERROR;
831 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
832 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
833 if (s->verbosity >= 3)
834 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
835 s->calculatedBlockCRC );
836 if (s->verbosity >= 2) VPrintf0 ( "]" );
837 if (s->calculatedBlockCRC != s->storedBlockCRC)
838 return BZ_DATA_ERROR;
839 s->calculatedCombinedCRC
840 = (s->calculatedCombinedCRC << 1) |
841 (s->calculatedCombinedCRC >> 31);
842 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
843 s->state = BZ_X_BLKHDR_1;
844 } else {
845 return BZ_OK;
846 }
847 }
848 if (s->state >= BZ_X_MAGIC_1) {
849 Int32 r = BZ2_decompress ( s );
850 if (r == BZ_STREAM_END) {
851 if (s->verbosity >= 3)
852 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
853 s->storedCombinedCRC, s->calculatedCombinedCRC );
854 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
855 return BZ_DATA_ERROR;
856 return r;
857 }
858 if (s->state != BZ_X_OUTPUT) return r;
859 }
860 }
861
862 AssertH ( 0, 6001 );
863
864 return 0; /*NOTREACHED*/
865 }
866
867
868 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressEnd)869 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
870 {
871 DState* s;
872 if (strm == NULL) return BZ_PARAM_ERROR;
873 s = strm->state;
874 if (s == NULL) return BZ_PARAM_ERROR;
875 if (s->strm != strm) return BZ_PARAM_ERROR;
876
877 if (s->tt != NULL) BZFREE(s->tt);
878 if (s->ll16 != NULL) BZFREE(s->ll16);
879 if (s->ll4 != NULL) BZFREE(s->ll4);
880
881 BZFREE(strm->state);
882 strm->state = NULL;
883
884 return BZ_OK;
885 }
886
887 #ifndef BZ_NO_COMPRESS
888
889 #ifndef BZ_NO_STDIO
890 /*---------------------------------------------------*/
891 /*--- File I/O stuff ---*/
892 /*---------------------------------------------------*/
893
894 #define BZ_SETERR(eee) \
895 { \
896 if (bzerror != NULL) *bzerror = eee; \
897 if (bzf != NULL) bzf->lastErr = eee; \
898 }
899
900 typedef
901 struct {
902 FILE* handle;
903 Char buf[BZ_MAX_UNUSED];
904 Int32 bufN;
905 Bool writing;
906 bz_stream strm;
907 Int32 lastErr;
908 Bool initialisedOk;
909 }
910 bzFile;
911
912
913 /*---------------------------------------------*/
myfeof(FILE * f)914 static Bool myfeof ( FILE* f )
915 {
916 Int32 c = fgetc ( f );
917 if (c == EOF) return True;
918 ungetc ( c, f );
919 return False;
920 }
921
922
923 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteOpen)924 BZFILE* BZ_API(BZ2_bzWriteOpen)
925 ( int* bzerror,
926 FILE* f,
927 int blockSize100k,
928 int verbosity,
929 int workFactor )
930 {
931 Int32 ret;
932 bzFile* bzf = NULL;
933
934 BZ_SETERR(BZ_OK);
935
936 if (f == NULL ||
937 (blockSize100k < 1 || blockSize100k > 9) ||
938 (workFactor < 0 || workFactor > 250) ||
939 (verbosity < 0 || verbosity > 4))
940 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
941
942 if (ferror(f))
943 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
944
945 bzf = malloc ( sizeof(bzFile) );
946 if (bzf == NULL)
947 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
948
949 BZ_SETERR(BZ_OK);
950 bzf->initialisedOk = False;
951 bzf->bufN = 0;
952 bzf->handle = f;
953 bzf->writing = True;
954 bzf->strm.bzalloc = NULL;
955 bzf->strm.bzfree = NULL;
956 bzf->strm.opaque = NULL;
957
958 if (workFactor == 0) workFactor = 30;
959 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
960 verbosity, workFactor );
961 if (ret != BZ_OK)
962 { BZ_SETERR(ret); free(bzf); return NULL; };
963
964 bzf->strm.avail_in = 0;
965 bzf->initialisedOk = True;
966 return bzf;
967 }
968
969
970
971 /*---------------------------------------------------*/
BZ_API(BZ2_bzWrite)972 void BZ_API(BZ2_bzWrite)
973 ( int* bzerror,
974 BZFILE* b,
975 void* buf,
976 int len )
977 {
978 Int32 n, n2, ret;
979 bzFile* bzf = (bzFile*)b;
980
981 BZ_SETERR(BZ_OK);
982 if (bzf == NULL || buf == NULL || len < 0)
983 { BZ_SETERR(BZ_PARAM_ERROR); return; };
984 if (!(bzf->writing))
985 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
986 if (ferror(bzf->handle))
987 { BZ_SETERR(BZ_IO_ERROR); return; };
988
989 if (len == 0)
990 { BZ_SETERR(BZ_OK); return; };
991
992 bzf->strm.avail_in = len;
993 bzf->strm.next_in = buf;
994
995 while (True) {
996 bzf->strm.avail_out = BZ_MAX_UNUSED;
997 bzf->strm.next_out = bzf->buf;
998 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
999 if (ret != BZ_RUN_OK)
1000 { BZ_SETERR(ret); return; };
1001
1002 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1003 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1004 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1005 n, bzf->handle );
1006 if (n != n2 || ferror(bzf->handle))
1007 { BZ_SETERR(BZ_IO_ERROR); return; };
1008 }
1009
1010 if (bzf->strm.avail_in == 0)
1011 { BZ_SETERR(BZ_OK); return; };
1012 }
1013 }
1014
1015
1016 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteClose)1017 void BZ_API(BZ2_bzWriteClose)
1018 ( int* bzerror,
1019 BZFILE* b,
1020 int abandon,
1021 unsigned int* nbytes_in,
1022 unsigned int* nbytes_out )
1023 {
1024 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1025 nbytes_in, NULL, nbytes_out, NULL );
1026 }
1027
1028
BZ_API(BZ2_bzWriteClose64)1029 void BZ_API(BZ2_bzWriteClose64)
1030 ( int* bzerror,
1031 BZFILE* b,
1032 int abandon,
1033 unsigned int* nbytes_in_lo32,
1034 unsigned int* nbytes_in_hi32,
1035 unsigned int* nbytes_out_lo32,
1036 unsigned int* nbytes_out_hi32 )
1037 {
1038 Int32 n, n2, ret;
1039 bzFile* bzf = (bzFile*)b;
1040
1041 if (bzf == NULL)
1042 { BZ_SETERR(BZ_OK); return; };
1043 if (!(bzf->writing))
1044 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1045 if (ferror(bzf->handle))
1046 { BZ_SETERR(BZ_IO_ERROR); return; };
1047
1048 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1049 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1050 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1051 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1052
1053 if ((!abandon) && bzf->lastErr == BZ_OK) {
1054 while (True) {
1055 bzf->strm.avail_out = BZ_MAX_UNUSED;
1056 bzf->strm.next_out = bzf->buf;
1057 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1058 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1059 { BZ_SETERR(ret); return; };
1060
1061 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1062 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1063 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1064 n, bzf->handle );
1065 if (n != n2 || ferror(bzf->handle))
1066 { BZ_SETERR(BZ_IO_ERROR); return; };
1067 }
1068
1069 if (ret == BZ_STREAM_END) break;
1070 }
1071 }
1072
1073 if ( !abandon && !ferror ( bzf->handle ) ) {
1074 fflush ( bzf->handle );
1075 if (ferror(bzf->handle))
1076 { BZ_SETERR(BZ_IO_ERROR); return; };
1077 }
1078
1079 if (nbytes_in_lo32 != NULL)
1080 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1081 if (nbytes_in_hi32 != NULL)
1082 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1083 if (nbytes_out_lo32 != NULL)
1084 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1085 if (nbytes_out_hi32 != NULL)
1086 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1087
1088 BZ_SETERR(BZ_OK);
1089 BZ2_bzCompressEnd ( &(bzf->strm) );
1090 free ( bzf );
1091 }
1092
1093
1094 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadOpen)1095 BZFILE* BZ_API(BZ2_bzReadOpen)
1096 ( int* bzerror,
1097 FILE* f,
1098 int verbosity,
1099 int small,
1100 void* unused,
1101 int nUnused )
1102 {
1103 bzFile* bzf = NULL;
1104 int ret;
1105
1106 BZ_SETERR(BZ_OK);
1107
1108 if (f == NULL ||
1109 (small != 0 && small != 1) ||
1110 (verbosity < 0 || verbosity > 4) ||
1111 (unused == NULL && nUnused != 0) ||
1112 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1113 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1114
1115 if (ferror(f))
1116 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1117
1118 bzf = malloc ( sizeof(bzFile) );
1119 if (bzf == NULL)
1120 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1121
1122 BZ_SETERR(BZ_OK);
1123
1124 bzf->initialisedOk = False;
1125 bzf->handle = f;
1126 bzf->bufN = 0;
1127 bzf->writing = False;
1128 bzf->strm.bzalloc = NULL;
1129 bzf->strm.bzfree = NULL;
1130 bzf->strm.opaque = NULL;
1131
1132 while (nUnused > 0) {
1133 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1134 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1135 nUnused--;
1136 }
1137
1138 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1139 if (ret != BZ_OK)
1140 { BZ_SETERR(ret); free(bzf); return NULL; };
1141
1142 bzf->strm.avail_in = bzf->bufN;
1143 bzf->strm.next_in = bzf->buf;
1144
1145 bzf->initialisedOk = True;
1146 return bzf;
1147 }
1148
1149
1150 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadClose)1151 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1152 {
1153 bzFile* bzf = (bzFile*)b;
1154
1155 BZ_SETERR(BZ_OK);
1156 if (bzf == NULL)
1157 { BZ_SETERR(BZ_OK); return; };
1158
1159 if (bzf->writing)
1160 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1161
1162 if (bzf->initialisedOk)
1163 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1164 free ( bzf );
1165 }
1166
1167
1168 /*---------------------------------------------------*/
BZ_API(BZ2_bzRead)1169 int BZ_API(BZ2_bzRead)
1170 ( int* bzerror,
1171 BZFILE* b,
1172 void* buf,
1173 int len )
1174 {
1175 Int32 n, ret;
1176 bzFile* bzf = (bzFile*)b;
1177
1178 BZ_SETERR(BZ_OK);
1179
1180 if (bzf == NULL || buf == NULL || len < 0)
1181 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1182
1183 if (bzf->writing)
1184 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1185
1186 if (len == 0)
1187 { BZ_SETERR(BZ_OK); return 0; };
1188
1189 bzf->strm.avail_out = len;
1190 bzf->strm.next_out = buf;
1191
1192 while (True) {
1193
1194 if (ferror(bzf->handle))
1195 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1196
1197 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1198 n = fread ( bzf->buf, sizeof(UChar),
1199 BZ_MAX_UNUSED, bzf->handle );
1200 if (ferror(bzf->handle))
1201 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1202 bzf->bufN = n;
1203 bzf->strm.avail_in = bzf->bufN;
1204 bzf->strm.next_in = bzf->buf;
1205 }
1206
1207 ret = BZ2_bzDecompress ( &(bzf->strm) );
1208
1209 if (ret != BZ_OK && ret != BZ_STREAM_END)
1210 { BZ_SETERR(ret); return 0; };
1211
1212 if (ret == BZ_OK && myfeof(bzf->handle) &&
1213 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1214 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1215
1216 if (ret == BZ_STREAM_END)
1217 { BZ_SETERR(BZ_STREAM_END);
1218 return len - bzf->strm.avail_out; };
1219 if (bzf->strm.avail_out == 0)
1220 { BZ_SETERR(BZ_OK); return len; };
1221
1222 }
1223
1224 return 0; /*not reached*/
1225 }
1226
1227
1228 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadGetUnused)1229 void BZ_API(BZ2_bzReadGetUnused)
1230 ( int* bzerror,
1231 BZFILE* b,
1232 void** unused,
1233 int* nUnused )
1234 {
1235 bzFile* bzf = (bzFile*)b;
1236 if (bzf == NULL)
1237 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1238 if (bzf->lastErr != BZ_STREAM_END)
1239 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1240 if (unused == NULL || nUnused == NULL)
1241 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1242
1243 BZ_SETERR(BZ_OK);
1244 *nUnused = bzf->strm.avail_in;
1245 *unused = bzf->strm.next_in;
1246 }
1247 #endif
1248
1249
1250 /*---------------------------------------------------*/
1251 /*--- Misc convenience stuff ---*/
1252 /*---------------------------------------------------*/
1253
1254 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffCompress)1255 int BZ_API(BZ2_bzBuffToBuffCompress)
1256 ( char* dest,
1257 unsigned int* destLen,
1258 char* source,
1259 unsigned int sourceLen,
1260 int blockSize100k,
1261 int verbosity,
1262 int workFactor )
1263 {
1264 bz_stream strm;
1265 int ret;
1266
1267 if (dest == NULL || destLen == NULL ||
1268 source == NULL ||
1269 blockSize100k < 1 || blockSize100k > 9 ||
1270 verbosity < 0 || verbosity > 4 ||
1271 workFactor < 0 || workFactor > 250)
1272 return BZ_PARAM_ERROR;
1273
1274 if (workFactor == 0) workFactor = 30;
1275 strm.bzalloc = NULL;
1276 strm.bzfree = NULL;
1277 strm.opaque = NULL;
1278 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1279 verbosity, workFactor );
1280 if (ret != BZ_OK) return ret;
1281
1282 strm.next_in = source;
1283 strm.next_out = dest;
1284 strm.avail_in = sourceLen;
1285 strm.avail_out = *destLen;
1286
1287 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1288 if (ret == BZ_FINISH_OK) goto output_overflow;
1289 if (ret != BZ_STREAM_END) goto errhandler;
1290
1291 /* normal termination */
1292 *destLen -= strm.avail_out;
1293 BZ2_bzCompressEnd ( &strm );
1294 return BZ_OK;
1295
1296 output_overflow:
1297 BZ2_bzCompressEnd ( &strm );
1298 return BZ_OUTBUFF_FULL;
1299
1300 errhandler:
1301 BZ2_bzCompressEnd ( &strm );
1302 return ret;
1303 }
1304
1305
1306 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffDecompress)1307 int BZ_API(BZ2_bzBuffToBuffDecompress)
1308 ( char* dest,
1309 unsigned int* destLen,
1310 char* source,
1311 unsigned int sourceLen,
1312 int small,
1313 int verbosity )
1314 {
1315 bz_stream strm;
1316 int ret;
1317
1318 if (dest == NULL || destLen == NULL ||
1319 source == NULL ||
1320 (small != 0 && small != 1) ||
1321 verbosity < 0 || verbosity > 4)
1322 return BZ_PARAM_ERROR;
1323
1324 strm.bzalloc = NULL;
1325 strm.bzfree = NULL;
1326 strm.opaque = NULL;
1327 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1328 if (ret != BZ_OK) return ret;
1329
1330 strm.next_in = source;
1331 strm.next_out = dest;
1332 strm.avail_in = sourceLen;
1333 strm.avail_out = *destLen;
1334
1335 ret = BZ2_bzDecompress ( &strm );
1336 if (ret == BZ_OK) goto output_overflow_or_eof;
1337 if (ret != BZ_STREAM_END) goto errhandler;
1338
1339 /* normal termination */
1340 *destLen -= strm.avail_out;
1341 BZ2_bzDecompressEnd ( &strm );
1342 return BZ_OK;
1343
1344 output_overflow_or_eof:
1345 if (strm.avail_out > 0) {
1346 BZ2_bzDecompressEnd ( &strm );
1347 return BZ_UNEXPECTED_EOF;
1348 } else {
1349 BZ2_bzDecompressEnd ( &strm );
1350 return BZ_OUTBUFF_FULL;
1351 };
1352
1353 errhandler:
1354 BZ2_bzDecompressEnd ( &strm );
1355 return ret;
1356 }
1357
1358
1359 /*---------------------------------------------------*/
1360 /*--
1361 Code contributed by Yoshioka Tsuneo ([email protected])
1362 to support better zlib compatibility.
1363 This code is not _officially_ part of libbzip2 (yet);
1364 I haven't tested it, documented it, or considered the
1365 threading-safeness of it.
1366 If this code breaks, please contact both Yoshioka and me.
1367 --*/
1368 /*---------------------------------------------------*/
1369
1370 /*---------------------------------------------------*/
1371 /*--
1372 return version like "0.9.5d, 4-Sept-1999".
1373 --*/
BZ_API(BZ2_bzlibVersion)1374 const char * BZ_API(BZ2_bzlibVersion)(void)
1375 {
1376 return BZ_VERSION;
1377 }
1378
1379
1380 #ifndef BZ_NO_STDIO
1381 /*---------------------------------------------------*/
1382
1383 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1384 # include <fcntl.h>
1385 # include <io.h>
1386 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1387 #else
1388 # define SET_BINARY_MODE(file)
1389 #endif
1390 static
bzopen_or_bzdopen(const char * path,int fd,const char * mode,int open_mode)1391 BZFILE * bzopen_or_bzdopen
1392 ( const char *path, /* no use when bzdopen */
1393 int fd, /* no use when bzdopen */
1394 const char *mode,
1395 int open_mode) /* bzopen: 0, bzdopen:1 */
1396 {
1397 int bzerr;
1398 char unused[BZ_MAX_UNUSED];
1399 int blockSize100k = 9;
1400 int writing = 0;
1401 char mode2[10] = "";
1402 FILE *fp = NULL;
1403 BZFILE *bzfp = NULL;
1404 int verbosity = 0;
1405 int workFactor = 30;
1406 int smallMode = 0;
1407 int nUnused = 0;
1408
1409 if (mode == NULL) return NULL;
1410 while (*mode) {
1411 switch (*mode) {
1412 case 'r':
1413 writing = 0; break;
1414 case 'w':
1415 writing = 1; break;
1416 case 's':
1417 smallMode = 1; break;
1418 default:
1419 if (isdigit((int)(*mode))) {
1420 blockSize100k = *mode-BZ_HDR_0;
1421 }
1422 }
1423 mode++;
1424 }
1425 strcat(mode2, writing ? "w" : "r" );
1426 strcat(mode2,"b"); /* binary mode */
1427
1428 if (open_mode==0) {
1429 if (path==NULL || strcmp(path,"")==0) {
1430 fp = (writing ? stdout : stdin);
1431 SET_BINARY_MODE(fp);
1432 } else {
1433 fp = fopen(path,mode2);
1434 }
1435 } else {
1436 #ifdef BZ_STRICT_ANSI
1437 fp = NULL;
1438 #else
1439 fp = fdopen(fd,mode2);
1440 #endif
1441 }
1442 if (fp == NULL) return NULL;
1443
1444 if (writing) {
1445 /* Guard against total chaos and anarchy -- JRS */
1446 if (blockSize100k < 1) blockSize100k = 1;
1447 if (blockSize100k > 9) blockSize100k = 9;
1448 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1449 verbosity,workFactor);
1450 } else {
1451 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1452 unused,nUnused);
1453 }
1454 if (bzfp == NULL) {
1455 if (fp != stdin && fp != stdout) fclose(fp);
1456 return NULL;
1457 }
1458 return bzfp;
1459 }
1460
1461
1462 /*---------------------------------------------------*/
1463 /*--
1464 open file for read or write.
1465 ex) bzopen("file","w9")
1466 case path="" or NULL => use stdin or stdout.
1467 --*/
BZ_API(BZ2_bzopen)1468 BZFILE * BZ_API(BZ2_bzopen)
1469 ( const char *path,
1470 const char *mode )
1471 {
1472 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1473 }
1474
1475
1476 /*---------------------------------------------------*/
BZ_API(BZ2_bzdopen)1477 BZFILE * BZ_API(BZ2_bzdopen)
1478 ( int fd,
1479 const char *mode )
1480 {
1481 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1482 }
1483
1484
1485 /*---------------------------------------------------*/
BZ_API(BZ2_bzread)1486 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1487 {
1488 int bzerr, nread;
1489 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1490 nread = BZ2_bzRead(&bzerr,b,buf,len);
1491 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1492 return nread;
1493 } else {
1494 return -1;
1495 }
1496 }
1497
1498
1499 /*---------------------------------------------------*/
BZ_API(BZ2_bzwrite)1500 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1501 {
1502 int bzerr;
1503
1504 BZ2_bzWrite(&bzerr,b,buf,len);
1505 if(bzerr == BZ_OK){
1506 return len;
1507 }else{
1508 return -1;
1509 }
1510 }
1511
1512
1513 /*---------------------------------------------------*/
BZ_API(BZ2_bzflush)1514 int BZ_API(BZ2_bzflush) (BZFILE *b)
1515 {
1516 /* do nothing now... */
1517 return 0;
1518 }
1519
1520
1521 /*---------------------------------------------------*/
BZ_API(BZ2_bzclose)1522 void BZ_API(BZ2_bzclose) (BZFILE* b)
1523 {
1524 int bzerr;
1525 FILE *fp;
1526
1527 if (b==NULL) {return;}
1528 fp = ((bzFile *)b)->handle;
1529 if(((bzFile*)b)->writing){
1530 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1531 if(bzerr != BZ_OK){
1532 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1533 }
1534 }else{
1535 BZ2_bzReadClose(&bzerr,b);
1536 }
1537 if(fp!=stdin && fp!=stdout){
1538 fclose(fp);
1539 }
1540 }
1541
1542
1543 /*---------------------------------------------------*/
1544 /*--
1545 return last error code
1546 --*/
1547 static const char *bzerrorstrings[] = {
1548 "OK"
1549 ,"SEQUENCE_ERROR"
1550 ,"PARAM_ERROR"
1551 ,"MEM_ERROR"
1552 ,"DATA_ERROR"
1553 ,"DATA_ERROR_MAGIC"
1554 ,"IO_ERROR"
1555 ,"UNEXPECTED_EOF"
1556 ,"OUTBUFF_FULL"
1557 ,"CONFIG_ERROR"
1558 ,"???" /* for future */
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1561 ,"???" /* for future */
1562 ,"???" /* for future */
1563 ,"???" /* for future */
1564 };
1565
1566
BZ_API(BZ2_bzerror)1567 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1568 {
1569 int err = ((bzFile *)b)->lastErr;
1570
1571 if(err>0) err = 0;
1572 *errnum = err;
1573 return bzerrorstrings[err*-1];
1574 }
1575 #endif
1576
1577 #endif /* BZ_NO_COMPRESS */
1578
1579 /*-------------------------------------------------------------*/
1580 /*--- end bzlib.c ---*/
1581 /*-------------------------------------------------------------*/
1582