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;
677
678 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
679
680 if (strm == NULL) return BZ_PARAM_ERROR;
681
682 s = strm->state;
683 s->strm = strm;
684
685 s->state = BZ_X_MAGIC_1;
686 s->bsLive = 0;
687 s->bsBuff = 0;
688 s->calculatedCombinedCRC = 0;
689 strm->total_in_lo32 = 0;
690 strm->total_in_hi32 = 0;
691 strm->total_out_lo32 = 0;
692 strm->total_out_hi32 = 0;
693
694 s->ll4 = NULL;
695 s->ll16 = NULL;
696 s->tt = NULL;
697 s->currBlockNo = 0;
698
699
700 return BZ_OK;
701 }
702
703
704 /*---------------------------------------------------*/
705 /* Return True iff data corruption is discovered.
706 Returns False if there is no problem.
707 */
708 static
709 Bool unRLE_obuf_to_output_FAST ( DState* s )
710 {
711 UChar k1;
712
713 if (s->blockRandomised) {
714
715 while (True) {
716 /* try to finish existing run */
717 while (True) {
718 if (s->strm->avail_out == 0) return False;
719 if (s->state_out_len == 0) break;
720 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
721 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
722 s->state_out_len--;
723 s->strm->next_out++;
724 s->strm->avail_out--;
725 s->strm->total_out_lo32++;
726 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
727 }
728
729 /* can a new run be started? */
730 if (s->nblock_used == s->save_nblock+1) return False;
731
732 /* Only caused by corrupt data stream? */
733 if (s->nblock_used > s->save_nblock+1)
734 return True;
735
736 s->state_out_len = 1;
737 s->state_out_ch = s->k0;
738 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
739 k1 ^= BZ_RAND_MASK; s->nblock_used++;
740 if (s->nblock_used == s->save_nblock+1) continue;
741 if (k1 != s->k0) { s->k0 = k1; continue; };
742
743 s->state_out_len = 2;
744 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
745 k1 ^= BZ_RAND_MASK; s->nblock_used++;
746 if (s->nblock_used == s->save_nblock+1) continue;
747 if (k1 != s->k0) { s->k0 = k1; continue; };
748
749 s->state_out_len = 3;
750 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
751 k1 ^= BZ_RAND_MASK; s->nblock_used++;
752 if (s->nblock_used == s->save_nblock+1) continue;
753 if (k1 != s->k0) { s->k0 = k1; continue; };
754
755 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
756 k1 ^= BZ_RAND_MASK; s->nblock_used++;
757 s->state_out_len = ((Int32)k1) + 4;
758 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
759 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
760 }
761
762 } else {
763
764 /* restore */
765 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
766 UChar c_state_out_ch = s->state_out_ch;
767 Int32 c_state_out_len = s->state_out_len;
768 Int32 c_nblock_used = s->nblock_used;
769 Int32 c_k0 = s->k0;
770 UInt32* c_tt = s->tt;
771 UInt32 c_tPos = s->tPos;
772 char* cs_next_out = s->strm->next_out;
773 unsigned int cs_avail_out = s->strm->avail_out;
774 Int32 ro_blockSize100k = s->blockSize100k;
775 /* end restore */
776
777 UInt32 avail_out_INIT = cs_avail_out;
778 Int32 s_save_nblockPP = s->save_nblock+1;
779 unsigned int total_out_lo32_old;
780
781 while (True) {
782
783 /* try to finish existing run */
784 if (c_state_out_len > 0) {
785 while (True) {
786 if (cs_avail_out == 0) goto return_notr;
787 if (c_state_out_len == 1) break;
788 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
789 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
790 c_state_out_len--;
791 cs_next_out++;
792 cs_avail_out--;
793 }
794 s_state_out_len_eq_one:
795 {
796 if (cs_avail_out == 0) {
797 c_state_out_len = 1; goto return_notr;
798 };
799 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
800 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
801 cs_next_out++;
802 cs_avail_out--;
803 }
804 }
805 /* Only caused by corrupt data stream? */
806 if (c_nblock_used > s_save_nblockPP)
807 return True;
808
809 /* can a new run be started? */
810 if (c_nblock_used == s_save_nblockPP) {
811 c_state_out_len = 0; goto return_notr;
812 };
813 c_state_out_ch = c_k0;
814 BZ_GET_FAST_C(k1); c_nblock_used++;
815 if (k1 != c_k0) {
816 c_k0 = k1; goto s_state_out_len_eq_one;
817 };
818 if (c_nblock_used == s_save_nblockPP)
819 goto s_state_out_len_eq_one;
820
821 c_state_out_len = 2;
822 BZ_GET_FAST_C(k1); c_nblock_used++;
823 if (c_nblock_used == s_save_nblockPP) continue;
824 if (k1 != c_k0) { c_k0 = k1; continue; };
825
826 c_state_out_len = 3;
827 BZ_GET_FAST_C(k1); c_nblock_used++;
828 if (c_nblock_used == s_save_nblockPP) continue;
829 if (k1 != c_k0) { c_k0 = k1; continue; };
830
831 BZ_GET_FAST_C(k1); c_nblock_used++;
832 c_state_out_len = ((Int32)k1) + 4;
833 BZ_GET_FAST_C(c_k0); c_nblock_used++;
834 }
835
836 return_notr:
837 total_out_lo32_old = s->strm->total_out_lo32;
838 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
839 if (s->strm->total_out_lo32 < total_out_lo32_old)
840 s->strm->total_out_hi32++;
841
842 /* save */
843 s->calculatedBlockCRC = c_calculatedBlockCRC;
844 s->state_out_ch = c_state_out_ch;
845 s->state_out_len = c_state_out_len;
846 s->nblock_used = c_nblock_used;
847 s->k0 = c_k0;
848 s->tt = c_tt;
849 s->tPos = c_tPos;
850 s->strm->next_out = cs_next_out;
851 s->strm->avail_out = cs_avail_out;
852 /* end save */
853 }
854 return False;
855 }
856
857
858
859 /*---------------------------------------------------*/
860 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
861 {
862 Int32 nb, na, mid;
863 nb = 0;
864 na = 256;
865 do {
866 mid = (nb + na) >> 1;
867 if (indx >= cftab[mid]) nb = mid; else na = mid;
868 }
869 while (na - nb != 1);
870 return nb;
871 }
872
873
874 /*---------------------------------------------------*/
875 /* Return True iff data corruption is discovered.
876 Returns False if there is no problem.
877 */
878 static
879 Bool unRLE_obuf_to_output_SMALL ( DState* s )
880 {
881 UChar k1;
882
883 if (s->blockRandomised) {
884
885 while (True) {
886 /* try to finish existing run */
887 while (True) {
888 if (s->strm->avail_out == 0) return False;
889 if (s->state_out_len == 0) break;
890 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
891 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
892 s->state_out_len--;
893 s->strm->next_out++;
894 s->strm->avail_out--;
895 s->strm->total_out_lo32++;
896 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
897 }
898
899 /* can a new run be started? */
900 if (s->nblock_used == s->save_nblock+1) return False;
901
902 /* Only caused by corrupt data stream? */
903 if (s->nblock_used > s->save_nblock+1)
904 return True;
905
906 s->state_out_len = 1;
907 s->state_out_ch = s->k0;
908 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
909 k1 ^= BZ_RAND_MASK; s->nblock_used++;
910 if (s->nblock_used == s->save_nblock+1) continue;
911 if (k1 != s->k0) { s->k0 = k1; continue; };
912
913 s->state_out_len = 2;
914 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
915 k1 ^= BZ_RAND_MASK; s->nblock_used++;
916 if (s->nblock_used == s->save_nblock+1) continue;
917 if (k1 != s->k0) { s->k0 = k1; continue; };
918
919 s->state_out_len = 3;
920 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
921 k1 ^= BZ_RAND_MASK; s->nblock_used++;
922 if (s->nblock_used == s->save_nblock+1) continue;
923 if (k1 != s->k0) { s->k0 = k1; continue; };
924
925 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
926 k1 ^= BZ_RAND_MASK; s->nblock_used++;
927 s->state_out_len = ((Int32)k1) + 4;
928 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
929 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
930 }
931
932 } else {
933
934 while (True) {
935 /* try to finish existing run */
936 while (True) {
937 if (s->strm->avail_out == 0) return False;
938 if (s->state_out_len == 0) break;
939 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
940 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
941 s->state_out_len--;
942 s->strm->next_out++;
943 s->strm->avail_out--;
944 s->strm->total_out_lo32++;
945 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
946 }
947
948 /* can a new run be started? */
949 if (s->nblock_used == s->save_nblock+1) return False;
950
951 /* Only caused by corrupt data stream? */
952 if (s->nblock_used > s->save_nblock+1)
953 return True;
954
955 s->state_out_len = 1;
956 s->state_out_ch = s->k0;
957 BZ_GET_SMALL(k1); s->nblock_used++;
958 if (s->nblock_used == s->save_nblock+1) continue;
959 if (k1 != s->k0) { s->k0 = k1; continue; };
960
961 s->state_out_len = 2;
962 BZ_GET_SMALL(k1); s->nblock_used++;
963 if (s->nblock_used == s->save_nblock+1) continue;
964 if (k1 != s->k0) { s->k0 = k1; continue; };
965
966 s->state_out_len = 3;
967 BZ_GET_SMALL(k1); s->nblock_used++;
968 if (s->nblock_used == s->save_nblock+1) continue;
969 if (k1 != s->k0) { s->k0 = k1; continue; };
970
971 BZ_GET_SMALL(k1); s->nblock_used++;
972 s->state_out_len = ((Int32)k1) + 4;
973 BZ_GET_SMALL(s->k0); s->nblock_used++;
974 }
975
976 }
977 }
978
979
980 /*---------------------------------------------------*/
981 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
982 {
983 Bool corrupt;
984 DState* s;
985 if (strm == NULL) return BZ_PARAM_ERROR;
986 s = strm->state;
987 if (s == NULL) return BZ_PARAM_ERROR;
988 if (s->strm != strm) return BZ_PARAM_ERROR;
989
990 while (True) {
991 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
992 if (s->state == BZ_X_OUTPUT) {
993 if (s->smallDecompress)
994 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
995 corrupt = unRLE_obuf_to_output_FAST ( s );
996 if (corrupt) return BZ_DATA_ERROR;
997 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
998 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
999 if (s->verbosity >= 3)
1000 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
1001 s->calculatedBlockCRC );
1002 if (s->verbosity >= 2) VPrintf0 ( "]" );
1003 if (s->calculatedBlockCRC != s->storedBlockCRC)
1004 return BZ_DATA_ERROR;
1005 s->calculatedCombinedCRC
1006 = (s->calculatedCombinedCRC << 1) |
1007 (s->calculatedCombinedCRC >> 31);
1008 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
1009 s->state = BZ_X_BLKHDR_1;
1010 } else {
1011 return BZ_OK;
1012 }
1013 }
1014 if (s->state >= BZ_X_MAGIC_1) {
1015 Int32 r = BZ2_decompress ( s );
1016 if (r == BZ_STREAM_END) {
1017 if (s->verbosity >= 3)
1018 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
1019 s->storedCombinedCRC, s->calculatedCombinedCRC );
1020 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
1021 return BZ_DATA_ERROR;
1022 return r;
1023 }
1024 if (s->state != BZ_X_OUTPUT) return r;
1025 }
1026 }
1027
1028 #if 0
1029 AssertH ( 0, 6001 );
1030
1031 return 0; /*NOTREACHED*/
1032 #endif
1033 }
1034
1035
1036 /*---------------------------------------------------*/
1037 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
1038 {
1039 DState* s;
1040 if (strm == NULL) return BZ_PARAM_ERROR;
1041 s = strm->state;
1042 if (s == NULL) return BZ_PARAM_ERROR;
1043 if (s->strm != strm) return BZ_PARAM_ERROR;
1044
1045 if (s->tt != NULL) BZFREE(s->tt);
1046 if (s->ll16 != NULL) BZFREE(s->ll16);
1047 if (s->ll4 != NULL) BZFREE(s->ll4);
1048
1049 BZFREE(strm->state);
1050 strm->state = NULL;
1051
1052 return BZ_OK;
1053 }
1054
1055 #ifndef BZ_NO_COMPRESS
1056
1057 #ifndef BZ_NO_STDIO
1058 /*---------------------------------------------------*/
1059 /*--- File I/O stuff ---*/
1060 /*---------------------------------------------------*/
1061
1062 #define BZ_SETERR(eee) \
1063 { \
1064 if (bzerror != NULL) *bzerror = eee; \
1065 if (bzf != NULL) bzf->lastErr = eee; \
1066 }
1067
1068 typedef
1069 struct {
1070 FILE* handle;
1071 Char buf[BZ_MAX_UNUSED];
1072 Int32 bufN;
1073 Bool writing;
1074 bz_stream strm;
1075 Int32 lastErr;
1076 Bool initialisedOk;
1077 }
1078 bzFile;
1079
1080
1081 /*---------------------------------------------*/
1082 static Bool myfeof ( FILE* f )
1083 {
1084 Int32 c = fgetc ( f );
1085 if (c == EOF) return True;
1086 ungetc ( c, f );
1087 return False;
1088 }
1089
1090
1091 /*---------------------------------------------------*/
1092 BZFILE* BZ_API(BZ2_bzWriteOpen)
1093 ( int* bzerror,
1094 FILE* f,
1095 int blockSize100k,
1096 int verbosity,
1097 int workFactor )
1098 {
1099 Int32 ret;
1100 bzFile* bzf = NULL;
1101
1102 BZ_SETERR(BZ_OK);
1103
1104 if (f == NULL ||
1105 (blockSize100k < 1 || blockSize100k > 9) ||
1106 (workFactor < 0 || workFactor > 250) ||
1107 (verbosity < 0 || verbosity > 4))
1108 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1109
1110 if (ferror(f))
1111 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1112
1113 bzf = malloc ( sizeof(bzFile) );
1114 if (bzf == NULL)
1115 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1116
1117 BZ_SETERR(BZ_OK);
1118 bzf->initialisedOk = False;
1119 bzf->bufN = 0;
1120 bzf->handle = f;
1121 bzf->writing = True;
1122 bzf->strm.bzalloc = NULL;
1123 bzf->strm.bzfree = NULL;
1124 bzf->strm.opaque = NULL;
1125
1126 if (workFactor == 0) workFactor = 30;
1127 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
1128 verbosity, workFactor );
1129 if (ret != BZ_OK)
1130 { BZ_SETERR(ret); free(bzf); return NULL; };
1131
1132 bzf->strm.avail_in = 0;
1133 bzf->initialisedOk = True;
1134 return bzf;
1135 }
1136
1137
1138
1139 /*---------------------------------------------------*/
1140 void BZ_API(BZ2_bzWrite)
1141 ( int* bzerror,
1142 BZFILE* b,
1143 void* buf,
1144 int len )
1145 {
1146 Int32 n, n2, ret;
1147 bzFile* bzf = (bzFile*)b;
1148
1149 BZ_SETERR(BZ_OK);
1150 if (bzf == NULL || buf == NULL || len < 0)
1151 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1152 if (!(bzf->writing))
1153 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1154 if (ferror(bzf->handle))
1155 { BZ_SETERR(BZ_IO_ERROR); return; };
1156
1157 if (len == 0)
1158 { BZ_SETERR(BZ_OK); return; };
1159
1160 bzf->strm.avail_in = len;
1161 bzf->strm.next_in = buf;
1162
1163 while (True) {
1164 bzf->strm.avail_out = BZ_MAX_UNUSED;
1165 bzf->strm.next_out = bzf->buf;
1166 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1167 if (ret != BZ_RUN_OK)
1168 { BZ_SETERR(ret); return; };
1169
1170 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1171 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1172 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1173 n, bzf->handle );
1174 if (n != n2 || ferror(bzf->handle))
1175 { BZ_SETERR(BZ_IO_ERROR); return; };
1176 }
1177
1178 if (bzf->strm.avail_in == 0)
1179 { BZ_SETERR(BZ_OK); return; };
1180 }
1181 }
1182
1183
1184 /*---------------------------------------------------*/
1185 void BZ_API(BZ2_bzWriteClose)
1186 ( int* bzerror,
1187 BZFILE* b,
1188 int abandon,
1189 unsigned int* nbytes_in,
1190 unsigned int* nbytes_out )
1191 {
1192 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1193 nbytes_in, NULL, nbytes_out, NULL );
1194 }
1195
1196
1197 void BZ_API(BZ2_bzWriteClose64)
1198 ( int* bzerror,
1199 BZFILE* b,
1200 int abandon,
1201 unsigned int* nbytes_in_lo32,
1202 unsigned int* nbytes_in_hi32,
1203 unsigned int* nbytes_out_lo32,
1204 unsigned int* nbytes_out_hi32 )
1205 {
1206 Int32 n, n2, ret;
1207 bzFile* bzf = (bzFile*)b;
1208
1209 if (bzf == NULL)
1210 { BZ_SETERR(BZ_OK); return; };
1211 if (!(bzf->writing))
1212 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1213 if (ferror(bzf->handle))
1214 { BZ_SETERR(BZ_IO_ERROR); return; };
1215
1216 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1217 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1218 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1219 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1220
1221 if ((!abandon) && bzf->lastErr == BZ_OK) {
1222 while (True) {
1223 bzf->strm.avail_out = BZ_MAX_UNUSED;
1224 bzf->strm.next_out = bzf->buf;
1225 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1226 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1227 { BZ_SETERR(ret); return; };
1228
1229 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1230 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1231 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1232 n, bzf->handle );
1233 if (n != n2 || ferror(bzf->handle))
1234 { BZ_SETERR(BZ_IO_ERROR); return; };
1235 }
1236
1237 if (ret == BZ_STREAM_END) break;
1238 }
1239 }
1240
1241 if ( !abandon && !ferror ( bzf->handle ) ) {
1242 fflush ( bzf->handle );
1243 if (ferror(bzf->handle))
1244 { BZ_SETERR(BZ_IO_ERROR); return; };
1245 }
1246
1247 if (nbytes_in_lo32 != NULL)
1248 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1249 if (nbytes_in_hi32 != NULL)
1250 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1251 if (nbytes_out_lo32 != NULL)
1252 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1253 if (nbytes_out_hi32 != NULL)
1254 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1255
1256 BZ_SETERR(BZ_OK);
1257 (void) BZ2_bzCompressEnd ( &(bzf->strm) );
1258 free ( bzf );
1259 }
1260
1261
1262 /*---------------------------------------------------*/
1263 BZFILE* BZ_API(BZ2_bzReadOpen)
1264 ( int* bzerror,
1265 FILE* f,
1266 int verbosity,
1267 int small,
1268 void* unused,
1269 int nUnused )
1270 {
1271 bzFile* bzf = NULL;
1272 int ret;
1273
1274 BZ_SETERR(BZ_OK);
1275
1276 if (f == NULL ||
1277 (small != 0 && small != 1) ||
1278 (verbosity < 0 || verbosity > 4) ||
1279 (unused == NULL && nUnused != 0) ||
1280 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1281 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1282
1283 if (ferror(f))
1284 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1285
1286 bzf = malloc ( sizeof(bzFile) );
1287 if (bzf == NULL)
1288 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1289
1290 BZ_SETERR(BZ_OK);
1291
1292 bzf->initialisedOk = False;
1293 bzf->handle = f;
1294 bzf->bufN = 0;
1295 bzf->writing = False;
1296 bzf->strm.bzalloc = NULL;
1297 bzf->strm.bzfree = NULL;
1298 bzf->strm.opaque = NULL;
1299
1300 while (nUnused > 0) {
1301 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1302 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1303 nUnused--;
1304 }
1305
1306 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1307 if (ret != BZ_OK)
1308 { BZ_SETERR(ret); free(bzf); return NULL; };
1309
1310 bzf->strm.avail_in = bzf->bufN;
1311 bzf->strm.next_in = bzf->buf;
1312
1313 bzf->initialisedOk = True;
1314 return bzf;
1315 }
1316
1317
1318 /*---------------------------------------------------*/
1319 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1320 {
1321 bzFile* bzf = (bzFile*)b;
1322
1323 BZ_SETERR(BZ_OK);
1324 if (bzf == NULL)
1325 { BZ_SETERR(BZ_OK); return; };
1326
1327 if (bzf->writing)
1328 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1329
1330 if (bzf->initialisedOk)
1331 (void) BZ2_bzDecompressEnd ( &(bzf->strm) );
1332 free ( bzf );
1333 }
1334
1335
1336 /*---------------------------------------------------*/
1337 int BZ_API(BZ2_bzRead)
1338 ( int* bzerror,
1339 BZFILE* b,
1340 void* buf,
1341 int len )
1342 {
1343 Int32 n, ret;
1344 bzFile* bzf = (bzFile*)b;
1345
1346 BZ_SETERR(BZ_OK);
1347
1348 if (bzf == NULL || buf == NULL || len < 0)
1349 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1350
1351 if (bzf->writing)
1352 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1353
1354 if (len == 0)
1355 { BZ_SETERR(BZ_OK); return 0; };
1356
1357 bzf->strm.avail_out = len;
1358 bzf->strm.next_out = buf;
1359
1360 while (True) {
1361
1362 if (ferror(bzf->handle))
1363 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1364
1365 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1366 n = fread ( bzf->buf, sizeof(UChar),
1367 BZ_MAX_UNUSED, bzf->handle );
1368 if (ferror(bzf->handle))
1369 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1370 bzf->bufN = n;
1371 bzf->strm.avail_in = bzf->bufN;
1372 bzf->strm.next_in = bzf->buf;
1373 }
1374
1375 ret = BZ2_bzDecompress ( &(bzf->strm) );
1376
1377 if (ret != BZ_OK && ret != BZ_STREAM_END)
1378 { BZ_SETERR(ret); return 0; };
1379
1380 if (ret == BZ_OK && myfeof(bzf->handle) &&
1381 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1382 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1383
1384 if (ret == BZ_STREAM_END)
1385 { BZ_SETERR(BZ_STREAM_END);
1386 return len - bzf->strm.avail_out; };
1387 if (bzf->strm.avail_out == 0)
1388 { BZ_SETERR(BZ_OK); return len; };
1389
1390 }
1391
1392 return 0; /*not reached*/
1393 }
1394
1395
1396 /*---------------------------------------------------*/
1397 void BZ_API(BZ2_bzReadGetUnused)
1398 ( int* bzerror,
1399 BZFILE* b,
1400 void** unused,
1401 int* nUnused )
1402 {
1403 bzFile* bzf = (bzFile*)b;
1404 if (bzf == NULL)
1405 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1406 if (bzf->lastErr != BZ_STREAM_END)
1407 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1408 if (unused == NULL || nUnused == NULL)
1409 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1410
1411 BZ_SETERR(BZ_OK);
1412 *nUnused = bzf->strm.avail_in;
1413 *unused = bzf->strm.next_in;
1414 }
1415 #endif
1416
1417
1418 /*---------------------------------------------------*/
1419 /*--- Misc convenience stuff ---*/
1420 /*---------------------------------------------------*/
1421
1422 /*---------------------------------------------------*/
1423 int BZ_API(BZ2_bzBuffToBuffCompress)
1424 ( char* dest,
1425 unsigned int* destLen,
1426 char* source,
1427 unsigned int sourceLen,
1428 int blockSize100k,
1429 int verbosity,
1430 int workFactor )
1431 {
1432 bz_stream strm;
1433 int ret;
1434
1435 if (dest == NULL || destLen == NULL ||
1436 source == NULL ||
1437 blockSize100k < 1 || blockSize100k > 9 ||
1438 verbosity < 0 || verbosity > 4 ||
1439 workFactor < 0 || workFactor > 250)
1440 return BZ_PARAM_ERROR;
1441
1442 if (workFactor == 0) workFactor = 30;
1443 strm.bzalloc = NULL;
1444 strm.bzfree = NULL;
1445 strm.opaque = NULL;
1446 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1447 verbosity, workFactor );
1448 if (ret != BZ_OK) return ret;
1449
1450 strm.next_in = source;
1451 strm.next_out = dest;
1452 strm.avail_in = sourceLen;
1453 strm.avail_out = *destLen;
1454
1455 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1456 if (ret == BZ_FINISH_OK) goto output_overflow;
1457 if (ret != BZ_STREAM_END) goto errhandler;
1458
1459 /* normal termination */
1460 *destLen -= strm.avail_out;
1461 (void) BZ2_bzCompressEnd ( &strm );
1462 return BZ_OK;
1463
1464 output_overflow:
1465 (void) BZ2_bzCompressEnd ( &strm );
1466 return BZ_OUTBUFF_FULL;
1467
1468 errhandler:
1469 (void) BZ2_bzCompressEnd ( &strm );
1470 return ret;
1471 }
1472
1473
1474 /*---------------------------------------------------*/
1475 int BZ_API(BZ2_bzBuffToBuffDecompress)
1476 ( char* dest,
1477 unsigned int* destLen,
1478 char* source,
1479 unsigned int sourceLen,
1480 int small,
1481 int verbosity )
1482 {
1483 bz_stream strm;
1484 int ret;
1485
1486 if (dest == NULL || destLen == NULL ||
1487 source == NULL ||
1488 (small != 0 && small != 1) ||
1489 verbosity < 0 || verbosity > 4)
1490 return BZ_PARAM_ERROR;
1491
1492 strm.bzalloc = NULL;
1493 strm.bzfree = NULL;
1494 strm.opaque = NULL;
1495 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1496 if (ret != BZ_OK) return ret;
1497
1498 strm.next_in = source;
1499 strm.next_out = dest;
1500 strm.avail_in = sourceLen;
1501 strm.avail_out = *destLen;
1502
1503 ret = BZ2_bzDecompress ( &strm );
1504 if (ret == BZ_OK) goto output_overflow_or_eof;
1505 if (ret != BZ_STREAM_END) goto errhandler;
1506
1507 /* normal termination */
1508 *destLen -= strm.avail_out;
1509 (void) BZ2_bzDecompressEnd ( &strm );
1510 return BZ_OK;
1511
1512 output_overflow_or_eof:
1513 if (strm.avail_out > 0) {
1514 (void) BZ2_bzDecompressEnd ( &strm );
1515 return BZ_UNEXPECTED_EOF;
1516 } else {
1517 (void) BZ2_bzDecompressEnd ( &strm );
1518 return BZ_OUTBUFF_FULL;
1519 }
1520
1521 errhandler:
1522 (void) BZ2_bzDecompressEnd ( &strm );
1523 return ret;
1524 }
1525
1526
1527 /*---------------------------------------------------*/
1528 /*--
1529 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1530 to support better zlib compatibility.
1531 This code is not _officially_ part of libbzip2 (yet);
1532 I haven't tested it, documented it, or considered the
1533 threading-safeness of it.
1534 If this code breaks, please contact both Yoshioka and me.
1535 --*/
1536 /*---------------------------------------------------*/
1537
1538 /*---------------------------------------------------*/
1539 /*--
1540 return version like "0.9.5d, 4-Sept-1999".
1541 --*/
1542 const char * BZ_API(BZ2_bzlibVersion)(void)
1543 {
1544 return BZ_VERSION;
1545 }
1546
1547
1548 #ifndef BZ_NO_STDIO
1549 /*---------------------------------------------------*/
1550
1551 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1552 # include <fcntl.h>
1553 # include <io.h>
1554 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1555 #else
1556 # define SET_BINARY_MODE(file)
1557 #endif
1558 static
1559 BZFILE * bzopen_or_bzdopen
1560 ( const char *path, /* no use when bzdopen */
1561 int fd, /* no use when bzdopen */
1562 const char *mode,
1563 int open_mode) /* bzopen: 0, bzdopen:1 */
1564 {
1565 int bzerr;
1566 char unused[BZ_MAX_UNUSED];
1567 int blockSize100k = 9;
1568 int writing = 0;
1569 char mode2[10] = "";
1570 FILE *fp = NULL;
1571 BZFILE *bzfp = NULL;
1572 int verbosity = 0;
1573 int workFactor = 30;
1574 int smallMode = 0;
1575 int nUnused = 0;
1576
1577 if (mode == NULL) return NULL;
1578 while (*mode) {
1579 switch (*mode) {
1580 case 'r':
1581 writing = 0; break;
1582 case 'w':
1583 writing = 1; break;
1584 case 's':
1585 smallMode = 1; break;
1586 default:
1587 if (isdigit((int)(*mode))) {
1588 blockSize100k = *mode-BZ_HDR_0;
1589 }
1590 }
1591 mode++;
1592 }
1593 strcat(mode2, writing ? "w" : "r" );
1594 strcat(mode2,"b"); /* binary mode */
1595
1596 if (open_mode==0) {
1597 if (path==NULL || strcmp(path,"")==0) {
1598 fp = (writing ? stdout : stdin);
1599 SET_BINARY_MODE(fp);
1600 } else {
1601 fp = fopen(path,mode2);
1602 }
1603 } else {
1604 #ifdef BZ_STRICT_ANSI
1605 fp = NULL;
1606 #else
1607 fp = fdopen(fd,mode2);
1608 #endif
1609 }
1610 if (fp == NULL) return NULL;
1611
1612 if (writing) {
1613 /* Guard against total chaos and anarchy -- JRS */
1614 if (blockSize100k < 1) blockSize100k = 1;
1615 if (blockSize100k > 9) blockSize100k = 9;
1616 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1617 verbosity,workFactor);
1618 } else {
1619 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1620 unused,nUnused);
1621 }
1622 if (bzfp == NULL) {
1623 if (fp != stdin && fp != stdout) fclose(fp);
1624 return NULL;
1625 }
1626 return bzfp;
1627 }
1628
1629
1630 /*---------------------------------------------------*/
1631 /*--
1632 open file for read or write.
1633 ex) bzopen("file","w9")
1634 case path="" or NULL => use stdin or stdout.
1635 --*/
1636 BZFILE * BZ_API(BZ2_bzopen)
1637 ( const char *path,
1638 const char *mode )
1639 {
1640 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1641 }
1642
1643
1644 /*---------------------------------------------------*/
1645 BZFILE * BZ_API(BZ2_bzdopen)
1646 ( int fd,
1647 const char *mode )
1648 {
1649 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1650 }
1651
1652
1653 /*---------------------------------------------------*/
1654 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1655 {
1656 int bzerr, nread;
1657 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1658 nread = BZ2_bzRead(&bzerr,b,buf,len);
1659 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1660 return nread;
1661 } else {
1662 return -1;
1663 }
1664 }
1665
1666
1667 /*---------------------------------------------------*/
1668 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1669 {
1670 int bzerr;
1671
1672 BZ2_bzWrite(&bzerr,b,buf,len);
1673 if(bzerr == BZ_OK){
1674 return len;
1675 }else{
1676 return -1;
1677 }
1678 }
1679
1680
1681 /*---------------------------------------------------*/
1682 int BZ_API(BZ2_bzflush) (BZFILE *b)
1683 {
1684 /* do nothing now... */
1685 return 0;
1686 }
1687
1688
1689 /*---------------------------------------------------*/
1690 void BZ_API(BZ2_bzclose) (BZFILE* b)
1691 {
1692 int bzerr;
1693 FILE *fp;
1694
1695 if (b==NULL) {return;}
1696 fp = ((bzFile *)b)->handle;
1697 if(((bzFile*)b)->writing){
1698 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1699 if(bzerr != BZ_OK){
1700 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1701 }
1702 }else{
1703 BZ2_bzReadClose(&bzerr,b);
1704 }
1705 if(fp!=stdin && fp!=stdout){
1706 fclose(fp);
1707 }
1708 }
1709
1710
1711 /*---------------------------------------------------*/
1712 /*--
1713 return last error code
1714 --*/
1715 static const char *bzerrorstrings[] = {
1716 "OK"
1717 ,"SEQUENCE_ERROR"
1718 ,"PARAM_ERROR"
1719 ,"MEM_ERROR"
1720 ,"DATA_ERROR"
1721 ,"DATA_ERROR_MAGIC"
1722 ,"IO_ERROR"
1723 ,"UNEXPECTED_EOF"
1724 ,"OUTBUFF_FULL"
1725 ,"CONFIG_ERROR"
1726 ,"???" /* for future */
1727 ,"???" /* for future */
1728 ,"???" /* for future */
1729 ,"???" /* for future */
1730 ,"???" /* for future */
1731 ,"???" /* for future */
1732 };
1733
1734
1735 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1736 {
1737 int err = ((bzFile *)b)->lastErr;
1738
1739 if(err>0) err = 0;
1740 *errnum = err;
1741 return bzerrorstrings[err*-1];
1742 }
1743 #endif
1744
1745 #endif /* BZ_NO_COMPRESS */
1746
1747 /*-------------------------------------------------------------*/
1748 /*--- end bzlib.c ---*/
1749 /*-------------------------------------------------------------*/