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