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