wg.conf.5: Fix a typo (in-inline comments are *not* allowed)
[dragonfly.git] / contrib / bzip2 / bzlib.c
blob2574a87b29323c9950f541e8dd50d4cc62939dd9
2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions. ---*/
4 /*--- bzlib.c ---*/
5 /*-------------------------------------------------------------*/
7 /* ------------------------------------------------------------------
8 This file is part of bzip2/libbzip2, a program and library for
9 lossless, block-sorting data compression.
11 bzip2/libbzip2 version 1.0.8 of 13 July 2019
12 Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
14 Please read the WARNING, DISCLAIMER and PATENTS sections in the
15 README file.
17 This program is released under the terms of the license contained
18 in the file LICENSE.
19 ------------------------------------------------------------------ */
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.
31 #include "bzlib_private.h"
33 #ifndef BZ_NO_COMPRESS
35 /*---------------------------------------------------*/
36 /*--- Compression stuff ---*/
37 /*---------------------------------------------------*/
40 /*---------------------------------------------------*/
41 #ifndef BZ_NO_STDIO
42 void BZ2_bz__AssertH__fail ( int errcode )
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: bzip2-devel@sourceware.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.\n\n",
53 errcode,
54 BZ2_bzlibVersion()
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"
85 exit(3);
87 #endif
89 #endif /* BZ_NO_COMPRESS */
91 /*---------------------------------------------------*/
92 static
93 int bz_config_ok ( void )
95 if (sizeof(int) != 4) return 0;
96 if (sizeof(short) != 2) return 0;
97 if (sizeof(char) != 1) return 0;
98 return 1;
102 /*---------------------------------------------------*/
103 static
104 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
106 void* v = malloc ( items * size );
107 return v;
110 static
111 void default_bzfree ( void* opaque, void* addr )
113 if (addr != NULL) free ( addr );
116 #ifndef BZ_NO_COMPRESS
118 /*---------------------------------------------------*/
119 static
120 void prepare_new_block ( EState* s )
122 Int32 i;
123 s->nblock = 0;
124 s->numZ = 0;
125 s->state_out_pos = 0;
126 BZ_INITIALISE_CRC ( s->blockCRC );
127 for (i = 0; i < 256; i++) s->inUse[i] = False;
128 s->blockNo++;
132 /*---------------------------------------------------*/
133 static
134 void init_RL ( EState* s )
136 s->state_in_ch = 256;
137 s->state_in_len = 0;
141 static
142 Bool isempty_RL ( EState* s )
144 if (s->state_in_ch < 256 && s->state_in_len > 0)
145 return False; else
146 return True;
150 /*---------------------------------------------------*/
151 int BZ_API(BZ2_bzCompressInit)
152 ( bz_stream* strm,
153 int blockSize100k,
154 int verbosity,
155 int workFactor )
157 Int32 n;
158 EState* s;
160 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
162 if (strm == NULL ||
163 blockSize100k < 1 || blockSize100k > 9 ||
164 workFactor < 0 || workFactor > 250)
165 return BZ_PARAM_ERROR;
167 if (workFactor == 0) workFactor = 30;
168 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
169 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
171 s = BZALLOC( sizeof(EState) );
172 if (s == NULL) return BZ_MEM_ERROR;
173 s->strm = strm;
175 s->arr1 = NULL;
176 s->arr2 = NULL;
177 s->ftab = NULL;
179 n = 100000 * blockSize100k;
180 s->arr1 = BZALLOC( n * sizeof(UInt32) );
181 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
182 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
184 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
185 if (s->arr1 != NULL) BZFREE(s->arr1);
186 if (s->arr2 != NULL) BZFREE(s->arr2);
187 if (s->ftab != NULL) BZFREE(s->ftab);
188 if (s != NULL) BZFREE(s);
189 return BZ_MEM_ERROR;
192 s->blockNo = 0;
193 s->state = BZ_S_INPUT;
194 s->mode = BZ_M_RUNNING;
195 s->combinedCRC = 0;
196 s->blockSize100k = blockSize100k;
197 s->nblockMAX = 100000 * blockSize100k - 19;
198 s->verbosity = verbosity;
199 s->workFactor = workFactor;
201 s->block = (UChar*)s->arr2;
202 s->mtfv = (UInt16*)s->arr1;
203 s->zbits = NULL;
204 s->ptr = (UInt32*)s->arr1;
206 strm->state = s;
207 strm->total_in_lo32 = 0;
208 strm->total_in_hi32 = 0;
209 strm->total_out_lo32 = 0;
210 strm->total_out_hi32 = 0;
211 init_RL ( s );
212 prepare_new_block ( s );
213 return BZ_OK;
217 /*---------------------------------------------------*/
218 static
219 void add_pair_to_block ( EState* s )
221 Int32 i;
222 UChar ch = (UChar)(s->state_in_ch);
223 for (i = 0; i < s->state_in_len; i++) {
224 BZ_UPDATE_CRC( s->blockCRC, ch );
226 s->inUse[s->state_in_ch] = True;
227 switch (s->state_in_len) {
228 case 1:
229 s->block[s->nblock] = (UChar)ch; s->nblock++;
230 break;
231 case 2:
232 s->block[s->nblock] = (UChar)ch; s->nblock++;
233 s->block[s->nblock] = (UChar)ch; s->nblock++;
234 break;
235 case 3:
236 s->block[s->nblock] = (UChar)ch; s->nblock++;
237 s->block[s->nblock] = (UChar)ch; s->nblock++;
238 s->block[s->nblock] = (UChar)ch; s->nblock++;
239 break;
240 default:
241 s->inUse[s->state_in_len-4] = True;
242 s->block[s->nblock] = (UChar)ch; s->nblock++;
243 s->block[s->nblock] = (UChar)ch; s->nblock++;
244 s->block[s->nblock] = (UChar)ch; s->nblock++;
245 s->block[s->nblock] = (UChar)ch; s->nblock++;
246 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
247 s->nblock++;
248 break;
253 /*---------------------------------------------------*/
254 static
255 void flush_RL ( EState* s )
257 if (s->state_in_ch < 256) add_pair_to_block ( s );
258 init_RL ( s );
262 /*---------------------------------------------------*/
263 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
265 UInt32 zchh = (UInt32)(zchh0); \
266 /*-- fast track the common case --*/ \
267 if (zchh != zs->state_in_ch && \
268 zs->state_in_len == 1) { \
269 UChar ch = (UChar)(zs->state_in_ch); \
270 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
271 zs->inUse[zs->state_in_ch] = True; \
272 zs->block[zs->nblock] = (UChar)ch; \
273 zs->nblock++; \
274 zs->state_in_ch = zchh; \
276 else \
277 /*-- general, uncommon cases --*/ \
278 if (zchh != zs->state_in_ch || \
279 zs->state_in_len == 255) { \
280 if (zs->state_in_ch < 256) \
281 add_pair_to_block ( zs ); \
282 zs->state_in_ch = zchh; \
283 zs->state_in_len = 1; \
284 } else { \
285 zs->state_in_len++; \
290 /*---------------------------------------------------*/
291 static
292 Bool copy_input_until_stop ( EState* s )
294 Bool progress_in = False;
296 if (s->mode == BZ_M_RUNNING) {
298 /*-- fast track the common case --*/
299 while (True) {
300 /*-- block full? --*/
301 if (s->nblock >= s->nblockMAX) break;
302 /*-- no input? --*/
303 if (s->strm->avail_in == 0) break;
304 progress_in = True;
305 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
306 s->strm->next_in++;
307 s->strm->avail_in--;
308 s->strm->total_in_lo32++;
309 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
312 } else {
314 /*-- general, uncommon case --*/
315 while (True) {
316 /*-- block full? --*/
317 if (s->nblock >= s->nblockMAX) break;
318 /*-- no input? --*/
319 if (s->strm->avail_in == 0) break;
320 /*-- flush/finish end? --*/
321 if (s->avail_in_expect == 0) break;
322 progress_in = True;
323 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
324 s->strm->next_in++;
325 s->strm->avail_in--;
326 s->strm->total_in_lo32++;
327 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
328 s->avail_in_expect--;
331 return progress_in;
335 /*---------------------------------------------------*/
336 static
337 Bool copy_output_until_stop ( EState* s )
339 Bool progress_out = False;
341 while (True) {
343 /*-- no output space? --*/
344 if (s->strm->avail_out == 0) break;
346 /*-- block done? --*/
347 if (s->state_out_pos >= s->numZ) break;
349 progress_out = True;
350 *(s->strm->next_out) = s->zbits[s->state_out_pos];
351 s->state_out_pos++;
352 s->strm->avail_out--;
353 s->strm->next_out++;
354 s->strm->total_out_lo32++;
355 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
358 return progress_out;
362 /*---------------------------------------------------*/
363 static
364 Bool handle_compress ( bz_stream* strm )
366 Bool progress_in = False;
367 Bool progress_out = False;
368 EState* s = strm->state;
370 while (True) {
372 if (s->state == BZ_S_OUTPUT) {
373 progress_out |= copy_output_until_stop ( s );
374 if (s->state_out_pos < s->numZ) break;
375 if (s->mode == BZ_M_FINISHING &&
376 s->avail_in_expect == 0 &&
377 isempty_RL(s)) break;
378 prepare_new_block ( s );
379 s->state = BZ_S_INPUT;
380 if (s->mode == BZ_M_FLUSHING &&
381 s->avail_in_expect == 0 &&
382 isempty_RL(s)) break;
385 if (s->state == BZ_S_INPUT) {
386 progress_in |= copy_input_until_stop ( s );
387 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
388 flush_RL ( s );
389 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
390 s->state = BZ_S_OUTPUT;
392 else
393 if (s->nblock >= s->nblockMAX) {
394 BZ2_compressBlock ( s, False );
395 s->state = BZ_S_OUTPUT;
397 else
398 if (s->strm->avail_in == 0) {
399 break;
405 return progress_in || progress_out;
409 /*---------------------------------------------------*/
410 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
412 Bool progress;
413 EState* s;
414 if (strm == NULL) return BZ_PARAM_ERROR;
415 s = strm->state;
416 if (s == NULL) return BZ_PARAM_ERROR;
417 if (s->strm != strm) return BZ_PARAM_ERROR;
419 preswitch:
420 switch (s->mode) {
422 case BZ_M_IDLE:
423 return BZ_SEQUENCE_ERROR;
425 case BZ_M_RUNNING:
426 if (action == BZ_RUN) {
427 progress = handle_compress ( strm );
428 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
430 else
431 if (action == BZ_FLUSH) {
432 s->avail_in_expect = strm->avail_in;
433 s->mode = BZ_M_FLUSHING;
434 goto preswitch;
436 else
437 if (action == BZ_FINISH) {
438 s->avail_in_expect = strm->avail_in;
439 s->mode = BZ_M_FINISHING;
440 goto preswitch;
442 else
443 return BZ_PARAM_ERROR;
445 case BZ_M_FLUSHING:
446 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
447 if (s->avail_in_expect != s->strm->avail_in)
448 return BZ_SEQUENCE_ERROR;
449 progress = handle_compress ( strm );
450 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
451 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
452 s->mode = BZ_M_RUNNING;
453 return BZ_RUN_OK;
455 case BZ_M_FINISHING:
456 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
457 if (s->avail_in_expect != s->strm->avail_in)
458 return BZ_SEQUENCE_ERROR;
459 progress = handle_compress ( strm );
460 if (!progress) return BZ_SEQUENCE_ERROR;
461 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
462 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
463 s->mode = BZ_M_IDLE;
464 return BZ_STREAM_END;
466 return BZ_OK; /*--not reached--*/
470 /*---------------------------------------------------*/
471 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
473 EState* s;
474 if (strm == NULL) return BZ_PARAM_ERROR;
475 s = strm->state;
476 if (s == NULL) return BZ_PARAM_ERROR;
477 if (s->strm != strm) return BZ_PARAM_ERROR;
479 if (s->arr1 != NULL) BZFREE(s->arr1);
480 if (s->arr2 != NULL) BZFREE(s->arr2);
481 if (s->ftab != NULL) BZFREE(s->ftab);
482 BZFREE(strm->state);
484 strm->state = NULL;
486 return BZ_OK;
489 #endif /* BZ_NO_COMPRESS */
491 /*---------------------------------------------------*/
492 /*--- Decompression stuff ---*/
493 /*---------------------------------------------------*/
495 /*---------------------------------------------------*/
496 int BZ_API(BZ2_bzDecompressInit)
497 ( bz_stream* strm,
498 int verbosity,
499 int small )
501 DState* s;
503 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
505 if (strm == NULL) return BZ_PARAM_ERROR;
506 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
507 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
509 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
510 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
512 s = BZALLOC( sizeof(DState) );
513 if (s == NULL) return BZ_MEM_ERROR;
514 s->strm = strm;
515 strm->state = s;
516 s->state = BZ_X_MAGIC_1;
517 s->bsLive = 0;
518 s->bsBuff = 0;
519 s->calculatedCombinedCRC = 0;
520 strm->total_in_lo32 = 0;
521 strm->total_in_hi32 = 0;
522 strm->total_out_lo32 = 0;
523 strm->total_out_hi32 = 0;
524 s->smallDecompress = (Bool)small;
525 s->ll4 = NULL;
526 s->ll16 = NULL;
527 s->tt = NULL;
528 s->currBlockNo = 0;
529 s->verbosity = verbosity;
531 return BZ_OK;
535 /*---------------------------------------------------*/
536 /* Return True iff data corruption is discovered.
537 Returns False if there is no problem.
539 static
540 Bool unRLE_obuf_to_output_FAST ( DState* s )
542 UChar k1;
544 if (s->blockRandomised) {
546 while (True) {
547 /* try to finish existing run */
548 while (True) {
549 if (s->strm->avail_out == 0) return False;
550 if (s->state_out_len == 0) break;
551 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
552 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
553 s->state_out_len--;
554 s->strm->next_out++;
555 s->strm->avail_out--;
556 s->strm->total_out_lo32++;
557 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
560 /* can a new run be started? */
561 if (s->nblock_used == s->save_nblock+1) return False;
563 /* Only caused by corrupt data stream? */
564 if (s->nblock_used > s->save_nblock+1)
565 return True;
567 s->state_out_len = 1;
568 s->state_out_ch = s->k0;
569 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
570 k1 ^= BZ_RAND_MASK; s->nblock_used++;
571 if (s->nblock_used == s->save_nblock+1) continue;
572 if (k1 != s->k0) { s->k0 = k1; continue; };
574 s->state_out_len = 2;
575 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
576 k1 ^= BZ_RAND_MASK; s->nblock_used++;
577 if (s->nblock_used == s->save_nblock+1) continue;
578 if (k1 != s->k0) { s->k0 = k1; continue; };
580 s->state_out_len = 3;
581 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
582 k1 ^= BZ_RAND_MASK; s->nblock_used++;
583 if (s->nblock_used == s->save_nblock+1) continue;
584 if (k1 != s->k0) { s->k0 = k1; continue; };
586 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
587 k1 ^= BZ_RAND_MASK; s->nblock_used++;
588 s->state_out_len = ((Int32)k1) + 4;
589 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
590 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
593 } else {
595 /* restore */
596 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
597 UChar c_state_out_ch = s->state_out_ch;
598 Int32 c_state_out_len = s->state_out_len;
599 Int32 c_nblock_used = s->nblock_used;
600 Int32 c_k0 = s->k0;
601 UInt32* c_tt = s->tt;
602 UInt32 c_tPos = s->tPos;
603 char* cs_next_out = s->strm->next_out;
604 unsigned int cs_avail_out = s->strm->avail_out;
605 Int32 ro_blockSize100k = s->blockSize100k;
606 /* end restore */
608 UInt32 avail_out_INIT = cs_avail_out;
609 Int32 s_save_nblockPP = s->save_nblock+1;
610 unsigned int total_out_lo32_old;
612 while (True) {
614 /* try to finish existing run */
615 if (c_state_out_len > 0) {
616 while (True) {
617 if (cs_avail_out == 0) goto return_notr;
618 if (c_state_out_len == 1) break;
619 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
620 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
621 c_state_out_len--;
622 cs_next_out++;
623 cs_avail_out--;
625 s_state_out_len_eq_one:
627 if (cs_avail_out == 0) {
628 c_state_out_len = 1; goto return_notr;
630 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
631 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
632 cs_next_out++;
633 cs_avail_out--;
636 /* Only caused by corrupt data stream? */
637 if (c_nblock_used > s_save_nblockPP)
638 return True;
640 /* can a new run be started? */
641 if (c_nblock_used == s_save_nblockPP) {
642 c_state_out_len = 0; goto return_notr;
644 c_state_out_ch = c_k0;
645 BZ_GET_FAST_C(k1); c_nblock_used++;
646 if (k1 != c_k0) {
647 c_k0 = k1; goto s_state_out_len_eq_one;
649 if (c_nblock_used == s_save_nblockPP)
650 goto s_state_out_len_eq_one;
652 c_state_out_len = 2;
653 BZ_GET_FAST_C(k1); c_nblock_used++;
654 if (c_nblock_used == s_save_nblockPP) continue;
655 if (k1 != c_k0) { c_k0 = k1; continue; };
657 c_state_out_len = 3;
658 BZ_GET_FAST_C(k1); c_nblock_used++;
659 if (c_nblock_used == s_save_nblockPP) continue;
660 if (k1 != c_k0) { c_k0 = k1; continue; };
662 BZ_GET_FAST_C(k1); c_nblock_used++;
663 c_state_out_len = ((Int32)k1) + 4;
664 BZ_GET_FAST_C(c_k0); c_nblock_used++;
667 return_notr:
668 total_out_lo32_old = s->strm->total_out_lo32;
669 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
670 if (s->strm->total_out_lo32 < total_out_lo32_old)
671 s->strm->total_out_hi32++;
673 /* save */
674 s->calculatedBlockCRC = c_calculatedBlockCRC;
675 s->state_out_ch = c_state_out_ch;
676 s->state_out_len = c_state_out_len;
677 s->nblock_used = c_nblock_used;
678 s->k0 = c_k0;
679 s->tt = c_tt;
680 s->tPos = c_tPos;
681 s->strm->next_out = cs_next_out;
682 s->strm->avail_out = cs_avail_out;
683 /* end save */
685 return False;
690 /*---------------------------------------------------*/
691 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
693 Int32 nb, na, mid;
694 nb = 0;
695 na = 256;
696 do {
697 mid = (nb + na) >> 1;
698 if (indx >= cftab[mid]) nb = mid; else na = mid;
700 while (na - nb != 1);
701 return nb;
705 /*---------------------------------------------------*/
706 /* Return True iff data corruption is discovered.
707 Returns False if there is no problem.
709 static
710 Bool unRLE_obuf_to_output_SMALL ( DState* s )
712 UChar k1;
714 if (s->blockRandomised) {
716 while (True) {
717 /* try to finish existing run */
718 while (True) {
719 if (s->strm->avail_out == 0) return False;
720 if (s->state_out_len == 0) break;
721 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
722 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
723 s->state_out_len--;
724 s->strm->next_out++;
725 s->strm->avail_out--;
726 s->strm->total_out_lo32++;
727 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
730 /* can a new run be started? */
731 if (s->nblock_used == s->save_nblock+1) return False;
733 /* Only caused by corrupt data stream? */
734 if (s->nblock_used > s->save_nblock+1)
735 return True;
737 s->state_out_len = 1;
738 s->state_out_ch = s->k0;
739 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
740 k1 ^= BZ_RAND_MASK; s->nblock_used++;
741 if (s->nblock_used == s->save_nblock+1) continue;
742 if (k1 != s->k0) { s->k0 = k1; continue; };
744 s->state_out_len = 2;
745 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
746 k1 ^= BZ_RAND_MASK; s->nblock_used++;
747 if (s->nblock_used == s->save_nblock+1) continue;
748 if (k1 != s->k0) { s->k0 = k1; continue; };
750 s->state_out_len = 3;
751 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
752 k1 ^= BZ_RAND_MASK; s->nblock_used++;
753 if (s->nblock_used == s->save_nblock+1) continue;
754 if (k1 != s->k0) { s->k0 = k1; continue; };
756 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
757 k1 ^= BZ_RAND_MASK; s->nblock_used++;
758 s->state_out_len = ((Int32)k1) + 4;
759 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
760 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
763 } else {
765 while (True) {
766 /* try to finish existing run */
767 while (True) {
768 if (s->strm->avail_out == 0) return False;
769 if (s->state_out_len == 0) break;
770 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
771 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
772 s->state_out_len--;
773 s->strm->next_out++;
774 s->strm->avail_out--;
775 s->strm->total_out_lo32++;
776 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
779 /* can a new run be started? */
780 if (s->nblock_used == s->save_nblock+1) return False;
782 /* Only caused by corrupt data stream? */
783 if (s->nblock_used > s->save_nblock+1)
784 return True;
786 s->state_out_len = 1;
787 s->state_out_ch = s->k0;
788 BZ_GET_SMALL(k1); s->nblock_used++;
789 if (s->nblock_used == s->save_nblock+1) continue;
790 if (k1 != s->k0) { s->k0 = k1; continue; };
792 s->state_out_len = 2;
793 BZ_GET_SMALL(k1); s->nblock_used++;
794 if (s->nblock_used == s->save_nblock+1) continue;
795 if (k1 != s->k0) { s->k0 = k1; continue; };
797 s->state_out_len = 3;
798 BZ_GET_SMALL(k1); s->nblock_used++;
799 if (s->nblock_used == s->save_nblock+1) continue;
800 if (k1 != s->k0) { s->k0 = k1; continue; };
802 BZ_GET_SMALL(k1); s->nblock_used++;
803 s->state_out_len = ((Int32)k1) + 4;
804 BZ_GET_SMALL(s->k0); s->nblock_used++;
811 /*---------------------------------------------------*/
812 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
814 Bool corrupt;
815 DState* s;
816 if (strm == NULL) return BZ_PARAM_ERROR;
817 s = strm->state;
818 if (s == NULL) return BZ_PARAM_ERROR;
819 if (s->strm != strm) return BZ_PARAM_ERROR;
821 while (True) {
822 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
823 if (s->state == BZ_X_OUTPUT) {
824 if (s->smallDecompress)
825 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
826 corrupt = unRLE_obuf_to_output_FAST ( s );
827 if (corrupt) return BZ_DATA_ERROR;
828 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
829 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
830 if (s->verbosity >= 3)
831 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
832 s->calculatedBlockCRC );
833 if (s->verbosity >= 2) VPrintf0 ( "]" );
834 if (s->calculatedBlockCRC != s->storedBlockCRC)
835 return BZ_DATA_ERROR;
836 s->calculatedCombinedCRC
837 = (s->calculatedCombinedCRC << 1) |
838 (s->calculatedCombinedCRC >> 31);
839 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
840 s->state = BZ_X_BLKHDR_1;
841 } else {
842 return BZ_OK;
845 if (s->state >= BZ_X_MAGIC_1) {
846 Int32 r = BZ2_decompress ( s );
847 if (r == BZ_STREAM_END) {
848 if (s->verbosity >= 3)
849 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
850 s->storedCombinedCRC, s->calculatedCombinedCRC );
851 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
852 return BZ_DATA_ERROR;
853 return r;
855 if (s->state != BZ_X_OUTPUT) return r;
859 AssertH ( 0, 6001 );
861 return 0; /*NOTREACHED*/
865 /*---------------------------------------------------*/
866 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
868 DState* s;
869 if (strm == NULL) return BZ_PARAM_ERROR;
870 s = strm->state;
871 if (s == NULL) return BZ_PARAM_ERROR;
872 if (s->strm != strm) return BZ_PARAM_ERROR;
874 if (s->tt != NULL) BZFREE(s->tt);
875 if (s->ll16 != NULL) BZFREE(s->ll16);
876 if (s->ll4 != NULL) BZFREE(s->ll4);
878 BZFREE(strm->state);
879 strm->state = NULL;
881 return BZ_OK;
884 #ifndef BZ_NO_COMPRESS
886 #ifndef BZ_NO_STDIO
887 /*---------------------------------------------------*/
888 /*--- File I/O stuff ---*/
889 /*---------------------------------------------------*/
891 #define BZ_SETERR(eee) \
893 if (bzerror != NULL) *bzerror = eee; \
894 if (bzf != NULL) bzf->lastErr = eee; \
897 typedef
898 struct {
899 FILE* handle;
900 Char buf[BZ_MAX_UNUSED];
901 Int32 bufN;
902 Bool writing;
903 bz_stream strm;
904 Int32 lastErr;
905 Bool initialisedOk;
907 bzFile;
910 /*---------------------------------------------*/
911 static Bool myfeof ( FILE* f )
913 Int32 c = fgetc ( f );
914 if (c == EOF) return True;
915 ungetc ( c, f );
916 return False;
920 /*---------------------------------------------------*/
921 BZFILE* BZ_API(BZ2_bzWriteOpen)
922 ( int* bzerror,
923 FILE* f,
924 int blockSize100k,
925 int verbosity,
926 int workFactor )
928 Int32 ret;
929 bzFile* bzf = NULL;
931 BZ_SETERR(BZ_OK);
933 if (f == NULL ||
934 (blockSize100k < 1 || blockSize100k > 9) ||
935 (workFactor < 0 || workFactor > 250) ||
936 (verbosity < 0 || verbosity > 4))
937 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
939 if (ferror(f))
940 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
942 bzf = malloc ( sizeof(bzFile) );
943 if (bzf == NULL)
944 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
946 BZ_SETERR(BZ_OK);
947 bzf->initialisedOk = False;
948 bzf->bufN = 0;
949 bzf->handle = f;
950 bzf->writing = True;
951 bzf->strm.bzalloc = NULL;
952 bzf->strm.bzfree = NULL;
953 bzf->strm.opaque = NULL;
955 if (workFactor == 0) workFactor = 30;
956 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
957 verbosity, workFactor );
958 if (ret != BZ_OK)
959 { BZ_SETERR(ret); free(bzf); return NULL; };
961 bzf->strm.avail_in = 0;
962 bzf->initialisedOk = True;
963 return bzf;
968 /*---------------------------------------------------*/
969 void BZ_API(BZ2_bzWrite)
970 ( int* bzerror,
971 BZFILE* b,
972 void* buf,
973 int len )
975 Int32 n, n2, ret;
976 bzFile* bzf = (bzFile*)b;
978 BZ_SETERR(BZ_OK);
979 if (bzf == NULL || buf == NULL || len < 0)
980 { BZ_SETERR(BZ_PARAM_ERROR); return; };
981 if (!(bzf->writing))
982 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
983 if (ferror(bzf->handle))
984 { BZ_SETERR(BZ_IO_ERROR); return; };
986 if (len == 0)
987 { BZ_SETERR(BZ_OK); return; };
989 bzf->strm.avail_in = len;
990 bzf->strm.next_in = buf;
992 while (True) {
993 bzf->strm.avail_out = BZ_MAX_UNUSED;
994 bzf->strm.next_out = bzf->buf;
995 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
996 if (ret != BZ_RUN_OK)
997 { BZ_SETERR(ret); return; };
999 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1000 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1001 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1002 n, bzf->handle );
1003 if (n != n2 || ferror(bzf->handle))
1004 { BZ_SETERR(BZ_IO_ERROR); return; };
1007 if (bzf->strm.avail_in == 0)
1008 { BZ_SETERR(BZ_OK); return; };
1013 /*---------------------------------------------------*/
1014 void BZ_API(BZ2_bzWriteClose)
1015 ( int* bzerror,
1016 BZFILE* b,
1017 int abandon,
1018 unsigned int* nbytes_in,
1019 unsigned int* nbytes_out )
1021 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1022 nbytes_in, NULL, nbytes_out, NULL );
1026 void BZ_API(BZ2_bzWriteClose64)
1027 ( int* bzerror,
1028 BZFILE* b,
1029 int abandon,
1030 unsigned int* nbytes_in_lo32,
1031 unsigned int* nbytes_in_hi32,
1032 unsigned int* nbytes_out_lo32,
1033 unsigned int* nbytes_out_hi32 )
1035 Int32 n, n2, ret;
1036 bzFile* bzf = (bzFile*)b;
1038 if (bzf == NULL)
1039 { BZ_SETERR(BZ_OK); return; };
1040 if (!(bzf->writing))
1041 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1042 if (ferror(bzf->handle))
1043 { BZ_SETERR(BZ_IO_ERROR); return; };
1045 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1046 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1047 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1048 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1050 if ((!abandon) && bzf->lastErr == BZ_OK) {
1051 while (True) {
1052 bzf->strm.avail_out = BZ_MAX_UNUSED;
1053 bzf->strm.next_out = bzf->buf;
1054 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1055 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1056 { BZ_SETERR(ret); return; };
1058 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1059 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1060 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1061 n, bzf->handle );
1062 if (n != n2 || ferror(bzf->handle))
1063 { BZ_SETERR(BZ_IO_ERROR); return; };
1066 if (ret == BZ_STREAM_END) break;
1070 if ( !abandon && !ferror ( bzf->handle ) ) {
1071 fflush ( bzf->handle );
1072 if (ferror(bzf->handle))
1073 { BZ_SETERR(BZ_IO_ERROR); return; };
1076 if (nbytes_in_lo32 != NULL)
1077 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1078 if (nbytes_in_hi32 != NULL)
1079 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1080 if (nbytes_out_lo32 != NULL)
1081 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1082 if (nbytes_out_hi32 != NULL)
1083 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1085 BZ_SETERR(BZ_OK);
1086 BZ2_bzCompressEnd ( &(bzf->strm) );
1087 free ( bzf );
1091 /*---------------------------------------------------*/
1092 BZFILE* BZ_API(BZ2_bzReadOpen)
1093 ( int* bzerror,
1094 FILE* f,
1095 int verbosity,
1096 int small,
1097 void* unused,
1098 int nUnused )
1100 bzFile* bzf = NULL;
1101 int ret;
1103 BZ_SETERR(BZ_OK);
1105 if (f == NULL ||
1106 (small != 0 && small != 1) ||
1107 (verbosity < 0 || verbosity > 4) ||
1108 (unused == NULL && nUnused != 0) ||
1109 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1110 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1112 if (ferror(f))
1113 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1115 bzf = malloc ( sizeof(bzFile) );
1116 if (bzf == NULL)
1117 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1119 BZ_SETERR(BZ_OK);
1121 bzf->initialisedOk = False;
1122 bzf->handle = f;
1123 bzf->bufN = 0;
1124 bzf->writing = False;
1125 bzf->strm.bzalloc = NULL;
1126 bzf->strm.bzfree = NULL;
1127 bzf->strm.opaque = NULL;
1129 while (nUnused > 0) {
1130 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1131 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1132 nUnused--;
1135 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1136 if (ret != BZ_OK)
1137 { BZ_SETERR(ret); free(bzf); return NULL; };
1139 bzf->strm.avail_in = bzf->bufN;
1140 bzf->strm.next_in = bzf->buf;
1142 bzf->initialisedOk = True;
1143 return bzf;
1147 /*---------------------------------------------------*/
1148 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1150 bzFile* bzf = (bzFile*)b;
1152 BZ_SETERR(BZ_OK);
1153 if (bzf == NULL)
1154 { BZ_SETERR(BZ_OK); return; };
1156 if (bzf->writing)
1157 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1159 if (bzf->initialisedOk)
1160 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1161 free ( bzf );
1165 /*---------------------------------------------------*/
1166 int BZ_API(BZ2_bzRead)
1167 ( int* bzerror,
1168 BZFILE* b,
1169 void* buf,
1170 int len )
1172 Int32 n, ret;
1173 bzFile* bzf = (bzFile*)b;
1175 BZ_SETERR(BZ_OK);
1177 if (bzf == NULL || buf == NULL || len < 0)
1178 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1180 if (bzf->writing)
1181 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1183 if (len == 0)
1184 { BZ_SETERR(BZ_OK); return 0; };
1186 bzf->strm.avail_out = len;
1187 bzf->strm.next_out = buf;
1189 while (True) {
1191 if (ferror(bzf->handle))
1192 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1194 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1195 n = fread ( bzf->buf, sizeof(UChar),
1196 BZ_MAX_UNUSED, bzf->handle );
1197 if (ferror(bzf->handle))
1198 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1199 bzf->bufN = n;
1200 bzf->strm.avail_in = bzf->bufN;
1201 bzf->strm.next_in = bzf->buf;
1204 ret = BZ2_bzDecompress ( &(bzf->strm) );
1206 if (ret != BZ_OK && ret != BZ_STREAM_END)
1207 { BZ_SETERR(ret); return 0; };
1209 if (ret == BZ_OK && myfeof(bzf->handle) &&
1210 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1211 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1213 if (ret == BZ_STREAM_END)
1214 { BZ_SETERR(BZ_STREAM_END);
1215 return len - bzf->strm.avail_out; };
1216 if (bzf->strm.avail_out == 0)
1217 { BZ_SETERR(BZ_OK); return len; };
1221 return 0; /*not reached*/
1225 /*---------------------------------------------------*/
1226 void BZ_API(BZ2_bzReadGetUnused)
1227 ( int* bzerror,
1228 BZFILE* b,
1229 void** unused,
1230 int* nUnused )
1232 bzFile* bzf = (bzFile*)b;
1233 if (bzf == NULL)
1234 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1235 if (bzf->lastErr != BZ_STREAM_END)
1236 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1237 if (unused == NULL || nUnused == NULL)
1238 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1240 BZ_SETERR(BZ_OK);
1241 *nUnused = bzf->strm.avail_in;
1242 *unused = bzf->strm.next_in;
1244 #endif
1247 /*---------------------------------------------------*/
1248 /*--- Misc convenience stuff ---*/
1249 /*---------------------------------------------------*/
1251 /*---------------------------------------------------*/
1252 int BZ_API(BZ2_bzBuffToBuffCompress)
1253 ( char* dest,
1254 unsigned int* destLen,
1255 char* source,
1256 unsigned int sourceLen,
1257 int blockSize100k,
1258 int verbosity,
1259 int workFactor )
1261 bz_stream strm;
1262 int ret;
1264 if (dest == NULL || destLen == NULL ||
1265 source == NULL ||
1266 blockSize100k < 1 || blockSize100k > 9 ||
1267 verbosity < 0 || verbosity > 4 ||
1268 workFactor < 0 || workFactor > 250)
1269 return BZ_PARAM_ERROR;
1271 if (workFactor == 0) workFactor = 30;
1272 strm.bzalloc = NULL;
1273 strm.bzfree = NULL;
1274 strm.opaque = NULL;
1275 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1276 verbosity, workFactor );
1277 if (ret != BZ_OK) return ret;
1279 strm.next_in = source;
1280 strm.next_out = dest;
1281 strm.avail_in = sourceLen;
1282 strm.avail_out = *destLen;
1284 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1285 if (ret == BZ_FINISH_OK) goto output_overflow;
1286 if (ret != BZ_STREAM_END) goto errhandler;
1288 /* normal termination */
1289 *destLen -= strm.avail_out;
1290 BZ2_bzCompressEnd ( &strm );
1291 return BZ_OK;
1293 output_overflow:
1294 BZ2_bzCompressEnd ( &strm );
1295 return BZ_OUTBUFF_FULL;
1297 errhandler:
1298 BZ2_bzCompressEnd ( &strm );
1299 return ret;
1303 /*---------------------------------------------------*/
1304 int BZ_API(BZ2_bzBuffToBuffDecompress)
1305 ( char* dest,
1306 unsigned int* destLen,
1307 char* source,
1308 unsigned int sourceLen,
1309 int small,
1310 int verbosity )
1312 bz_stream strm;
1313 int ret;
1315 if (dest == NULL || destLen == NULL ||
1316 source == NULL ||
1317 (small != 0 && small != 1) ||
1318 verbosity < 0 || verbosity > 4)
1319 return BZ_PARAM_ERROR;
1321 strm.bzalloc = NULL;
1322 strm.bzfree = NULL;
1323 strm.opaque = NULL;
1324 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1325 if (ret != BZ_OK) return ret;
1327 strm.next_in = source;
1328 strm.next_out = dest;
1329 strm.avail_in = sourceLen;
1330 strm.avail_out = *destLen;
1332 ret = BZ2_bzDecompress ( &strm );
1333 if (ret == BZ_OK) goto output_overflow_or_eof;
1334 if (ret != BZ_STREAM_END) goto errhandler;
1336 /* normal termination */
1337 *destLen -= strm.avail_out;
1338 BZ2_bzDecompressEnd ( &strm );
1339 return BZ_OK;
1341 output_overflow_or_eof:
1342 if (strm.avail_out > 0) {
1343 BZ2_bzDecompressEnd ( &strm );
1344 return BZ_UNEXPECTED_EOF;
1345 } else {
1346 BZ2_bzDecompressEnd ( &strm );
1347 return BZ_OUTBUFF_FULL;
1350 errhandler:
1351 BZ2_bzDecompressEnd ( &strm );
1352 return ret;
1356 /*---------------------------------------------------*/
1357 /*--
1358 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1359 to support better zlib compatibility.
1360 This code is not _officially_ part of libbzip2 (yet);
1361 I haven't tested it, documented it, or considered the
1362 threading-safeness of it.
1363 If this code breaks, please contact both Yoshioka and me.
1364 --*/
1365 /*---------------------------------------------------*/
1367 /*---------------------------------------------------*/
1368 /*--
1369 return version like "0.9.5d, 4-Sept-1999".
1370 --*/
1371 const char * BZ_API(BZ2_bzlibVersion)(void)
1373 return BZ_VERSION;
1377 #ifndef BZ_NO_STDIO
1378 /*---------------------------------------------------*/
1380 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1381 # include <fcntl.h>
1382 # include <io.h>
1383 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1384 #else
1385 # define SET_BINARY_MODE(file)
1386 #endif
1387 static
1388 BZFILE * bzopen_or_bzdopen
1389 ( const char *path, /* no use when bzdopen */
1390 int fd, /* no use when bzdopen */
1391 const char *mode,
1392 int open_mode) /* bzopen: 0, bzdopen:1 */
1394 int bzerr;
1395 char unused[BZ_MAX_UNUSED];
1396 int blockSize100k = 9;
1397 int writing = 0;
1398 char mode2[10] = "";
1399 FILE *fp = NULL;
1400 BZFILE *bzfp = NULL;
1401 int verbosity = 0;
1402 int workFactor = 30;
1403 int smallMode = 0;
1404 int nUnused = 0;
1406 if (mode == NULL) return NULL;
1407 while (*mode) {
1408 switch (*mode) {
1409 case 'r':
1410 writing = 0; break;
1411 case 'w':
1412 writing = 1; break;
1413 case 's':
1414 smallMode = 1; break;
1415 default:
1416 if (isdigit((int)(*mode))) {
1417 blockSize100k = *mode-BZ_HDR_0;
1420 mode++;
1422 strcat(mode2, writing ? "w" : "r" );
1423 strcat(mode2,"b"); /* binary mode */
1425 if (open_mode==0) {
1426 if (path==NULL || strcmp(path,"")==0) {
1427 fp = (writing ? stdout : stdin);
1428 SET_BINARY_MODE(fp);
1429 } else {
1430 fp = fopen(path,mode2);
1432 } else {
1433 #ifdef BZ_STRICT_ANSI
1434 fp = NULL;
1435 #else
1436 fp = fdopen(fd,mode2);
1437 #endif
1439 if (fp == NULL) return NULL;
1441 if (writing) {
1442 /* Guard against total chaos and anarchy -- JRS */
1443 if (blockSize100k < 1) blockSize100k = 1;
1444 if (blockSize100k > 9) blockSize100k = 9;
1445 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1446 verbosity,workFactor);
1447 } else {
1448 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1449 unused,nUnused);
1451 if (bzfp == NULL) {
1452 if (fp != stdin && fp != stdout) fclose(fp);
1453 return NULL;
1455 return bzfp;
1459 /*---------------------------------------------------*/
1460 /*--
1461 open file for read or write.
1462 ex) bzopen("file","w9")
1463 case path="" or NULL => use stdin or stdout.
1464 --*/
1465 BZFILE * BZ_API(BZ2_bzopen)
1466 ( const char *path,
1467 const char *mode )
1469 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1473 /*---------------------------------------------------*/
1474 BZFILE * BZ_API(BZ2_bzdopen)
1475 ( int fd,
1476 const char *mode )
1478 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1482 /*---------------------------------------------------*/
1483 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1485 int bzerr, nread;
1486 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1487 nread = BZ2_bzRead(&bzerr,b,buf,len);
1488 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1489 return nread;
1490 } else {
1491 return -1;
1496 /*---------------------------------------------------*/
1497 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1499 int bzerr;
1501 BZ2_bzWrite(&bzerr,b,buf,len);
1502 if(bzerr == BZ_OK){
1503 return len;
1504 }else{
1505 return -1;
1510 /*---------------------------------------------------*/
1511 int BZ_API(BZ2_bzflush) (BZFILE *b)
1513 /* do nothing now... */
1514 return 0;
1518 /*---------------------------------------------------*/
1519 void BZ_API(BZ2_bzclose) (BZFILE* b)
1521 int bzerr;
1522 FILE *fp;
1524 if (b==NULL) {return;}
1525 fp = ((bzFile *)b)->handle;
1526 if(((bzFile*)b)->writing){
1527 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1528 if(bzerr != BZ_OK){
1529 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1531 }else{
1532 BZ2_bzReadClose(&bzerr,b);
1534 if(fp!=stdin && fp!=stdout){
1535 fclose(fp);
1540 /*---------------------------------------------------*/
1541 /*--
1542 return last error code
1543 --*/
1544 static const char *bzerrorstrings[] = {
1545 "OK"
1546 ,"SEQUENCE_ERROR"
1547 ,"PARAM_ERROR"
1548 ,"MEM_ERROR"
1549 ,"DATA_ERROR"
1550 ,"DATA_ERROR_MAGIC"
1551 ,"IO_ERROR"
1552 ,"UNEXPECTED_EOF"
1553 ,"OUTBUFF_FULL"
1554 ,"CONFIG_ERROR"
1555 ,"???" /* for future */
1556 ,"???" /* for future */
1557 ,"???" /* for future */
1558 ,"???" /* for future */
1559 ,"???" /* for future */
1560 ,"???" /* for future */
1564 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1566 int err = ((bzFile *)b)->lastErr;
1568 if(err>0) err = 0;
1569 *errnum = err;
1570 return bzerrorstrings[err*-1];
1572 #endif
1574 #endif /* BZ_NO_COMPRESS */
1576 /*-------------------------------------------------------------*/
1577 /*--- end bzlib.c ---*/
1578 /*-------------------------------------------------------------*/