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 #ifndef BZ_NO_COMPRESS
34
35 /*---------------------------------------------------*/
36 /*--- Compression stuff ---*/
37 /*---------------------------------------------------*/
38
39
40 /*---------------------------------------------------*/
41 #ifndef BZ_NO_STDIO
BZ2_bz__AssertH__fail(int errcode)42 void BZ2_bz__AssertH__fail ( int errcode )
43 {
44 fprintf(stderr,
45 "\n\nbzip2/libbzip2: internal error number %d.\n"
46 "This is a bug in bzip2/libbzip2, %s.\n"
47 "Please report it to: bzip2-devel@sourceware.org. If this happened\n"
48 "when you were using some program which uses libbzip2 as a\n"
49 "component, you should also report this bug to the author(s)\n"
50 "of that program. Please make an effort to report this bug;\n"
51 "timely and accurate bug reports eventually lead to higher\n"
52 "quality software. Thanks.\n\n",
53 errcode,
54 BZ2_bzlibVersion()
55 );
56
57 if (errcode == 1007) {
58 fprintf(stderr,
59 "\n*** A special note about internal error number 1007 ***\n"
60 "\n"
61 "Experience suggests that a common cause of i.e. 1007\n"
62 "is unreliable memory or other hardware. The 1007 assertion\n"
63 "just happens to cross-check the results of huge numbers of\n"
64 "memory reads/writes, and so acts (unintendedly) as a stress\n"
65 "test of your memory system.\n"
66 "\n"
67 "I suggest the following: try compressing the file again,\n"
68 "possibly monitoring progress in detail with the -vv flag.\n"
69 "\n"
70 "* If the error cannot be reproduced, and/or happens at different\n"
71 " points in compression, you may have a flaky memory system.\n"
72 " Try a memory-test program. I have used Memtest86\n"
73 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
74 " Memtest86 tests memory much more thorougly than your BIOSs\n"
75 " power-on test, and may find failures that the BIOS doesn't.\n"
76 "\n"
77 "* If the error can be repeatably reproduced, this is a bug in\n"
78 " bzip2, and I would very much like to hear about it. Please\n"
79 " let me know, and, ideally, save a copy of the file causing the\n"
80 " problem -- without which I will be unable to investigate it.\n"
81 "\n"
82 );
83 }
84
85 exit(3);
86 }
87 #endif
88
89 #endif /* BZ_NO_COMPRESS */
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 #ifndef BZ_NO_COMPRESS
117
118 /*---------------------------------------------------*/
119 static
prepare_new_block(EState * s)120 void prepare_new_block ( EState* s )
121 {
122 Int32 i;
123 s->nblock = 0;
124 s->numZ = 0;
125 s->state_out_pos = 0;
126 BZ_INITIALISE_CRC ( s->blockCRC );
127 for (i = 0; i < 256; i++) s->inUse[i] = False;
128 s->blockNo++;
129 }
130
131
132 /*---------------------------------------------------*/
133 static
init_RL(EState * s)134 void init_RL ( EState* s )
135 {
136 s->state_in_ch = 256;
137 s->state_in_len = 0;
138 }
139
140
141 static
isempty_RL(EState * s)142 Bool isempty_RL ( EState* s )
143 {
144 if (s->state_in_ch < 256 && s->state_in_len > 0)
145 return False; else
146 return True;
147 }
148
149
150 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressInit)151 int BZ_API(BZ2_bzCompressInit)
152 ( bz_stream* strm,
153 int blockSize100k,
154 int verbosity,
155 int workFactor )
156 {
157 Int32 n;
158 EState* s;
159
160 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
161
162 if (strm == NULL ||
163 blockSize100k < 1 || blockSize100k > 9 ||
164 workFactor < 0 || workFactor > 250)
165 return BZ_PARAM_ERROR;
166
167 if (workFactor == 0) workFactor = 30;
168 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
169 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
170
171 s = BZALLOC( sizeof(EState) );
172 if (s == NULL) return BZ_MEM_ERROR;
173 s->strm = strm;
174
175 s->arr1 = NULL;
176 s->arr2 = NULL;
177 s->ftab = NULL;
178
179 n = 100000 * blockSize100k;
180 s->arr1 = BZALLOC( n * sizeof(UInt32) );
181 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
182 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
183
184 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
185 if (s->arr1 != NULL) BZFREE(s->arr1);
186 if (s->arr2 != NULL) BZFREE(s->arr2);
187 if (s->ftab != NULL) BZFREE(s->ftab);
188 if (s != NULL) BZFREE(s);
189 return BZ_MEM_ERROR;
190 }
191
192 s->blockNo = 0;
193 s->state = BZ_S_INPUT;
194 s->mode = BZ_M_RUNNING;
195 s->combinedCRC = 0;
196 s->blockSize100k = blockSize100k;
197 s->nblockMAX = 100000 * blockSize100k - 19;
198 s->verbosity = verbosity;
199 s->workFactor = workFactor;
200
201 s->block = (UChar*)s->arr2;
202 s->mtfv = (UInt16*)s->arr1;
203 s->zbits = NULL;
204 s->ptr = (UInt32*)s->arr1;
205
206 strm->state = s;
207 strm->total_in_lo32 = 0;
208 strm->total_in_hi32 = 0;
209 strm->total_out_lo32 = 0;
210 strm->total_out_hi32 = 0;
211 init_RL ( s );
212 prepare_new_block ( s );
213 return BZ_OK;
214 }
215
216
217 /*---------------------------------------------------*/
218 static
add_pair_to_block(EState * s)219 void add_pair_to_block ( EState* s )
220 {
221 Int32 i;
222 UChar ch = (UChar)(s->state_in_ch);
223 for (i = 0; i < s->state_in_len; i++) {
224 BZ_UPDATE_CRC( s->blockCRC, ch );
225 }
226 s->inUse[s->state_in_ch] = True;
227 switch (s->state_in_len) {
228 case 1:
229 s->block[s->nblock] = (UChar)ch; s->nblock++;
230 break;
231 case 2:
232 s->block[s->nblock] = (UChar)ch; s->nblock++;
233 s->block[s->nblock] = (UChar)ch; s->nblock++;
234 break;
235 case 3:
236 s->block[s->nblock] = (UChar)ch; s->nblock++;
237 s->block[s->nblock] = (UChar)ch; s->nblock++;
238 s->block[s->nblock] = (UChar)ch; s->nblock++;
239 break;
240 default:
241 s->inUse[s->state_in_len-4] = True;
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)ch; s->nblock++;
246 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
247 s->nblock++;
248 break;
249 }
250 }
251
252
253 /*---------------------------------------------------*/
254 static
flush_RL(EState * s)255 void flush_RL ( EState* s )
256 {
257 if (s->state_in_ch < 256) add_pair_to_block ( s );
258 init_RL ( s );
259 }
260
261
262 /*---------------------------------------------------*/
263 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
264 { \
265 UInt32 zchh = (UInt32)(zchh0); \
266 /*-- fast track the common case --*/ \
267 if (zchh != zs->state_in_ch && \
268 zs->state_in_len == 1) { \
269 UChar ch = (UChar)(zs->state_in_ch); \
270 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
271 zs->inUse[zs->state_in_ch] = True; \
272 zs->block[zs->nblock] = (UChar)ch; \
273 zs->nblock++; \
274 zs->state_in_ch = zchh; \
275 } \
276 else \
277 /*-- general, uncommon cases --*/ \
278 if (zchh != zs->state_in_ch || \
279 zs->state_in_len == 255) { \
280 if (zs->state_in_ch < 256) \
281 add_pair_to_block ( zs ); \
282 zs->state_in_ch = zchh; \
283 zs->state_in_len = 1; \
284 } else { \
285 zs->state_in_len++; \
286 } \
287 }
288
289
290 /*---------------------------------------------------*/
291 static
copy_input_until_stop(EState * s)292 Bool copy_input_until_stop ( EState* s )
293 {
294 Bool progress_in = False;
295
296 if (s->mode == BZ_M_RUNNING) {
297
298 /*-- fast track the common case --*/
299 while (True) {
300 /*-- block full? --*/
301 if (s->nblock >= s->nblockMAX) break;
302 /*-- no input? --*/
303 if (s->strm->avail_in == 0) break;
304 progress_in = True;
305 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
306 s->strm->next_in++;
307 s->strm->avail_in--;
308 s->strm->total_in_lo32++;
309 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
310 }
311
312 } else {
313
314 /*-- general, uncommon case --*/
315 while (True) {
316 /*-- block full? --*/
317 if (s->nblock >= s->nblockMAX) break;
318 /*-- no input? --*/
319 if (s->strm->avail_in == 0) break;
320 /*-- flush/finish end? --*/
321 if (s->avail_in_expect == 0) break;
322 progress_in = True;
323 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
324 s->strm->next_in++;
325 s->strm->avail_in--;
326 s->strm->total_in_lo32++;
327 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
328 s->avail_in_expect--;
329 }
330 }
331 return progress_in;
332 }
333
334
335 /*---------------------------------------------------*/
336 static
copy_output_until_stop(EState * s)337 Bool copy_output_until_stop ( EState* s )
338 {
339 Bool progress_out = False;
340
341 while (True) {
342
343 /*-- no output space? --*/
344 if (s->strm->avail_out == 0) break;
345
346 /*-- block done? --*/
347 if (s->state_out_pos >= s->numZ) break;
348
349 progress_out = True;
350 *(s->strm->next_out) = s->zbits[s->state_out_pos];
351 s->state_out_pos++;
352 s->strm->avail_out--;
353 s->strm->next_out++;
354 s->strm->total_out_lo32++;
355 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
356 }
357
358 return progress_out;
359 }
360
361
362 /*---------------------------------------------------*/
363 static
handle_compress(bz_stream * strm)364 Bool handle_compress ( bz_stream* strm )
365 {
366 Bool progress_in = False;
367 Bool progress_out = False;
368 EState* s = strm->state;
369
370 while (True) {
371
372 if (s->state == BZ_S_OUTPUT) {
373 progress_out |= copy_output_until_stop ( s );
374 if (s->state_out_pos < s->numZ) break;
375 if (s->mode == BZ_M_FINISHING &&
376 s->avail_in_expect == 0 &&
377 isempty_RL(s)) break;
378 prepare_new_block ( s );
379 s->state = BZ_S_INPUT;
380 if (s->mode == BZ_M_FLUSHING &&
381 s->avail_in_expect == 0 &&
382 isempty_RL(s)) break;
383 }
384
385 if (s->state == BZ_S_INPUT) {
386 progress_in |= copy_input_until_stop ( s );
387 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
388 flush_RL ( s );
389 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
390 s->state = BZ_S_OUTPUT;
391 }
392 else
393 if (s->nblock >= s->nblockMAX) {
394 BZ2_compressBlock ( s, False );
395 s->state = BZ_S_OUTPUT;
396 }
397 else
398 if (s->strm->avail_in == 0) {
399 break;
400 }
401 }
402
403 }
404
405 return progress_in || progress_out;
406 }
407
408
409 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompress)410 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
411 {
412 Bool progress;
413 EState* s;
414 if (strm == NULL) return BZ_PARAM_ERROR;
415 s = strm->state;
416 if (s == NULL) return BZ_PARAM_ERROR;
417 if (s->strm != strm) return BZ_PARAM_ERROR;
418
419 preswitch:
420 switch (s->mode) {
421
422 case BZ_M_IDLE:
423 return BZ_SEQUENCE_ERROR;
424
425 case BZ_M_RUNNING:
426 if (action == BZ_RUN) {
427 progress = handle_compress ( strm );
428 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
429 }
430 else
431 if (action == BZ_FLUSH) {
432 s->avail_in_expect = strm->avail_in;
433 s->mode = BZ_M_FLUSHING;
434 goto preswitch;
435 }
436 else
437 if (action == BZ_FINISH) {
438 s->avail_in_expect = strm->avail_in;
439 s->mode = BZ_M_FINISHING;
440 goto preswitch;
441 }
442 else
443 return BZ_PARAM_ERROR;
444
445 case BZ_M_FLUSHING:
446 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
447 if (s->avail_in_expect != s->strm->avail_in)
448 return BZ_SEQUENCE_ERROR;
449 progress = handle_compress ( strm );
450 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
451 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
452 s->mode = BZ_M_RUNNING;
453 return BZ_RUN_OK;
454
455 case BZ_M_FINISHING:
456 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
457 if (s->avail_in_expect != s->strm->avail_in)
458 return BZ_SEQUENCE_ERROR;
459 progress = handle_compress ( strm );
460 if (!progress) return BZ_SEQUENCE_ERROR;
461 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
462 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
463 s->mode = BZ_M_IDLE;
464 return BZ_STREAM_END;
465 }
466 return BZ_OK; /*--not reached--*/
467 }
468
469
470 /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressEnd)471 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
472 {
473 EState* s;
474 if (strm == NULL) return BZ_PARAM_ERROR;
475 s = strm->state;
476 if (s == NULL) return BZ_PARAM_ERROR;
477 if (s->strm != strm) return BZ_PARAM_ERROR;
478
479 if (s->arr1 != NULL) BZFREE(s->arr1);
480 if (s->arr2 != NULL) BZFREE(s->arr2);
481 if (s->ftab != NULL) BZFREE(s->ftab);
482 BZFREE(strm->state);
483
484 strm->state = NULL;
485
486 return BZ_OK;
487 }
488
489 #endif /* BZ_NO_COMPRESS */
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 = 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 /*---------------------------------------------------*/
BZ2_indexIntoF(Int32 indx,Int32 * cftab)691 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
692 {
693 Int32 nb, na, mid;
694 nb = 0;
695 na = 256;
696 do {
697 mid = (nb + na) >> 1;
698 if (indx >= cftab[mid]) nb = mid; else na = mid;
699 }
700 while (na - nb != 1);
701 return nb;
702 }
703
704
705 /*---------------------------------------------------*/
706 /* Return True iff data corruption is discovered.
707 Returns False if there is no problem.
708 */
709 static
unRLE_obuf_to_output_SMALL(DState * s)710 Bool unRLE_obuf_to_output_SMALL ( DState* s )
711 {
712 UChar k1;
713
714 if (s->blockRandomised) {
715
716 while (True) {
717 /* try to finish existing run */
718 while (True) {
719 if (s->strm->avail_out == 0) return False;
720 if (s->state_out_len == 0) break;
721 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
722 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
723 s->state_out_len--;
724 s->strm->next_out++;
725 s->strm->avail_out--;
726 s->strm->total_out_lo32++;
727 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
728 }
729
730 /* can a new run be started? */
731 if (s->nblock_used == s->save_nblock+1) return False;
732
733 /* Only caused by corrupt data stream? */
734 if (s->nblock_used > s->save_nblock+1)
735 return True;
736
737 s->state_out_len = 1;
738 s->state_out_ch = s->k0;
739 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
740 k1 ^= BZ_RAND_MASK; s->nblock_used++;
741 if (s->nblock_used == s->save_nblock+1) continue;
742 if (k1 != s->k0) { s->k0 = k1; continue; };
743
744 s->state_out_len = 2;
745 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
746 k1 ^= BZ_RAND_MASK; s->nblock_used++;
747 if (s->nblock_used == s->save_nblock+1) continue;
748 if (k1 != s->k0) { s->k0 = k1; continue; };
749
750 s->state_out_len = 3;
751 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
752 k1 ^= BZ_RAND_MASK; s->nblock_used++;
753 if (s->nblock_used == s->save_nblock+1) continue;
754 if (k1 != s->k0) { s->k0 = k1; continue; };
755
756 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
757 k1 ^= BZ_RAND_MASK; s->nblock_used++;
758 s->state_out_len = ((Int32)k1) + 4;
759 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
760 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
761 }
762
763 } else {
764
765 while (True) {
766 /* try to finish existing run */
767 while (True) {
768 if (s->strm->avail_out == 0) return False;
769 if (s->state_out_len == 0) break;
770 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
771 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
772 s->state_out_len--;
773 s->strm->next_out++;
774 s->strm->avail_out--;
775 s->strm->total_out_lo32++;
776 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
777 }
778
779 /* can a new run be started? */
780 if (s->nblock_used == s->save_nblock+1) return False;
781
782 /* Only caused by corrupt data stream? */
783 if (s->nblock_used > s->save_nblock+1)
784 return True;
785
786 s->state_out_len = 1;
787 s->state_out_ch = s->k0;
788 BZ_GET_SMALL(k1); s->nblock_used++;
789 if (s->nblock_used == s->save_nblock+1) continue;
790 if (k1 != s->k0) { s->k0 = k1; continue; };
791
792 s->state_out_len = 2;
793 BZ_GET_SMALL(k1); s->nblock_used++;
794 if (s->nblock_used == s->save_nblock+1) continue;
795 if (k1 != s->k0) { s->k0 = k1; continue; };
796
797 s->state_out_len = 3;
798 BZ_GET_SMALL(k1); s->nblock_used++;
799 if (s->nblock_used == s->save_nblock+1) continue;
800 if (k1 != s->k0) { s->k0 = k1; continue; };
801
802 BZ_GET_SMALL(k1); s->nblock_used++;
803 s->state_out_len = ((Int32)k1) + 4;
804 BZ_GET_SMALL(s->k0); s->nblock_used++;
805 }
806
807 }
808 }
809
810
811 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompress)812 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
813 {
814 Bool corrupt;
815 DState* s;
816 if (strm == NULL) return BZ_PARAM_ERROR;
817 s = strm->state;
818 if (s == NULL) return BZ_PARAM_ERROR;
819 if (s->strm != strm) return BZ_PARAM_ERROR;
820
821 while (True) {
822 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
823 if (s->state == BZ_X_OUTPUT) {
824 if (s->smallDecompress)
825 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
826 corrupt = unRLE_obuf_to_output_FAST ( s );
827 if (corrupt) return BZ_DATA_ERROR;
828 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
829 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
830 if (s->verbosity >= 3)
831 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
832 s->calculatedBlockCRC );
833 if (s->verbosity >= 2) VPrintf0 ( "]" );
834 if (s->calculatedBlockCRC != s->storedBlockCRC)
835 return BZ_DATA_ERROR;
836 s->calculatedCombinedCRC
837 = (s->calculatedCombinedCRC << 1) |
838 (s->calculatedCombinedCRC >> 31);
839 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
840 s->state = BZ_X_BLKHDR_1;
841 } else {
842 return BZ_OK;
843 }
844 }
845 if (s->state >= BZ_X_MAGIC_1) {
846 Int32 r = BZ2_decompress ( s );
847 if (r == BZ_STREAM_END) {
848 if (s->verbosity >= 3)
849 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
850 s->storedCombinedCRC, s->calculatedCombinedCRC );
851 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
852 return BZ_DATA_ERROR;
853 return r;
854 }
855 if (s->state != BZ_X_OUTPUT) return r;
856 }
857 }
858
859 AssertH ( 0, 6001 );
860
861 return 0; /*NOTREACHED*/
862 }
863
864
865 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressEnd)866 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
867 {
868 DState* s;
869 if (strm == NULL) return BZ_PARAM_ERROR;
870 s = strm->state;
871 if (s == NULL) return BZ_PARAM_ERROR;
872 if (s->strm != strm) return BZ_PARAM_ERROR;
873
874 if (s->tt != NULL) BZFREE(s->tt);
875 if (s->ll16 != NULL) BZFREE(s->ll16);
876 if (s->ll4 != NULL) BZFREE(s->ll4);
877
878 BZFREE(strm->state);
879 strm->state = NULL;
880
881 return BZ_OK;
882 }
883
884 #ifndef BZ_NO_COMPRESS
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 = 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 = 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 = 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 = 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((int)(*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 #endif /* BZ_NO_COMPRESS */
1575
1576 /*-------------------------------------------------------------*/
1577 /*--- end bzlib.c ---*/
1578 /*-------------------------------------------------------------*/
1579