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