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 <jseward@acm.org>
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 "bzlib_private.h"
32
33
34 /*---------------------------------------------------*/
35 /*--- Compression stuff ---*/
36 /*---------------------------------------------------*/
37
38
39 /*---------------------------------------------------*/
40 #ifndef BZ_NO_STDIO
BZ2_bz__AssertH__fail(int errcode)41 void BZ2_bz__AssertH__fail ( int errcode )
42 {
43 fprintf(stderr,
44 "\n\nbzip2/libbzip2: internal error number %d.\n"
45 "This is a bug in bzip2/libbzip2, %s.\n"
46 "Please report it to: bzip2-devel@sourceware.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.\n\n",
52 errcode,
53 BZ2_bzlibVersion()
54 );
55
56 if (errcode == 1007) {
57 fprintf(stderr,
58 "\n*** A special note about internal error number 1007 ***\n"
59 "\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"
65 "\n"
66 "I suggest the following: try compressing the file again,\n"
67 "possibly monitoring progress in detail with the -vv flag.\n"
68 "\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"
75 "\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"
80 "\n"
81 );
82 }
83
84 exit(3);
85 }
86 #endif
87
88
89 /*---------------------------------------------------*/
90 static
bz_config_ok(void)91 int bz_config_ok ( void )
92 {
93 if (sizeof(int) != 4) return 0;
94 if (sizeof(short) != 2) return 0;
95 if (sizeof(char) != 1) return 0;
96 return 1;
97 }
98
99
100 /*---------------------------------------------------*/
101 static
default_bzalloc(void * opaque,Int32 items,Int32 size)102 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
103 {
104 void* v = malloc ( items * size );
105 ((void)opaque); /* Silence unused parameter warning */
106
107 return v;
108 }
109
110 static
default_bzfree(void * opaque,void * addr)111 void default_bzfree ( void* opaque, void* addr )
112 {
113 ((void)opaque); /* Silence unused parameter warning */
114
115 if (addr != NULL) free ( addr );
116 }
117
118
119 /*---------------------------------------------------*/
120 static
prepare_new_block(EState * s)121 void prepare_new_block ( EState* s )
122 {
123 Int32 i;
124 s->nblock = 0;
125 s->numZ = 0;
126 s->state_out_pos = 0;
127 BZ_INITIALISE_CRC ( s->blockCRC );
128 for (i = 0; i < 256; i++) s->inUse[i] = False;
129 s->blockNo++;
130 }
131
132
133 /*---------------------------------------------------*/
134 static
init_RL(EState * s)135 void init_RL ( EState* s )
136 {
137 s->state_in_ch = 256;
138 s->state_in_len = 0;
139 }
140
141
142 static
isempty_RL(EState * s)143 Bool isempty_RL ( EState* s )
144 {
145 if (s->state_in_ch < 256 && s->state_in_len > 0)
146 return False; else
147 return True;
148 }
149
150
151 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressInit)152 int BZ_API(BZ2_bzCompressInit)
153 ( bz_stream* strm,
154 int blockSize100k,
155 int verbosity,
156 int workFactor )
157 {
158 Int32 n;
159 EState* s;
160
161 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
162
163 if (strm == NULL ||
164 blockSize100k < 1 || blockSize100k > 9 ||
165 workFactor < 0 || workFactor > 250)
166 return BZ_PARAM_ERROR;
167
168 if (workFactor == 0) workFactor = 30;
169 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
170 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
171
172 s = (EState*) BZALLOC( sizeof(EState) );
173 if (s == NULL) return BZ_MEM_ERROR;
174 s->strm = strm;
175
176 s->arr1 = NULL;
177 s->arr2 = NULL;
178 s->ftab = NULL;
179
180 n = 100000 * blockSize100k;
181 s->arr1 = (UInt32*) BZALLOC( n * sizeof(UInt32) );
182 s->arr2 = (UInt32*) BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
183 s->ftab = (UInt32*) BZALLOC( 65537 * sizeof(UInt32) );
184
185 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
186 if (s->arr1 != NULL) BZFREE(s->arr1);
187 if (s->arr2 != NULL) BZFREE(s->arr2);
188 if (s->ftab != NULL) BZFREE(s->ftab);
189 if (s != NULL) BZFREE(s);
190 return BZ_MEM_ERROR;
191 }
192
193 s->blockNo = 0;
194 s->state = BZ_S_INPUT;
195 s->mode = BZ_M_RUNNING;
196 s->combinedCRC = 0;
197 s->blockSize100k = blockSize100k;
198 s->nblockMAX = 100000 * blockSize100k - 19;
199 s->verbosity = verbosity;
200 s->workFactor = workFactor;
201
202 s->block = (UChar*)s->arr2;
203 s->mtfv = (UInt16*)s->arr1;
204 s->zbits = NULL;
205 s->ptr = (UInt32*)s->arr1;
206
207 strm->state = s;
208 strm->total_in_lo32 = 0;
209 strm->total_in_hi32 = 0;
210 strm->total_out_lo32 = 0;
211 strm->total_out_hi32 = 0;
212 init_RL ( s );
213 prepare_new_block ( s );
214 return BZ_OK;
215 }
216
217
218 /*---------------------------------------------------*/
219 static
add_pair_to_block(EState * s)220 void add_pair_to_block ( EState* s )
221 {
222 Int32 i;
223 UChar ch = (UChar)(s->state_in_ch);
224 for (i = 0; i < s->state_in_len; i++) {
225 BZ_UPDATE_CRC( s->blockCRC, ch );
226 }
227 s->inUse[s->state_in_ch] = True;
228 switch (s->state_in_len) {
229 case 1:
230 s->block[s->nblock] = (UChar)ch; s->nblock++;
231 break;
232 case 2:
233 s->block[s->nblock] = (UChar)ch; s->nblock++;
234 s->block[s->nblock] = (UChar)ch; s->nblock++;
235 break;
236 case 3:
237 s->block[s->nblock] = (UChar)ch; s->nblock++;
238 s->block[s->nblock] = (UChar)ch; s->nblock++;
239 s->block[s->nblock] = (UChar)ch; s->nblock++;
240 break;
241 default:
242 s->inUse[s->state_in_len-4] = True;
243 s->block[s->nblock] = (UChar)ch; s->nblock++;
244 s->block[s->nblock] = (UChar)ch; s->nblock++;
245 s->block[s->nblock] = (UChar)ch; s->nblock++;
246 s->block[s->nblock] = (UChar)ch; s->nblock++;
247 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
248 s->nblock++;
249 break;
250 }
251 }
252
253
254 /*---------------------------------------------------*/
255 static
flush_RL(EState * s)256 void flush_RL ( EState* s )
257 {
258 if (s->state_in_ch < 256) add_pair_to_block ( s );
259 init_RL ( s );
260 }
261
262
263 /*---------------------------------------------------*/
264 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
265 { \
266 UInt32 zchh = (UInt32)(zchh0); \
267 /*-- fast track the common case --*/ \
268 if (zchh != zs->state_in_ch && \
269 zs->state_in_len == 1) { \
270 UChar ch = (UChar)(zs->state_in_ch); \
271 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
272 zs->inUse[zs->state_in_ch] = True; \
273 zs->block[zs->nblock] = (UChar)ch; \
274 zs->nblock++; \
275 zs->state_in_ch = zchh; \
276 } \
277 else \
278 /*-- general, uncommon cases --*/ \
279 if (zchh != zs->state_in_ch || \
280 zs->state_in_len == 255) { \
281 if (zs->state_in_ch < 256) \
282 add_pair_to_block ( zs ); \
283 zs->state_in_ch = zchh; \
284 zs->state_in_len = 1; \
285 } else { \
286 zs->state_in_len++; \
287 } \
288 }
289
290
291 /*---------------------------------------------------*/
292 static
copy_input_until_stop(EState * s)293 Bool copy_input_until_stop ( EState* s )
294 {
295 Bool progress_in = False;
296
297 if (s->mode == BZ_M_RUNNING) {
298
299 /*-- fast track the common case --*/
300 while (True) {
301 /*-- block full? --*/
302 if (s->nblock >= s->nblockMAX) break;
303 /*-- no input? --*/
304 if (s->strm->avail_in == 0) break;
305 progress_in = True;
306 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
307 s->strm->next_in++;
308 s->strm->avail_in--;
309 s->strm->total_in_lo32++;
310 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
311 }
312
313 } else {
314
315 /*-- general, uncommon case --*/
316 while (True) {
317 /*-- block full? --*/
318 if (s->nblock >= s->nblockMAX) break;
319 /*-- no input? --*/
320 if (s->strm->avail_in == 0) break;
321 /*-- flush/finish end? --*/
322 if (s->avail_in_expect == 0) break;
323 progress_in = True;
324 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
325 s->strm->next_in++;
326 s->strm->avail_in--;
327 s->strm->total_in_lo32++;
328 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
329 s->avail_in_expect--;
330 }
331 }
332 return progress_in;
333 }
334
335
336 /*---------------------------------------------------*/
337 static
copy_output_until_stop(EState * s)338 Bool copy_output_until_stop ( EState* s )
339 {
340 Bool progress_out = False;
341
342 while (True) {
343
344 /*-- no output space? --*/
345 if (s->strm->avail_out == 0) break;
346
347 /*-- block done? --*/
348 if (s->state_out_pos >= s->numZ) break;
349
350 progress_out = True;
351 *(s->strm->next_out) = s->zbits[s->state_out_pos];
352 s->state_out_pos++;
353 s->strm->avail_out--;
354 s->strm->next_out++;
355 s->strm->total_out_lo32++;
356 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
357 }
358
359 return progress_out;
360 }
361
362
363 /*---------------------------------------------------*/
364 static
handle_compress(bz_stream * strm)365 Bool handle_compress ( bz_stream* strm )
366 {
367 Bool progress_in = False;
368 Bool progress_out = False;
369 EState* s = (EState*) strm->state;
370
371 while (True) {
372
373 if (s->state == BZ_S_OUTPUT) {
374 progress_out |= copy_output_until_stop ( s );
375 if (s->state_out_pos < s->numZ) break;
376 if (s->mode == BZ_M_FINISHING &&
377 s->avail_in_expect == 0 &&
378 isempty_RL(s)) break;
379 prepare_new_block ( s );
380 s->state = BZ_S_INPUT;
381 if (s->mode == BZ_M_FLUSHING &&
382 s->avail_in_expect == 0 &&
383 isempty_RL(s)) break;
384 }
385
386 if (s->state == BZ_S_INPUT) {
387 progress_in |= copy_input_until_stop ( s );
388 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
389 flush_RL ( s );
390 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
391 s->state = BZ_S_OUTPUT;
392 }
393 else
394 if (s->nblock >= s->nblockMAX) {
395 BZ2_compressBlock ( s, False );
396 s->state = BZ_S_OUTPUT;
397 }
398 else
399 if (s->strm->avail_in == 0) {
400 break;
401 }
402 }
403
404 }
405
406 return progress_in || progress_out;
407 }
408
409
410 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompress)411 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
412 {
413 Bool progress;
414 EState* s;
415 if (strm == NULL) return BZ_PARAM_ERROR;
416 s = (EState*) strm->state;
417 if (s == NULL) return BZ_PARAM_ERROR;
418 if (s->strm != strm) return BZ_PARAM_ERROR;
419
420 preswitch:
421 switch (s->mode) {
422
423 case BZ_M_IDLE:
424 return BZ_SEQUENCE_ERROR;
425
426 case BZ_M_RUNNING:
427 if (action == BZ_RUN) {
428 progress = handle_compress ( strm );
429 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
430 }
431 else
432 if (action == BZ_FLUSH) {
433 s->avail_in_expect = strm->avail_in;
434 s->mode = BZ_M_FLUSHING;
435 goto preswitch;
436 }
437 else
438 if (action == BZ_FINISH) {
439 s->avail_in_expect = strm->avail_in;
440 s->mode = BZ_M_FINISHING;
441 goto preswitch;
442 }
443 else
444 return BZ_PARAM_ERROR;
445
446 case BZ_M_FLUSHING:
447 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
448 if (s->avail_in_expect != s->strm->avail_in)
449 return BZ_SEQUENCE_ERROR;
450 progress = handle_compress ( strm );
451 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
452 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
453 s->mode = BZ_M_RUNNING;
454 return BZ_RUN_OK;
455
456 case BZ_M_FINISHING:
457 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
458 if (s->avail_in_expect != s->strm->avail_in)
459 return BZ_SEQUENCE_ERROR;
460 progress = handle_compress ( strm );
461 if (!progress) return BZ_SEQUENCE_ERROR;
462 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
463 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
464 s->mode = BZ_M_IDLE;
465 return BZ_STREAM_END;
466 }
467 return BZ_OK; /*--not reached--*/
468 }
469
470
471 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressEnd)472 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
473 {
474 EState* s;
475 if (strm == NULL) return BZ_PARAM_ERROR;
476 s = (EState*) strm->state;
477 if (s == NULL) return BZ_PARAM_ERROR;
478 if (s->strm != strm) return BZ_PARAM_ERROR;
479
480 if (s->arr1 != NULL) BZFREE(s->arr1);
481 if (s->arr2 != NULL) BZFREE(s->arr2);
482 if (s->ftab != NULL) BZFREE(s->ftab);
483 BZFREE(strm->state);
484
485 strm->state = NULL;
486
487 return BZ_OK;
488 }
489
490
491 /*---------------------------------------------------*/
492 /*--- Decompression stuff ---*/
493 /*---------------------------------------------------*/
494
495 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressInit)496 int BZ_API(BZ2_bzDecompressInit)
497 ( bz_stream* strm,
498 int verbosity,
499 int small )
500 {
501 DState* s;
502
503 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
504
505 if (strm == NULL) return BZ_PARAM_ERROR;
506 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
507 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
508
509 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
510 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
511
512 s = (DState*) BZALLOC( sizeof(DState) );
513 if (s == NULL) return BZ_MEM_ERROR;
514 s->strm = strm;
515 strm->state = s;
516 s->state = BZ_X_MAGIC_1;
517 s->bsLive = 0;
518 s->bsBuff = 0;
519 s->calculatedCombinedCRC = 0;
520 strm->total_in_lo32 = 0;
521 strm->total_in_hi32 = 0;
522 strm->total_out_lo32 = 0;
523 strm->total_out_hi32 = 0;
524 s->smallDecompress = (Bool)small;
525 s->ll4 = NULL;
526 s->ll16 = NULL;
527 s->tt = NULL;
528 s->currBlockNo = 0;
529 s->verbosity = verbosity;
530
531 return BZ_OK;
532 }
533
534
535 /*---------------------------------------------------*/
536 /* Return True iff data corruption is discovered.
537 Returns False if there is no problem.
538 */
539 static
unRLE_obuf_to_output_FAST(DState * s)540 Bool unRLE_obuf_to_output_FAST ( DState* s )
541 {
542 UChar k1;
543
544 if (s->blockRandomised) {
545
546 while (True) {
547 /* try to finish existing run */
548 while (True) {
549 if (s->strm->avail_out == 0) return False;
550 if (s->state_out_len == 0) break;
551 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
552 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
553 s->state_out_len--;
554 s->strm->next_out++;
555 s->strm->avail_out--;
556 s->strm->total_out_lo32++;
557 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
558 }
559
560 /* can a new run be started? */
561 if (s->nblock_used == s->save_nblock+1) return False;
562
563 /* Only caused by corrupt data stream? */
564 if (s->nblock_used > s->save_nblock+1)
565 return True;
566
567 s->state_out_len = 1;
568 s->state_out_ch = s->k0;
569 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
570 k1 ^= BZ_RAND_MASK; s->nblock_used++;
571 if (s->nblock_used == s->save_nblock+1) continue;
572 if (k1 != s->k0) { s->k0 = k1; continue; };
573
574 s->state_out_len = 2;
575 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
576 k1 ^= BZ_RAND_MASK; s->nblock_used++;
577 if (s->nblock_used == s->save_nblock+1) continue;
578 if (k1 != s->k0) { s->k0 = k1; continue; };
579
580 s->state_out_len = 3;
581 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
582 k1 ^= BZ_RAND_MASK; s->nblock_used++;
583 if (s->nblock_used == s->save_nblock+1) continue;
584 if (k1 != s->k0) { s->k0 = k1; continue; };
585
586 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
587 k1 ^= BZ_RAND_MASK; s->nblock_used++;
588 s->state_out_len = ((Int32)k1) + 4;
589 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
590 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
591 }
592
593 } else {
594
595 /* restore */
596 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
597 UChar c_state_out_ch = s->state_out_ch;
598 Int32 c_state_out_len = s->state_out_len;
599 Int32 c_nblock_used = s->nblock_used;
600 Int32 c_k0 = s->k0;
601 UInt32* c_tt = s->tt;
602 UInt32 c_tPos = s->tPos;
603 char* cs_next_out = s->strm->next_out;
604 unsigned int cs_avail_out = s->strm->avail_out;
605 Int32 ro_blockSize100k = s->blockSize100k;
606 /* end restore */
607
608 UInt32 avail_out_INIT = cs_avail_out;
609 Int32 s_save_nblockPP = s->save_nblock+1;
610 unsigned int total_out_lo32_old;
611
612 while (True) {
613
614 /* try to finish existing run */
615 if (c_state_out_len > 0) {
616 while (True) {
617 if (cs_avail_out == 0) goto return_notr;
618 if (c_state_out_len == 1) break;
619 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
620 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
621 c_state_out_len--;
622 cs_next_out++;
623 cs_avail_out--;
624 }
625 s_state_out_len_eq_one:
626 {
627 if (cs_avail_out == 0) {
628 c_state_out_len = 1; goto return_notr;
629 };
630 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
631 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
632 cs_next_out++;
633 cs_avail_out--;
634 }
635 }
636 /* Only caused by corrupt data stream? */
637 if (c_nblock_used > s_save_nblockPP)
638 return True;
639
640 /* can a new run be started? */
641 if (c_nblock_used == s_save_nblockPP) {
642 c_state_out_len = 0; goto return_notr;
643 };
644 c_state_out_ch = c_k0;
645 BZ_GET_FAST_C(k1); c_nblock_used++;
646 if (k1 != c_k0) {
647 c_k0 = k1; goto s_state_out_len_eq_one;
648 };
649 if (c_nblock_used == s_save_nblockPP)
650 goto s_state_out_len_eq_one;
651
652 c_state_out_len = 2;
653 BZ_GET_FAST_C(k1); c_nblock_used++;
654 if (c_nblock_used == s_save_nblockPP) continue;
655 if (k1 != c_k0) { c_k0 = k1; continue; };
656
657 c_state_out_len = 3;
658 BZ_GET_FAST_C(k1); c_nblock_used++;
659 if (c_nblock_used == s_save_nblockPP) continue;
660 if (k1 != c_k0) { c_k0 = k1; continue; };
661
662 BZ_GET_FAST_C(k1); c_nblock_used++;
663 c_state_out_len = ((Int32)k1) + 4;
664 BZ_GET_FAST_C(c_k0); c_nblock_used++;
665 }
666
667 return_notr:
668 total_out_lo32_old = s->strm->total_out_lo32;
669 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
670 if (s->strm->total_out_lo32 < total_out_lo32_old)
671 s->strm->total_out_hi32++;
672
673 /* save */
674 s->calculatedBlockCRC = c_calculatedBlockCRC;
675 s->state_out_ch = c_state_out_ch;
676 s->state_out_len = c_state_out_len;
677 s->nblock_used = c_nblock_used;
678 s->k0 = c_k0;
679 s->tt = c_tt;
680 s->tPos = c_tPos;
681 s->strm->next_out = cs_next_out;
682 s->strm->avail_out = cs_avail_out;
683 /* end save */
684 }
685 return False;
686 }
687
688
689
690 /*---------------------------------------------------*/
691 #ifndef __cplusplus
692 __inline__
693 #endif
BZ2_indexIntoF(Int32 indx,Int32 * cftab)694 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 = (DState*) 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 /*NOTREACHED*/
863 }
864
865
866 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressEnd)867 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
868 {
869 DState* s;
870 if (strm == NULL) return BZ_PARAM_ERROR;
871 s = (DState*) strm->state;
872 if (s == NULL) return BZ_PARAM_ERROR;
873 if (s->strm != strm) return BZ_PARAM_ERROR;
874
875 if (s->tt != NULL) BZFREE(s->tt);
876 if (s->ll16 != NULL) BZFREE(s->ll16);
877 if (s->ll4 != NULL) BZFREE(s->ll4);
878
879 BZFREE(strm->state);
880 strm->state = NULL;
881
882 return BZ_OK;
883 }
884
885
886 #ifndef BZ_NO_STDIO
887 /*---------------------------------------------------*/
888 /*--- File I/O stuff ---*/
889 /*---------------------------------------------------*/
890
891 #define BZ_SETERR(eee) \
892 { \
893 if (bzerror != NULL) *bzerror = eee; \
894 if (bzf != NULL) bzf->lastErr = eee; \
895 }
896
897 typedef
898 struct {
899 FILE* handle;
900 Char buf[BZ_MAX_UNUSED];
901 Int32 bufN;
902 Bool writing;
903 bz_stream strm;
904 Int32 lastErr;
905 Bool initialisedOk;
906 }
907 bzFile;
908
909
910 /*---------------------------------------------*/
myfeof(FILE * f)911 static Bool myfeof ( FILE* f )
912 {
913 Int32 c = fgetc ( f );
914 if (c == EOF) return True;
915 ungetc ( c, f );
916 return False;
917 }
918
919
920 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteOpen)921 BZFILE* BZ_API(BZ2_bzWriteOpen)
922 ( int* bzerror,
923 FILE* f,
924 int blockSize100k,
925 int verbosity,
926 int workFactor )
927 {
928 Int32 ret;
929 bzFile* bzf = NULL;
930
931 BZ_SETERR(BZ_OK);
932
933 if (f == NULL ||
934 (blockSize100k < 1 || blockSize100k > 9) ||
935 (workFactor < 0 || workFactor > 250) ||
936 (verbosity < 0 || verbosity > 4))
937 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
938
939 if (ferror(f))
940 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
941
942 bzf = (bzFile*) malloc ( sizeof(bzFile) );
943 if (bzf == NULL)
944 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
945
946 BZ_SETERR(BZ_OK);
947 bzf->initialisedOk = False;
948 bzf->bufN = 0;
949 bzf->handle = f;
950 bzf->writing = True;
951 bzf->strm.bzalloc = NULL;
952 bzf->strm.bzfree = NULL;
953 bzf->strm.opaque = NULL;
954
955 if (workFactor == 0) workFactor = 30;
956 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
957 verbosity, workFactor );
958 if (ret != BZ_OK)
959 { BZ_SETERR(ret); free(bzf); return NULL; };
960
961 bzf->strm.avail_in = 0;
962 bzf->initialisedOk = True;
963 return bzf;
964 }
965
966
967
968 /*---------------------------------------------------*/
BZ_API(BZ2_bzWrite)969 void BZ_API(BZ2_bzWrite)
970 ( int* bzerror,
971 BZFILE* b,
972 void* buf,
973 int len )
974 {
975 Int32 n, n2, ret;
976 bzFile* bzf = (bzFile*)b;
977
978 BZ_SETERR(BZ_OK);
979 if (bzf == NULL || buf == NULL || len < 0)
980 { BZ_SETERR(BZ_PARAM_ERROR); return; };
981 if (!(bzf->writing))
982 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
983 if (ferror(bzf->handle))
984 { BZ_SETERR(BZ_IO_ERROR); return; };
985
986 if (len == 0)
987 { BZ_SETERR(BZ_OK); return; };
988
989 bzf->strm.avail_in = len;
990 bzf->strm.next_in = (char*)buf;
991
992 while (True) {
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; };
998
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),
1002 n, bzf->handle );
1003 if (n != n2 || ferror(bzf->handle))
1004 { BZ_SETERR(BZ_IO_ERROR); return; };
1005 }
1006
1007 if (bzf->strm.avail_in == 0)
1008 { BZ_SETERR(BZ_OK); return; };
1009 }
1010 }
1011
1012
1013 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteClose)1014 void BZ_API(BZ2_bzWriteClose)
1015 ( int* bzerror,
1016 BZFILE* b,
1017 int abandon,
1018 unsigned int* nbytes_in,
1019 unsigned int* nbytes_out )
1020 {
1021 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1022 nbytes_in, NULL, nbytes_out, NULL );
1023 }
1024
1025
BZ_API(BZ2_bzWriteClose64)1026 void BZ_API(BZ2_bzWriteClose64)
1027 ( int* bzerror,
1028 BZFILE* b,
1029 int abandon,
1030 unsigned int* nbytes_in_lo32,
1031 unsigned int* nbytes_in_hi32,
1032 unsigned int* nbytes_out_lo32,
1033 unsigned int* nbytes_out_hi32 )
1034 {
1035 Int32 n, n2, ret;
1036 bzFile* bzf = (bzFile*)b;
1037
1038 if (bzf == NULL)
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; };
1044
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;
1049
1050 if ((!abandon) && bzf->lastErr == BZ_OK) {
1051 while (True) {
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; };
1057
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),
1061 n, bzf->handle );
1062 if (n != n2 || ferror(bzf->handle))
1063 { BZ_SETERR(BZ_IO_ERROR); return; };
1064 }
1065
1066 if (ret == BZ_STREAM_END) break;
1067 }
1068 }
1069
1070 if ( !abandon && !ferror ( bzf->handle ) ) {
1071 fflush ( bzf->handle );
1072 if (ferror(bzf->handle))
1073 { BZ_SETERR(BZ_IO_ERROR); return; };
1074 }
1075
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;
1084
1085 BZ_SETERR(BZ_OK);
1086 BZ2_bzCompressEnd ( &(bzf->strm) );
1087 free ( bzf );
1088 }
1089
1090
1091 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadOpen)1092 BZFILE* BZ_API(BZ2_bzReadOpen)
1093 ( int* bzerror,
1094 FILE* f,
1095 int verbosity,
1096 int small,
1097 void* unused,
1098 int nUnused )
1099 {
1100 bzFile* bzf = NULL;
1101 int ret;
1102
1103 BZ_SETERR(BZ_OK);
1104
1105 if (f == NULL ||
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; };
1111
1112 if (ferror(f))
1113 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1114
1115 bzf = (bzFile*) malloc ( sizeof(bzFile) );
1116 if (bzf == NULL)
1117 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1118
1119 BZ_SETERR(BZ_OK);
1120
1121 bzf->initialisedOk = False;
1122 bzf->handle = f;
1123 bzf->bufN = 0;
1124 bzf->writing = False;
1125 bzf->strm.bzalloc = NULL;
1126 bzf->strm.bzfree = NULL;
1127 bzf->strm.opaque = NULL;
1128
1129 while (nUnused > 0) {
1130 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1131 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1132 nUnused--;
1133 }
1134
1135 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1136 if (ret != BZ_OK)
1137 { BZ_SETERR(ret); free(bzf); return NULL; };
1138
1139 bzf->strm.avail_in = bzf->bufN;
1140 bzf->strm.next_in = bzf->buf;
1141
1142 bzf->initialisedOk = True;
1143 return bzf;
1144 }
1145
1146
1147 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadClose)1148 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1149 {
1150 bzFile* bzf = (bzFile*)b;
1151
1152 BZ_SETERR(BZ_OK);
1153 if (bzf == NULL)
1154 { BZ_SETERR(BZ_OK); return; };
1155
1156 if (bzf->writing)
1157 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1158
1159 if (bzf->initialisedOk)
1160 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1161 free ( bzf );
1162 }
1163
1164
1165 /*---------------------------------------------------*/
BZ_API(BZ2_bzRead)1166 int BZ_API(BZ2_bzRead)
1167 ( int* bzerror,
1168 BZFILE* b,
1169 void* buf,
1170 int len )
1171 {
1172 Int32 n, ret;
1173 bzFile* bzf = (bzFile*)b;
1174
1175 BZ_SETERR(BZ_OK);
1176
1177 if (bzf == NULL || buf == NULL || len < 0)
1178 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1179
1180 if (bzf->writing)
1181 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1182
1183 if (len == 0)
1184 { BZ_SETERR(BZ_OK); return 0; };
1185
1186 bzf->strm.avail_out = len;
1187 bzf->strm.next_out = (char*) buf;
1188
1189 while (True) {
1190
1191 if (ferror(bzf->handle))
1192 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1193
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; };
1199 bzf->bufN = n;
1200 bzf->strm.avail_in = bzf->bufN;
1201 bzf->strm.next_in = bzf->buf;
1202 }
1203
1204 ret = BZ2_bzDecompress ( &(bzf->strm) );
1205
1206 if (ret != BZ_OK && ret != BZ_STREAM_END)
1207 { BZ_SETERR(ret); return 0; };
1208
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; };
1212
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; };
1218
1219 }
1220
1221 return 0; /*not reached*/
1222 }
1223
1224
1225 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadGetUnused)1226 void BZ_API(BZ2_bzReadGetUnused)
1227 ( int* bzerror,
1228 BZFILE* b,
1229 void** unused,
1230 int* nUnused )
1231 {
1232 bzFile* bzf = (bzFile*)b;
1233 if (bzf == NULL)
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; };
1239
1240 BZ_SETERR(BZ_OK);
1241 *nUnused = bzf->strm.avail_in;
1242 *unused = bzf->strm.next_in;
1243 }
1244 #endif
1245
1246
1247 /*---------------------------------------------------*/
1248 /*--- Misc convenience stuff ---*/
1249 /*---------------------------------------------------*/
1250
1251 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffCompress)1252 int BZ_API(BZ2_bzBuffToBuffCompress)
1253 ( char* dest,
1254 unsigned int* destLen,
1255 char* source,
1256 unsigned int sourceLen,
1257 int blockSize100k,
1258 int verbosity,
1259 int workFactor )
1260 {
1261 bz_stream strm;
1262 int ret;
1263
1264 if (dest == NULL || destLen == NULL ||
1265 source == NULL ||
1266 blockSize100k < 1 || blockSize100k > 9 ||
1267 verbosity < 0 || verbosity > 4 ||
1268 workFactor < 0 || workFactor > 250)
1269 return BZ_PARAM_ERROR;
1270
1271 if (workFactor == 0) workFactor = 30;
1272 strm.bzalloc = NULL;
1273 strm.bzfree = NULL;
1274 strm.opaque = NULL;
1275 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1276 verbosity, workFactor );
1277 if (ret != BZ_OK) return ret;
1278
1279 strm.next_in = source;
1280 strm.next_out = dest;
1281 strm.avail_in = sourceLen;
1282 strm.avail_out = *destLen;
1283
1284 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1285 if (ret == BZ_FINISH_OK) goto output_overflow;
1286 if (ret != BZ_STREAM_END) goto errhandler;
1287
1288 /* normal termination */
1289 *destLen -= strm.avail_out;
1290 BZ2_bzCompressEnd ( &strm );
1291 return BZ_OK;
1292
1293 output_overflow:
1294 BZ2_bzCompressEnd ( &strm );
1295 return BZ_OUTBUFF_FULL;
1296
1297 errhandler:
1298 BZ2_bzCompressEnd ( &strm );
1299 return ret;
1300 }
1301
1302
1303 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffDecompress)1304 int BZ_API(BZ2_bzBuffToBuffDecompress)
1305 ( char* dest,
1306 unsigned int* destLen,
1307 char* source,
1308 unsigned int sourceLen,
1309 int small,
1310 int verbosity )
1311 {
1312 bz_stream strm;
1313 int ret;
1314
1315 if (dest == NULL || destLen == NULL ||
1316 source == NULL ||
1317 (small != 0 && small != 1) ||
1318 verbosity < 0 || verbosity > 4)
1319 return BZ_PARAM_ERROR;
1320
1321 strm.bzalloc = NULL;
1322 strm.bzfree = NULL;
1323 strm.opaque = NULL;
1324 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1325 if (ret != BZ_OK) return ret;
1326
1327 strm.next_in = source;
1328 strm.next_out = dest;
1329 strm.avail_in = sourceLen;
1330 strm.avail_out = *destLen;
1331
1332 ret = BZ2_bzDecompress ( &strm );
1333 if (ret == BZ_OK) goto output_overflow_or_eof;
1334 if (ret != BZ_STREAM_END) goto errhandler;
1335
1336 /* normal termination */
1337 *destLen -= strm.avail_out;
1338 BZ2_bzDecompressEnd ( &strm );
1339 return BZ_OK;
1340
1341 output_overflow_or_eof:
1342 if (strm.avail_out > 0) {
1343 BZ2_bzDecompressEnd ( &strm );
1344 return BZ_UNEXPECTED_EOF;
1345 } else {
1346 BZ2_bzDecompressEnd ( &strm );
1347 return BZ_OUTBUFF_FULL;
1348 };
1349
1350 errhandler:
1351 BZ2_bzDecompressEnd ( &strm );
1352 return ret;
1353 }
1354
1355
1356 /*---------------------------------------------------*/
1357 /*--
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.
1364 --*/
1365 /*---------------------------------------------------*/
1366
1367 /*---------------------------------------------------*/
1368 /*--
1369 return version like "0.9.5d, 4-Sept-1999".
1370 --*/
BZ_API(BZ2_bzlibVersion)1371 const char * BZ_API(BZ2_bzlibVersion)(void)
1372 {
1373 return BZ_VERSION;
1374 }
1375
1376
1377 #ifndef BZ_NO_STDIO
1378 /*---------------------------------------------------*/
1379
1380 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1381 # include <fcntl.h>
1382 # include <io.h>
1383 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1384 #else
1385 # define SET_BINARY_MODE(file)
1386 #endif
1387 static
bzopen_or_bzdopen(const char * path,int fd,const char * mode,int open_mode)1388 BZFILE * bzopen_or_bzdopen
1389 ( const char *path, /* no use when bzdopen */
1390 int fd, /* no use when bzdopen */
1391 const char *mode,
1392 int open_mode) /* bzopen: 0, bzdopen:1 */
1393 {
1394 int bzerr;
1395 char unused[BZ_MAX_UNUSED];
1396 int blockSize100k = 9;
1397 int writing = 0;
1398 char mode2[10] = "";
1399 FILE *fp = NULL;
1400 BZFILE *bzfp = NULL;
1401 int verbosity = 0;
1402 int workFactor = 30;
1403 int smallMode = 0;
1404 int nUnused = 0;
1405
1406 if (mode == NULL) return NULL;
1407 while (*mode) {
1408 switch (*mode) {
1409 case 'r':
1410 writing = 0; break;
1411 case 'w':
1412 writing = 1; break;
1413 case 's':
1414 smallMode = 1; break;
1415 default:
1416 if (isdigit((unsigned char)(*mode))) {
1417 blockSize100k = *mode-BZ_HDR_0;
1418 }
1419 }
1420 mode++;
1421 }
1422 strcat(mode2, writing ? "w" : "r" );
1423 strcat(mode2,"b"); /* binary mode */
1424
1425 if (open_mode==0) {
1426 if (path==NULL || strcmp(path,"")==0) {
1427 fp = (writing ? stdout : stdin);
1428 SET_BINARY_MODE(fp);
1429 } else {
1430 fp = fopen(path,mode2);
1431 }
1432 } else {
1433 #ifdef BZ_STRICT_ANSI
1434 fp = NULL;
1435 #else
1436 fp = fdopen(fd,mode2);
1437 #endif
1438 }
1439 if (fp == NULL) return NULL;
1440
1441 if (writing) {
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);
1447 } else {
1448 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1449 unused,nUnused);
1450 }
1451 if (bzfp == NULL) {
1452 if (fp != stdin && fp != stdout) fclose(fp);
1453 return NULL;
1454 }
1455 return bzfp;
1456 }
1457
1458
1459 /*---------------------------------------------------*/
1460 /*--
1461 open file for read or write.
1462 ex) bzopen("file","w9")
1463 case path="" or NULL => use stdin or stdout.
1464 --*/
BZ_API(BZ2_bzopen)1465 BZFILE * BZ_API(BZ2_bzopen)
1466 ( const char *path,
1467 const char *mode )
1468 {
1469 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1470 }
1471
1472
1473 /*---------------------------------------------------*/
BZ_API(BZ2_bzdopen)1474 BZFILE * BZ_API(BZ2_bzdopen)
1475 ( int fd,
1476 const char *mode )
1477 {
1478 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1479 }
1480
1481
1482 /*---------------------------------------------------*/
BZ_API(BZ2_bzread)1483 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1484 {
1485 int bzerr, nread;
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) {
1489 return nread;
1490 } else {
1491 return -1;
1492 }
1493 }
1494
1495
1496 /*---------------------------------------------------*/
BZ_API(BZ2_bzwrite)1497 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1498 {
1499 int bzerr;
1500
1501 BZ2_bzWrite(&bzerr,b,buf,len);
1502 if(bzerr == BZ_OK){
1503 return len;
1504 }else{
1505 return -1;
1506 }
1507 }
1508
1509
1510 /*---------------------------------------------------*/
BZ_API(BZ2_bzflush)1511 int BZ_API(BZ2_bzflush) (BZFILE *b)
1512 {
1513 /* do nothing now... */
1514 return 0;
1515 }
1516
1517
1518 /*---------------------------------------------------*/
BZ_API(BZ2_bzclose)1519 void BZ_API(BZ2_bzclose) (BZFILE* b)
1520 {
1521 int bzerr;
1522 FILE *fp;
1523
1524 if (b==NULL) {return;}
1525 fp = ((bzFile *)b)->handle;
1526 if(((bzFile*)b)->writing){
1527 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1528 if(bzerr != BZ_OK){
1529 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1530 }
1531 }else{
1532 BZ2_bzReadClose(&bzerr,b);
1533 }
1534 if(fp!=stdin && fp!=stdout){
1535 fclose(fp);
1536 }
1537 }
1538
1539
1540 /*---------------------------------------------------*/
1541 /*--
1542 return last error code
1543 --*/
1544 static const char *bzerrorstrings[] = {
1545 "OK"
1546 ,"SEQUENCE_ERROR"
1547 ,"PARAM_ERROR"
1548 ,"MEM_ERROR"
1549 ,"DATA_ERROR"
1550 ,"DATA_ERROR_MAGIC"
1551 ,"IO_ERROR"
1552 ,"UNEXPECTED_EOF"
1553 ,"OUTBUFF_FULL"
1554 ,"CONFIG_ERROR"
1555 ,"???" /* for future */
1556 ,"???" /* for future */
1557 ,"???" /* for future */
1558 ,"???" /* for future */
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1561 };
1562
1563
BZ_API(BZ2_bzerror)1564 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1565 {
1566 int err = ((bzFile *)b)->lastErr;
1567
1568 if(err>0) err = 0;
1569 *errnum = err;
1570 return bzerrorstrings[err*-1];
1571 }
1572 #endif
1573
1574
1575 /*-------------------------------------------------------------*/
1576 /*--- end bzlib.c ---*/
1577 /*-------------------------------------------------------------*/
1578