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