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 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 = (DState*) 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
888 #ifndef BZ_NO_STDIO
889 /*---------------------------------------------------*/
890 /*--- File I/O stuff ---*/
891 /*---------------------------------------------------*/
892
893 #define BZ_SETERR(eee) \
894 { \
895 if (bzerror != NULL) *bzerror = eee; \
896 if (bzf != NULL) bzf->lastErr = eee; \
897 }
898
899 typedef
900 struct {
901 FILE* handle;
902 Char buf[BZ_MAX_UNUSED];
903 Int32 bufN;
904 Bool writing;
905 bz_stream strm;
906 Int32 lastErr;
907 Bool initialisedOk;
908 }
909 bzFile;
910
911
912 /*---------------------------------------------*/
myfeof(FILE * f)913 static Bool myfeof ( FILE* f )
914 {
915 Int32 c = fgetc ( f );
916 if (c == EOF) return True;
917 ungetc ( c, f );
918 return False;
919 }
920
921
922 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteOpen)923 BZFILE* BZ_API(BZ2_bzWriteOpen)
924 ( int* bzerror,
925 FILE* f,
926 int blockSize100k,
927 int verbosity,
928 int workFactor )
929 {
930 Int32 ret;
931 bzFile* bzf = NULL;
932
933 BZ_SETERR(BZ_OK);
934
935 if (f == NULL ||
936 (blockSize100k < 1 || blockSize100k > 9) ||
937 (workFactor < 0 || workFactor > 250) ||
938 (verbosity < 0 || verbosity > 4))
939 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
940
941 if (ferror(f))
942 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
943
944 bzf = (bzFile*) malloc ( sizeof(bzFile) );
945 if (bzf == NULL)
946 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
947
948 BZ_SETERR(BZ_OK);
949 bzf->initialisedOk = False;
950 bzf->bufN = 0;
951 bzf->handle = f;
952 bzf->writing = True;
953 bzf->strm.bzalloc = NULL;
954 bzf->strm.bzfree = NULL;
955 bzf->strm.opaque = NULL;
956
957 if (workFactor == 0) workFactor = 30;
958 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
959 verbosity, workFactor );
960 if (ret != BZ_OK)
961 { BZ_SETERR(ret); free(bzf); return NULL; };
962
963 bzf->strm.avail_in = 0;
964 bzf->initialisedOk = True;
965 return bzf;
966 }
967
968
969
970 /*---------------------------------------------------*/
BZ_API(BZ2_bzWrite)971 void BZ_API(BZ2_bzWrite)
972 ( int* bzerror,
973 BZFILE* b,
974 void* buf,
975 int len )
976 {
977 Int32 n, n2, ret;
978 bzFile* bzf = (bzFile*)b;
979
980 BZ_SETERR(BZ_OK);
981 if (bzf == NULL || buf == NULL || len < 0)
982 { BZ_SETERR(BZ_PARAM_ERROR); return; };
983 if (!(bzf->writing))
984 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
985 if (ferror(bzf->handle))
986 { BZ_SETERR(BZ_IO_ERROR); return; };
987
988 if (len == 0)
989 { BZ_SETERR(BZ_OK); return; };
990
991 bzf->strm.avail_in = len;
992 bzf->strm.next_in = (char*)buf;
993
994 while (True) {
995 bzf->strm.avail_out = BZ_MAX_UNUSED;
996 bzf->strm.next_out = bzf->buf;
997 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
998 if (ret != BZ_RUN_OK)
999 { BZ_SETERR(ret); return; };
1000
1001 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1002 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1003 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1004 n, bzf->handle );
1005 if (n != n2 || ferror(bzf->handle))
1006 { BZ_SETERR(BZ_IO_ERROR); return; };
1007 }
1008
1009 if (bzf->strm.avail_in == 0)
1010 { BZ_SETERR(BZ_OK); return; };
1011 }
1012 }
1013
1014
1015 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteClose)1016 void BZ_API(BZ2_bzWriteClose)
1017 ( int* bzerror,
1018 BZFILE* b,
1019 int abandon,
1020 unsigned int* nbytes_in,
1021 unsigned int* nbytes_out )
1022 {
1023 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1024 nbytes_in, NULL, nbytes_out, NULL );
1025 }
1026
1027
BZ_API(BZ2_bzWriteClose64)1028 void BZ_API(BZ2_bzWriteClose64)
1029 ( int* bzerror,
1030 BZFILE* b,
1031 int abandon,
1032 unsigned int* nbytes_in_lo32,
1033 unsigned int* nbytes_in_hi32,
1034 unsigned int* nbytes_out_lo32,
1035 unsigned int* nbytes_out_hi32 )
1036 {
1037 Int32 n, n2, ret;
1038 bzFile* bzf = (bzFile*)b;
1039
1040 if (bzf == NULL)
1041 { BZ_SETERR(BZ_OK); return; };
1042 if (!(bzf->writing))
1043 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1044 if (ferror(bzf->handle))
1045 { BZ_SETERR(BZ_IO_ERROR); return; };
1046
1047 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1048 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1049 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1050 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1051
1052 if ((!abandon) && bzf->lastErr == BZ_OK) {
1053 while (True) {
1054 bzf->strm.avail_out = BZ_MAX_UNUSED;
1055 bzf->strm.next_out = bzf->buf;
1056 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1057 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1058 { BZ_SETERR(ret); return; };
1059
1060 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1061 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1062 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1063 n, bzf->handle );
1064 if (n != n2 || ferror(bzf->handle))
1065 { BZ_SETERR(BZ_IO_ERROR); return; };
1066 }
1067
1068 if (ret == BZ_STREAM_END) break;
1069 }
1070 }
1071
1072 if ( !abandon && !ferror ( bzf->handle ) ) {
1073 fflush ( bzf->handle );
1074 if (ferror(bzf->handle))
1075 { BZ_SETERR(BZ_IO_ERROR); return; };
1076 }
1077
1078 if (nbytes_in_lo32 != NULL)
1079 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1080 if (nbytes_in_hi32 != NULL)
1081 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1082 if (nbytes_out_lo32 != NULL)
1083 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1084 if (nbytes_out_hi32 != NULL)
1085 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1086
1087 BZ_SETERR(BZ_OK);
1088 BZ2_bzCompressEnd ( &(bzf->strm) );
1089 free ( bzf );
1090 }
1091
1092
1093 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadOpen)1094 BZFILE* BZ_API(BZ2_bzReadOpen)
1095 ( int* bzerror,
1096 FILE* f,
1097 int verbosity,
1098 int small,
1099 void* unused,
1100 int nUnused )
1101 {
1102 bzFile* bzf = NULL;
1103 int ret;
1104
1105 BZ_SETERR(BZ_OK);
1106
1107 if (f == NULL ||
1108 (small != 0 && small != 1) ||
1109 (verbosity < 0 || verbosity > 4) ||
1110 (unused == NULL && nUnused != 0) ||
1111 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1112 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1113
1114 if (ferror(f))
1115 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1116
1117 bzf = (bzFile*) malloc ( sizeof(bzFile) );
1118 if (bzf == NULL)
1119 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1120
1121 BZ_SETERR(BZ_OK);
1122
1123 bzf->initialisedOk = False;
1124 bzf->handle = f;
1125 bzf->bufN = 0;
1126 bzf->writing = False;
1127 bzf->strm.bzalloc = NULL;
1128 bzf->strm.bzfree = NULL;
1129 bzf->strm.opaque = NULL;
1130
1131 while (nUnused > 0) {
1132 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1133 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1134 nUnused--;
1135 }
1136
1137 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1138 if (ret != BZ_OK)
1139 { BZ_SETERR(ret); free(bzf); return NULL; };
1140
1141 bzf->strm.avail_in = bzf->bufN;
1142 bzf->strm.next_in = bzf->buf;
1143
1144 bzf->initialisedOk = True;
1145 return bzf;
1146 }
1147
1148
1149 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadClose)1150 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1151 {
1152 bzFile* bzf = (bzFile*)b;
1153
1154 BZ_SETERR(BZ_OK);
1155 if (bzf == NULL)
1156 { BZ_SETERR(BZ_OK); return; };
1157
1158 if (bzf->writing)
1159 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1160
1161 if (bzf->initialisedOk)
1162 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1163 free ( bzf );
1164 }
1165
1166
1167 /*---------------------------------------------------*/
BZ_API(BZ2_bzRead)1168 int BZ_API(BZ2_bzRead)
1169 ( int* bzerror,
1170 BZFILE* b,
1171 void* buf,
1172 int len )
1173 {
1174 Int32 n, ret;
1175 bzFile* bzf = (bzFile*)b;
1176
1177 BZ_SETERR(BZ_OK);
1178
1179 if (bzf == NULL || buf == NULL || len < 0)
1180 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1181
1182 if (bzf->writing)
1183 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1184
1185 if (len == 0)
1186 { BZ_SETERR(BZ_OK); return 0; };
1187
1188 bzf->strm.avail_out = len;
1189 bzf->strm.next_out = (char*) buf;
1190
1191 while (True) {
1192
1193 if (ferror(bzf->handle))
1194 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1195
1196 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1197 n = fread ( bzf->buf, sizeof(UChar),
1198 BZ_MAX_UNUSED, bzf->handle );
1199 if (ferror(bzf->handle))
1200 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1201 bzf->bufN = n;
1202 bzf->strm.avail_in = bzf->bufN;
1203 bzf->strm.next_in = bzf->buf;
1204 }
1205
1206 ret = BZ2_bzDecompress ( &(bzf->strm) );
1207
1208 if (ret != BZ_OK && ret != BZ_STREAM_END)
1209 { BZ_SETERR(ret); return 0; };
1210
1211 if (ret == BZ_OK && myfeof(bzf->handle) &&
1212 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1213 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1214
1215 if (ret == BZ_STREAM_END)
1216 { BZ_SETERR(BZ_STREAM_END);
1217 return len - bzf->strm.avail_out; };
1218 if (bzf->strm.avail_out == 0)
1219 { BZ_SETERR(BZ_OK); return len; };
1220
1221 }
1222
1223 return 0; /*not reached*/
1224 }
1225
1226
1227 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadGetUnused)1228 void BZ_API(BZ2_bzReadGetUnused)
1229 ( int* bzerror,
1230 BZFILE* b,
1231 void** unused,
1232 int* nUnused )
1233 {
1234 bzFile* bzf = (bzFile*)b;
1235 if (bzf == NULL)
1236 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1237 if (bzf->lastErr != BZ_STREAM_END)
1238 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1239 if (unused == NULL || nUnused == NULL)
1240 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1241
1242 BZ_SETERR(BZ_OK);
1243 *nUnused = bzf->strm.avail_in;
1244 *unused = bzf->strm.next_in;
1245 }
1246 #endif
1247
1248
1249 /*---------------------------------------------------*/
1250 /*--- Misc convenience stuff ---*/
1251 /*---------------------------------------------------*/
1252
1253 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffCompress)1254 int BZ_API(BZ2_bzBuffToBuffCompress)
1255 ( char* dest,
1256 unsigned int* destLen,
1257 char* source,
1258 unsigned int sourceLen,
1259 int blockSize100k,
1260 int verbosity,
1261 int workFactor )
1262 {
1263 bz_stream strm;
1264 int ret;
1265
1266 if (dest == NULL || destLen == NULL ||
1267 source == NULL ||
1268 blockSize100k < 1 || blockSize100k > 9 ||
1269 verbosity < 0 || verbosity > 4 ||
1270 workFactor < 0 || workFactor > 250)
1271 return BZ_PARAM_ERROR;
1272
1273 if (workFactor == 0) workFactor = 30;
1274 strm.bzalloc = NULL;
1275 strm.bzfree = NULL;
1276 strm.opaque = NULL;
1277 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1278 verbosity, workFactor );
1279 if (ret != BZ_OK) return ret;
1280
1281 strm.next_in = source;
1282 strm.next_out = dest;
1283 strm.avail_in = sourceLen;
1284 strm.avail_out = *destLen;
1285
1286 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1287 if (ret == BZ_FINISH_OK) goto output_overflow;
1288 if (ret != BZ_STREAM_END) goto errhandler;
1289
1290 /* normal termination */
1291 *destLen -= strm.avail_out;
1292 BZ2_bzCompressEnd ( &strm );
1293 return BZ_OK;
1294
1295 output_overflow:
1296 BZ2_bzCompressEnd ( &strm );
1297 return BZ_OUTBUFF_FULL;
1298
1299 errhandler:
1300 BZ2_bzCompressEnd ( &strm );
1301 return ret;
1302 }
1303
1304
1305 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffDecompress)1306 int BZ_API(BZ2_bzBuffToBuffDecompress)
1307 ( char* dest,
1308 unsigned int* destLen,
1309 char* source,
1310 unsigned int sourceLen,
1311 int small,
1312 int verbosity )
1313 {
1314 bz_stream strm;
1315 int ret;
1316
1317 if (dest == NULL || destLen == NULL ||
1318 source == NULL ||
1319 (small != 0 && small != 1) ||
1320 verbosity < 0 || verbosity > 4)
1321 return BZ_PARAM_ERROR;
1322
1323 strm.bzalloc = NULL;
1324 strm.bzfree = NULL;
1325 strm.opaque = NULL;
1326 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1327 if (ret != BZ_OK) return ret;
1328
1329 strm.next_in = source;
1330 strm.next_out = dest;
1331 strm.avail_in = sourceLen;
1332 strm.avail_out = *destLen;
1333
1334 ret = BZ2_bzDecompress ( &strm );
1335 if (ret == BZ_OK) goto output_overflow_or_eof;
1336 if (ret != BZ_STREAM_END) goto errhandler;
1337
1338 /* normal termination */
1339 *destLen -= strm.avail_out;
1340 BZ2_bzDecompressEnd ( &strm );
1341 return BZ_OK;
1342
1343 output_overflow_or_eof:
1344 if (strm.avail_out > 0) {
1345 BZ2_bzDecompressEnd ( &strm );
1346 return BZ_UNEXPECTED_EOF;
1347 } else {
1348 BZ2_bzDecompressEnd ( &strm );
1349 return BZ_OUTBUFF_FULL;
1350 };
1351
1352 errhandler:
1353 BZ2_bzDecompressEnd ( &strm );
1354 return ret;
1355 }
1356
1357
1358 /*---------------------------------------------------*/
1359 /*--
1360 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1361 to support better zlib compatibility.
1362 This code is not _officially_ part of libbzip2 (yet);
1363 I haven't tested it, documented it, or considered the
1364 threading-safeness of it.
1365 If this code breaks, please contact both Yoshioka and me.
1366 --*/
1367 /*---------------------------------------------------*/
1368
1369 /*---------------------------------------------------*/
1370 /*--
1371 return version like "0.9.5d, 4-Sept-1999".
1372 --*/
BZ_API(BZ2_bzlibVersion)1373 const char * BZ_API(BZ2_bzlibVersion)(void)
1374 {
1375 return BZ_VERSION;
1376 }
1377
1378
1379 #ifndef BZ_NO_STDIO
1380 /*---------------------------------------------------*/
1381
1382 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1383 # include <fcntl.h>
1384 # include <io.h>
1385 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1386 #else
1387 # define SET_BINARY_MODE(file)
1388 #endif
1389 static
bzopen_or_bzdopen(const char * path,int fd,const char * mode,int open_mode)1390 BZFILE * bzopen_or_bzdopen
1391 ( const char *path, /* no use when bzdopen */
1392 int fd, /* no use when bzdopen */
1393 const char *mode,
1394 int open_mode) /* bzopen: 0, bzdopen:1 */
1395 {
1396 int bzerr;
1397 char unused[BZ_MAX_UNUSED];
1398 int blockSize100k = 9;
1399 int writing = 0;
1400 char mode2[10] = "";
1401 FILE *fp = NULL;
1402 BZFILE *bzfp = NULL;
1403 int verbosity = 0;
1404 int workFactor = 30;
1405 int smallMode = 0;
1406 int nUnused = 0;
1407
1408 if (mode == NULL) return NULL;
1409 while (*mode) {
1410 switch (*mode) {
1411 case 'r':
1412 writing = 0; break;
1413 case 'w':
1414 writing = 1; break;
1415 case 's':
1416 smallMode = 1; break;
1417 default:
1418 if (isdigit((unsigned char)(*mode))) {
1419 blockSize100k = *mode-BZ_HDR_0;
1420 }
1421 }
1422 mode++;
1423 }
1424 strcat(mode2, writing ? "w" : "r" );
1425 strcat(mode2,"b"); /* binary mode */
1426
1427 if (open_mode==0) {
1428 if (path==NULL || strcmp(path,"")==0) {
1429 fp = (writing ? stdout : stdin);
1430 SET_BINARY_MODE(fp);
1431 } else {
1432 fp = fopen(path,mode2);
1433 }
1434 } else {
1435 #ifdef BZ_STRICT_ANSI
1436 fp = NULL;
1437 #else
1438 fp = fdopen(fd,mode2);
1439 #endif
1440 }
1441 if (fp == NULL) return NULL;
1442
1443 if (writing) {
1444 /* Guard against total chaos and anarchy -- JRS */
1445 if (blockSize100k < 1) blockSize100k = 1;
1446 if (blockSize100k > 9) blockSize100k = 9;
1447 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1448 verbosity,workFactor);
1449 } else {
1450 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1451 unused,nUnused);
1452 }
1453 if (bzfp == NULL) {
1454 if (fp != stdin && fp != stdout) fclose(fp);
1455 return NULL;
1456 }
1457 return bzfp;
1458 }
1459
1460
1461 /*---------------------------------------------------*/
1462 /*--
1463 open file for read or write.
1464 ex) bzopen("file","w9")
1465 case path="" or NULL => use stdin or stdout.
1466 --*/
BZ_API(BZ2_bzopen)1467 BZFILE * BZ_API(BZ2_bzopen)
1468 ( const char *path,
1469 const char *mode )
1470 {
1471 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1472 }
1473
1474
1475 /*---------------------------------------------------*/
BZ_API(BZ2_bzdopen)1476 BZFILE * BZ_API(BZ2_bzdopen)
1477 ( int fd,
1478 const char *mode )
1479 {
1480 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1481 }
1482
1483
1484 /*---------------------------------------------------*/
BZ_API(BZ2_bzread)1485 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1486 {
1487 int bzerr, nread;
1488 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1489 nread = BZ2_bzRead(&bzerr,b,buf,len);
1490 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1491 return nread;
1492 } else {
1493 return -1;
1494 }
1495 }
1496
1497
1498 /*---------------------------------------------------*/
BZ_API(BZ2_bzwrite)1499 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1500 {
1501 int bzerr;
1502
1503 BZ2_bzWrite(&bzerr,b,buf,len);
1504 if(bzerr == BZ_OK){
1505 return len;
1506 }else{
1507 return -1;
1508 }
1509 }
1510
1511
1512 /*---------------------------------------------------*/
BZ_API(BZ2_bzflush)1513 int BZ_API(BZ2_bzflush) (BZFILE *b)
1514 {
1515 /* do nothing now... */
1516 return 0;
1517 }
1518
1519
1520 /*---------------------------------------------------*/
BZ_API(BZ2_bzclose)1521 void BZ_API(BZ2_bzclose) (BZFILE* b)
1522 {
1523 int bzerr;
1524 FILE *fp;
1525
1526 if (b==NULL) {return;}
1527 fp = ((bzFile *)b)->handle;
1528 if(((bzFile*)b)->writing){
1529 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1530 if(bzerr != BZ_OK){
1531 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1532 }
1533 }else{
1534 BZ2_bzReadClose(&bzerr,b);
1535 }
1536 if(fp!=stdin && fp!=stdout){
1537 fclose(fp);
1538 }
1539 }
1540
1541
1542 /*---------------------------------------------------*/
1543 /*--
1544 return last error code
1545 --*/
1546 static const char *bzerrorstrings[] = {
1547 "OK"
1548 ,"SEQUENCE_ERROR"
1549 ,"PARAM_ERROR"
1550 ,"MEM_ERROR"
1551 ,"DATA_ERROR"
1552 ,"DATA_ERROR_MAGIC"
1553 ,"IO_ERROR"
1554 ,"UNEXPECTED_EOF"
1555 ,"OUTBUFF_FULL"
1556 ,"CONFIG_ERROR"
1557 ,"???" /* for future */
1558 ,"???" /* for future */
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1561 ,"???" /* for future */
1562 ,"???" /* for future */
1563 };
1564
1565
BZ_API(BZ2_bzerror)1566 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1567 {
1568 int err = ((bzFile *)b)->lastErr;
1569
1570 if(err>0) err = 0;
1571 *errnum = err;
1572 return bzerrorstrings[err*-1];
1573 }
1574 #endif
1575
1576
1577 /*-------------------------------------------------------------*/
1578 /*--- end bzlib.c ---*/
1579 /*-------------------------------------------------------------*/
1580