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