remove unused <tools.h>
[minix.git] / dist / bzip2 / bzlib.c
blob8b5ca35f53589380b0772d649f062806e3d0d497
1 /* $NetBSD: bzlib.c,v 1.4 2008/03/18 14:47:07 christos Exp $ */
4 /*-------------------------------------------------------------*/
5 /*--- Library top-level functions. ---*/
6 /*--- bzlib.c ---*/
7 /*-------------------------------------------------------------*/
9 /* ------------------------------------------------------------------
10 This file is part of bzip2/libbzip2, a program and library for
11 lossless, block-sorting data compression.
13 bzip2/libbzip2 version 1.0.5 of 10 December 2007
14 Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
16 Please read the WARNING, DISCLAIMER and PATENTS sections in the
17 README file.
19 This program is released under the terms of the license contained
20 in the file LICENSE.
21 ------------------------------------------------------------------ */
23 /* CHANGES
24 0.9.0 -- original version.
25 0.9.0a/b -- no changes in this file.
26 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress().
27 fixed bzWrite/bzRead to ignore zero-length requests.
28 fixed bzread to correctly handle read requests after EOF.
29 wrong parameter order in call to bzDecompressInit in
30 bzBuffToBuffDecompress. Fixed.
33 #include "bzlib_private.h"
36 /*---------------------------------------------------*/
37 /*--- Compression stuff ---*/
38 /*---------------------------------------------------*/
41 /*---------------------------------------------------*/
42 #ifndef BZ_NO_STDIO
43 void BZ2_bz__AssertH__fail ( int errcode )
45 fprintf(stderr,
46 "\n\nbzip2/libbzip2: internal error number %d.\n"
47 "This is a bug in bzip2/libbzip2, %s.\n"
48 "Please report it to me at: jseward@bzip.org. If this happened\n"
49 "when you were using some program which uses libbzip2 as a\n"
50 "component, you should also report this bug to the author(s)\n"
51 "of that program. Please make an effort to report this bug;\n"
52 "timely and accurate bug reports eventually lead to higher\n"
53 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
54 errcode,
55 BZ2_bzlibVersion()
58 if (errcode == 1007) {
59 fprintf(stderr,
60 "\n*** A special note about internal error number 1007 ***\n"
61 "\n"
62 "Experience suggests that a common cause of i.e. 1007\n"
63 "is unreliable memory or other hardware. The 1007 assertion\n"
64 "just happens to cross-check the results of huge numbers of\n"
65 "memory reads/writes, and so acts (unintendedly) as a stress\n"
66 "test of your memory system.\n"
67 "\n"
68 "I suggest the following: try compressing the file again,\n"
69 "possibly monitoring progress in detail with the -vv flag.\n"
70 "\n"
71 "* If the error cannot be reproduced, and/or happens at different\n"
72 " points in compression, you may have a flaky memory system.\n"
73 " Try a memory-test program. I have used Memtest86\n"
74 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
75 " Memtest86 tests memory much more thorougly than your BIOSs\n"
76 " power-on test, and may find failures that the BIOS doesn't.\n"
77 "\n"
78 "* If the error can be repeatably reproduced, this is a bug in\n"
79 " bzip2, and I would very much like to hear about it. Please\n"
80 " let me know, and, ideally, save a copy of the file causing the\n"
81 " problem -- without which I will be unable to investigate it.\n"
82 "\n"
86 exit(3);
88 #endif
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 );
117 /*---------------------------------------------------*/
118 static
119 void prepare_new_block ( EState* s )
121 Int32 i;
122 s->nblock = 0;
123 s->numZ = 0;
124 s->state_out_pos = 0;
125 BZ_INITIALISE_CRC ( s->blockCRC );
126 for (i = 0; i < 256; i++) s->inUse[i] = False;
127 s->blockNo++;
131 /*---------------------------------------------------*/
132 static
133 void init_RL ( EState* s )
135 s->state_in_ch = 256;
136 s->state_in_len = 0;
140 static
141 Bool isempty_RL ( EState* s )
143 if (s->state_in_ch < 256 && s->state_in_len > 0)
144 return False; else
145 return True;
149 /*---------------------------------------------------*/
150 int BZ_API(BZ2_bzCompressInit)
151 ( bz_stream* strm,
152 int blockSize100k,
153 int verbosity,
154 int workFactor )
156 Int32 n;
157 EState* s;
159 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
161 if (strm == NULL ||
162 blockSize100k < 1 || blockSize100k > 9 ||
163 workFactor < 0 || workFactor > 250)
164 return BZ_PARAM_ERROR;
166 if (workFactor == 0) workFactor = 30;
167 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
168 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
170 s = BZALLOC( sizeof(EState) );
171 if (s == NULL) return BZ_MEM_ERROR;
172 s->strm = strm;
174 s->arr1 = NULL;
175 s->arr2 = NULL;
176 s->ftab = NULL;
178 n = 100000 * blockSize100k;
179 s->arr1 = BZALLOC( n * sizeof(UInt32) );
180 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
181 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
183 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
184 if (s->arr1 != NULL) BZFREE(s->arr1);
185 if (s->arr2 != NULL) BZFREE(s->arr2);
186 if (s->ftab != NULL) BZFREE(s->ftab);
187 if (s != NULL) BZFREE(s);
188 return BZ_MEM_ERROR;
191 s->blockNo = 0;
192 s->state = BZ_S_INPUT;
193 s->mode = BZ_M_RUNNING;
194 s->combinedCRC = 0;
195 s->blockSize100k = blockSize100k;
196 s->nblockMAX = 100000 * blockSize100k - 19;
197 s->verbosity = verbosity;
198 s->workFactor = workFactor;
200 s->block = (UChar*)s->arr2;
201 s->mtfv = (UInt16*)s->arr1;
202 s->zbits = NULL;
203 s->ptr = (UInt32*)s->arr1;
205 strm->state = s;
206 strm->total_in_lo32 = 0;
207 strm->total_in_hi32 = 0;
208 strm->total_out_lo32 = 0;
209 strm->total_out_hi32 = 0;
210 init_RL ( s );
211 prepare_new_block ( s );
212 return BZ_OK;
216 /*---------------------------------------------------*/
217 static
218 void add_pair_to_block ( EState* s )
220 Int32 i;
221 UChar ch = (UChar)(s->state_in_ch);
222 for (i = 0; i < s->state_in_len; i++) {
223 BZ_UPDATE_CRC( s->blockCRC, ch );
225 s->inUse[s->state_in_ch] = True;
226 switch (s->state_in_len) {
227 case 1:
228 s->block[s->nblock] = (UChar)ch; s->nblock++;
229 break;
230 case 2:
231 s->block[s->nblock] = (UChar)ch; s->nblock++;
232 s->block[s->nblock] = (UChar)ch; s->nblock++;
233 break;
234 case 3:
235 s->block[s->nblock] = (UChar)ch; s->nblock++;
236 s->block[s->nblock] = (UChar)ch; s->nblock++;
237 s->block[s->nblock] = (UChar)ch; s->nblock++;
238 break;
239 default:
240 s->inUse[s->state_in_len-4] = True;
241 s->block[s->nblock] = (UChar)ch; s->nblock++;
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)(s->state_in_len-4));
246 s->nblock++;
247 break;
252 /*---------------------------------------------------*/
253 static
254 void flush_RL ( EState* s )
256 if (s->state_in_ch < 256) add_pair_to_block ( s );
257 init_RL ( s );
261 /*---------------------------------------------------*/
262 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
264 UInt32 zchh = (UInt32)(zchh0); \
265 /*-- fast track the common case --*/ \
266 if (zchh != zs->state_in_ch && \
267 zs->state_in_len == 1) { \
268 UChar ch = (UChar)(zs->state_in_ch); \
269 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
270 zs->inUse[zs->state_in_ch] = True; \
271 zs->block[zs->nblock] = (UChar)ch; \
272 zs->nblock++; \
273 zs->state_in_ch = zchh; \
275 else \
276 /*-- general, uncommon cases --*/ \
277 if (zchh != zs->state_in_ch || \
278 zs->state_in_len == 255) { \
279 if (zs->state_in_ch < 256) \
280 add_pair_to_block ( zs ); \
281 zs->state_in_ch = zchh; \
282 zs->state_in_len = 1; \
283 } else { \
284 zs->state_in_len++; \
289 /*---------------------------------------------------*/
290 static
291 Bool copy_input_until_stop ( EState* s )
293 Bool progress_in = False;
295 if (s->mode == BZ_M_RUNNING) {
297 /*-- fast track the common case --*/
298 while (True) {
299 /*-- block full? --*/
300 if (s->nblock >= s->nblockMAX) break;
301 /*-- no input? --*/
302 if (s->strm->avail_in == 0) break;
303 progress_in = True;
304 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
305 s->strm->next_in++;
306 s->strm->avail_in--;
307 s->strm->total_in_lo32++;
308 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
311 } else {
313 /*-- general, uncommon case --*/
314 while (True) {
315 /*-- block full? --*/
316 if (s->nblock >= s->nblockMAX) break;
317 /*-- no input? --*/
318 if (s->strm->avail_in == 0) break;
319 /*-- flush/finish end? --*/
320 if (s->avail_in_expect == 0) break;
321 progress_in = True;
322 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
323 s->strm->next_in++;
324 s->strm->avail_in--;
325 s->strm->total_in_lo32++;
326 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
327 s->avail_in_expect--;
330 return progress_in;
334 /*---------------------------------------------------*/
335 static
336 Bool copy_output_until_stop ( EState* s )
338 Bool progress_out = False;
340 while (True) {
342 /*-- no output space? --*/
343 if (s->strm->avail_out == 0) break;
345 /*-- block done? --*/
346 if (s->state_out_pos >= s->numZ) break;
348 progress_out = True;
349 *(s->strm->next_out) = s->zbits[s->state_out_pos];
350 s->state_out_pos++;
351 s->strm->avail_out--;
352 s->strm->next_out++;
353 s->strm->total_out_lo32++;
354 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
357 return progress_out;
361 /*---------------------------------------------------*/
362 static
363 Bool handle_compress ( bz_stream* strm )
365 Bool progress_in = False;
366 Bool progress_out = False;
367 EState* s = strm->state;
369 while (True) {
371 if (s->state == BZ_S_OUTPUT) {
372 progress_out |= copy_output_until_stop ( s );
373 if (s->state_out_pos < s->numZ) break;
374 if (s->mode == BZ_M_FINISHING &&
375 s->avail_in_expect == 0 &&
376 isempty_RL(s)) break;
377 prepare_new_block ( s );
378 s->state = BZ_S_INPUT;
379 if (s->mode == BZ_M_FLUSHING &&
380 s->avail_in_expect == 0 &&
381 isempty_RL(s)) break;
384 if (s->state == BZ_S_INPUT) {
385 progress_in |= copy_input_until_stop ( s );
386 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
387 flush_RL ( s );
388 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
389 s->state = BZ_S_OUTPUT;
391 else
392 if (s->nblock >= s->nblockMAX) {
393 BZ2_compressBlock ( s, False );
394 s->state = BZ_S_OUTPUT;
396 else
397 if (s->strm->avail_in == 0) {
398 break;
404 return progress_in || progress_out;
408 /*---------------------------------------------------*/
409 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
411 Bool progress;
412 EState* s;
413 if (strm == NULL) return BZ_PARAM_ERROR;
414 s = strm->state;
415 if (s == NULL) return BZ_PARAM_ERROR;
416 if (s->strm != strm) return BZ_PARAM_ERROR;
418 preswitch:
419 switch (s->mode) {
421 case BZ_M_IDLE:
422 return BZ_SEQUENCE_ERROR;
424 case BZ_M_RUNNING:
425 if (action == BZ_RUN) {
426 progress = handle_compress ( strm );
427 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
429 else
430 if (action == BZ_FLUSH) {
431 s->avail_in_expect = strm->avail_in;
432 s->mode = BZ_M_FLUSHING;
433 goto preswitch;
435 else
436 if (action == BZ_FINISH) {
437 s->avail_in_expect = strm->avail_in;
438 s->mode = BZ_M_FINISHING;
439 goto preswitch;
441 else
442 return BZ_PARAM_ERROR;
444 case BZ_M_FLUSHING:
445 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
446 if (s->avail_in_expect != s->strm->avail_in)
447 return BZ_SEQUENCE_ERROR;
448 progress = handle_compress ( strm );
449 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
450 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
451 s->mode = BZ_M_RUNNING;
452 return BZ_RUN_OK;
454 case BZ_M_FINISHING:
455 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
456 if (s->avail_in_expect != s->strm->avail_in)
457 return BZ_SEQUENCE_ERROR;
458 progress = handle_compress ( strm );
459 if (!progress) return BZ_SEQUENCE_ERROR;
460 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
461 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
462 s->mode = BZ_M_IDLE;
463 return BZ_STREAM_END;
465 return BZ_OK; /*--not reached--*/
469 /*---------------------------------------------------*/
470 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
472 EState* s;
473 if (strm == NULL) return BZ_PARAM_ERROR;
474 s = strm->state;
475 if (s == NULL) return BZ_PARAM_ERROR;
476 if (s->strm != strm) return BZ_PARAM_ERROR;
478 if (s->arr1 != NULL) BZFREE(s->arr1);
479 if (s->arr2 != NULL) BZFREE(s->arr2);
480 if (s->ftab != NULL) BZFREE(s->ftab);
481 BZFREE(strm->state);
483 strm->state = NULL;
485 return BZ_OK;
489 /*---------------------------------------------------*/
490 /*--- Decompression stuff ---*/
491 /*---------------------------------------------------*/
493 /*---------------------------------------------------*/
494 int BZ_API(BZ2_bzDecompressInit)
495 ( bz_stream* strm,
496 int verbosity,
497 int small )
499 DState* s;
501 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
503 if (strm == NULL) return BZ_PARAM_ERROR;
504 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
505 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
507 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
508 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
510 s = BZALLOC( sizeof(DState) );
511 if (s == NULL) return BZ_MEM_ERROR;
512 s->strm = strm;
513 strm->state = s;
514 s->state = BZ_X_MAGIC_1;
515 s->bsLive = 0;
516 s->bsBuff = 0;
517 s->calculatedCombinedCRC = 0;
518 strm->total_in_lo32 = 0;
519 strm->total_in_hi32 = 0;
520 strm->total_out_lo32 = 0;
521 strm->total_out_hi32 = 0;
522 s->smallDecompress = (Bool)small;
523 s->ll4 = NULL;
524 s->ll16 = NULL;
525 s->tt = NULL;
526 s->currBlockNo = 0;
527 s->verbosity = verbosity;
529 return BZ_OK;
533 /*---------------------------------------------------*/
534 /* Return True iff data corruption is discovered.
535 Returns False if there is no problem.
537 static
538 Bool unRLE_obuf_to_output_FAST ( DState* s )
540 UChar k1;
542 if (s->blockRandomised) {
544 while (True) {
545 /* try to finish existing run */
546 while (True) {
547 if (s->strm->avail_out == 0) return False;
548 if (s->state_out_len == 0) break;
549 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
550 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
551 s->state_out_len--;
552 s->strm->next_out++;
553 s->strm->avail_out--;
554 s->strm->total_out_lo32++;
555 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
558 /* can a new run be started? */
559 if (s->nblock_used == s->save_nblock+1) return False;
561 /* Only caused by corrupt data stream? */
562 if (s->nblock_used > s->save_nblock+1)
563 return True;
565 s->state_out_len = 1;
566 s->state_out_ch = s->k0;
567 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
568 k1 ^= BZ_RAND_MASK; s->nblock_used++;
569 if (s->nblock_used == s->save_nblock+1) continue;
570 if (k1 != s->k0) { s->k0 = k1; continue; };
572 s->state_out_len = 2;
573 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
574 k1 ^= BZ_RAND_MASK; s->nblock_used++;
575 if (s->nblock_used == s->save_nblock+1) continue;
576 if (k1 != s->k0) { s->k0 = k1; continue; };
578 s->state_out_len = 3;
579 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
580 k1 ^= BZ_RAND_MASK; s->nblock_used++;
581 if (s->nblock_used == s->save_nblock+1) continue;
582 if (k1 != s->k0) { s->k0 = k1; continue; };
584 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
585 k1 ^= BZ_RAND_MASK; s->nblock_used++;
586 s->state_out_len = ((Int32)k1) + 4;
587 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
588 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
591 } else {
593 /* restore */
594 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
595 UChar c_state_out_ch = s->state_out_ch;
596 Int32 c_state_out_len = s->state_out_len;
597 Int32 c_nblock_used = s->nblock_used;
598 Int32 c_k0 = s->k0;
599 UInt32* c_tt = s->tt;
600 UInt32 c_tPos = s->tPos;
601 char* cs_next_out = s->strm->next_out;
602 unsigned int cs_avail_out = s->strm->avail_out;
603 Int32 ro_blockSize100k = s->blockSize100k;
604 /* end restore */
606 UInt32 avail_out_INIT = cs_avail_out;
607 Int32 s_save_nblockPP = s->save_nblock+1;
608 unsigned int total_out_lo32_old;
610 while (True) {
612 /* try to finish existing run */
613 if (c_state_out_len > 0) {
614 while (True) {
615 if (cs_avail_out == 0) goto return_notr;
616 if (c_state_out_len == 1) break;
617 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
618 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
619 c_state_out_len--;
620 cs_next_out++;
621 cs_avail_out--;
623 s_state_out_len_eq_one:
625 if (cs_avail_out == 0) {
626 c_state_out_len = 1; goto return_notr;
628 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
629 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
630 cs_next_out++;
631 cs_avail_out--;
634 /* Only caused by corrupt data stream? */
635 if (c_nblock_used > s_save_nblockPP)
636 return True;
638 /* can a new run be started? */
639 if (c_nblock_used == s_save_nblockPP) {
640 c_state_out_len = 0; goto return_notr;
642 c_state_out_ch = c_k0;
643 BZ_GET_FAST_C(k1); c_nblock_used++;
644 if (k1 != c_k0) {
645 c_k0 = k1; goto s_state_out_len_eq_one;
647 if (c_nblock_used == s_save_nblockPP)
648 goto s_state_out_len_eq_one;
650 c_state_out_len = 2;
651 BZ_GET_FAST_C(k1); c_nblock_used++;
652 if (c_nblock_used == s_save_nblockPP) continue;
653 if (k1 != c_k0) { c_k0 = k1; continue; };
655 c_state_out_len = 3;
656 BZ_GET_FAST_C(k1); c_nblock_used++;
657 if (c_nblock_used == s_save_nblockPP) continue;
658 if (k1 != c_k0) { c_k0 = k1; continue; };
660 BZ_GET_FAST_C(k1); c_nblock_used++;
661 c_state_out_len = ((Int32)k1) + 4;
662 BZ_GET_FAST_C(c_k0); c_nblock_used++;
665 return_notr:
666 total_out_lo32_old = s->strm->total_out_lo32;
667 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
668 if (s->strm->total_out_lo32 < total_out_lo32_old)
669 s->strm->total_out_hi32++;
671 /* save */
672 s->calculatedBlockCRC = c_calculatedBlockCRC;
673 s->state_out_ch = c_state_out_ch;
674 s->state_out_len = c_state_out_len;
675 s->nblock_used = c_nblock_used;
676 s->k0 = c_k0;
677 s->tt = c_tt;
678 s->tPos = c_tPos;
679 s->strm->next_out = cs_next_out;
680 s->strm->avail_out = cs_avail_out;
681 /* end save */
683 return False;
688 /*---------------------------------------------------*/
689 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
691 Int32 nb, na, mid;
692 nb = 0;
693 na = 256;
694 do {
695 mid = (nb + na) >> 1;
696 if (indx >= cftab[mid]) nb = mid; else na = mid;
698 while (na - nb != 1);
699 return nb;
703 /*---------------------------------------------------*/
704 /* Return True iff data corruption is discovered.
705 Returns False if there is no problem.
707 static
708 Bool unRLE_obuf_to_output_SMALL ( DState* s )
710 UChar k1;
712 if (s->blockRandomised) {
714 while (True) {
715 /* try to finish existing run */
716 while (True) {
717 if (s->strm->avail_out == 0) return False;
718 if (s->state_out_len == 0) break;
719 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
720 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
721 s->state_out_len--;
722 s->strm->next_out++;
723 s->strm->avail_out--;
724 s->strm->total_out_lo32++;
725 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
728 /* can a new run be started? */
729 if (s->nblock_used == s->save_nblock+1) return False;
731 /* Only caused by corrupt data stream? */
732 if (s->nblock_used > s->save_nblock+1)
733 return True;
735 s->state_out_len = 1;
736 s->state_out_ch = s->k0;
737 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
738 k1 ^= BZ_RAND_MASK; s->nblock_used++;
739 if (s->nblock_used == s->save_nblock+1) continue;
740 if (k1 != s->k0) { s->k0 = k1; continue; };
742 s->state_out_len = 2;
743 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
744 k1 ^= BZ_RAND_MASK; s->nblock_used++;
745 if (s->nblock_used == s->save_nblock+1) continue;
746 if (k1 != s->k0) { s->k0 = k1; continue; };
748 s->state_out_len = 3;
749 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
750 k1 ^= BZ_RAND_MASK; s->nblock_used++;
751 if (s->nblock_used == s->save_nblock+1) continue;
752 if (k1 != s->k0) { s->k0 = k1; continue; };
754 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
755 k1 ^= BZ_RAND_MASK; s->nblock_used++;
756 s->state_out_len = ((Int32)k1) + 4;
757 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
758 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
761 } else {
763 while (True) {
764 /* try to finish existing run */
765 while (True) {
766 if (s->strm->avail_out == 0) return False;
767 if (s->state_out_len == 0) break;
768 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
769 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
770 s->state_out_len--;
771 s->strm->next_out++;
772 s->strm->avail_out--;
773 s->strm->total_out_lo32++;
774 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
777 /* can a new run be started? */
778 if (s->nblock_used == s->save_nblock+1) return False;
780 /* Only caused by corrupt data stream? */
781 if (s->nblock_used > s->save_nblock+1)
782 return True;
784 s->state_out_len = 1;
785 s->state_out_ch = s->k0;
786 BZ_GET_SMALL(k1); s->nblock_used++;
787 if (s->nblock_used == s->save_nblock+1) continue;
788 if (k1 != s->k0) { s->k0 = k1; continue; };
790 s->state_out_len = 2;
791 BZ_GET_SMALL(k1); s->nblock_used++;
792 if (s->nblock_used == s->save_nblock+1) continue;
793 if (k1 != s->k0) { s->k0 = k1; continue; };
795 s->state_out_len = 3;
796 BZ_GET_SMALL(k1); s->nblock_used++;
797 if (s->nblock_used == s->save_nblock+1) continue;
798 if (k1 != s->k0) { s->k0 = k1; continue; };
800 BZ_GET_SMALL(k1); s->nblock_used++;
801 s->state_out_len = ((Int32)k1) + 4;
802 BZ_GET_SMALL(s->k0); s->nblock_used++;
809 /*---------------------------------------------------*/
810 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
812 Bool corrupt;
813 DState* s;
814 if (strm == NULL) return BZ_PARAM_ERROR;
815 s = strm->state;
816 if (s == NULL) return BZ_PARAM_ERROR;
817 if (s->strm != strm) return BZ_PARAM_ERROR;
819 while (True) {
820 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
821 if (s->state == BZ_X_OUTPUT) {
822 if (s->smallDecompress)
823 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
824 corrupt = unRLE_obuf_to_output_FAST ( s );
825 if (corrupt) return BZ_DATA_ERROR;
826 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
827 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
828 if (s->verbosity >= 3)
829 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
830 s->calculatedBlockCRC );
831 if (s->verbosity >= 2) VPrintf0 ( "]" );
832 if (s->calculatedBlockCRC != s->storedBlockCRC)
833 return BZ_DATA_ERROR;
834 s->calculatedCombinedCRC
835 = (s->calculatedCombinedCRC << 1) |
836 (s->calculatedCombinedCRC >> 31);
837 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
838 s->state = BZ_X_BLKHDR_1;
839 } else {
840 return BZ_OK;
843 if (s->state >= BZ_X_MAGIC_1) {
844 Int32 r = BZ2_decompress ( s );
845 if (r == BZ_STREAM_END) {
846 if (s->verbosity >= 3)
847 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
848 s->storedCombinedCRC, s->calculatedCombinedCRC );
849 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
850 return BZ_DATA_ERROR;
851 return r;
853 if (s->state != BZ_X_OUTPUT) return r;
857 AssertH ( 0, 6001 );
859 return 0; /*NOTREACHED*/
863 /*---------------------------------------------------*/
864 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
866 DState* s;
867 if (strm == NULL) return BZ_PARAM_ERROR;
868 s = strm->state;
869 if (s == NULL) return BZ_PARAM_ERROR;
870 if (s->strm != strm) return BZ_PARAM_ERROR;
872 if (s->tt != NULL) BZFREE(s->tt);
873 if (s->ll16 != NULL) BZFREE(s->ll16);
874 if (s->ll4 != NULL) BZFREE(s->ll4);
876 BZFREE(strm->state);
877 strm->state = NULL;
879 return BZ_OK;
883 #ifndef BZ_NO_STDIO
884 /*---------------------------------------------------*/
885 /*--- File I/O stuff ---*/
886 /*---------------------------------------------------*/
888 #define BZ_SETERR(eee) \
890 if (bzerror != NULL) *bzerror = eee; \
891 if (bzf != NULL) bzf->lastErr = eee; \
894 typedef
895 struct {
896 FILE* handle;
897 Char buf[BZ_MAX_UNUSED];
898 Int32 bufN;
899 Bool writing;
900 bz_stream strm;
901 Int32 lastErr;
902 Bool initialisedOk;
904 bzFile;
907 /*---------------------------------------------*/
908 static Bool myfeof ( FILE* f )
910 Int32 c = fgetc ( f );
911 if (c == EOF) return True;
912 ungetc ( c, f );
913 return False;
917 /*---------------------------------------------------*/
918 BZFILE* BZ_API(BZ2_bzWriteOpen)
919 ( int* bzerror,
920 FILE* f,
921 int blockSize100k,
922 int verbosity,
923 int workFactor )
925 Int32 ret;
926 bzFile* bzf = NULL;
928 BZ_SETERR(BZ_OK);
930 if (f == NULL ||
931 (blockSize100k < 1 || blockSize100k > 9) ||
932 (workFactor < 0 || workFactor > 250) ||
933 (verbosity < 0 || verbosity > 4))
934 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
936 if (ferror(f))
937 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
939 bzf = malloc ( sizeof(bzFile) );
940 if (bzf == NULL)
941 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
943 BZ_SETERR(BZ_OK);
944 bzf->initialisedOk = False;
945 bzf->bufN = 0;
946 bzf->handle = f;
947 bzf->writing = True;
948 bzf->strm.bzalloc = NULL;
949 bzf->strm.bzfree = NULL;
950 bzf->strm.opaque = NULL;
952 if (workFactor == 0) workFactor = 30;
953 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
954 verbosity, workFactor );
955 if (ret != BZ_OK)
956 { BZ_SETERR(ret); free(bzf); return NULL; };
958 bzf->strm.avail_in = 0;
959 bzf->initialisedOk = True;
960 return bzf;
965 /*---------------------------------------------------*/
966 void BZ_API(BZ2_bzWrite)
967 ( int* bzerror,
968 BZFILE* b,
969 void* buf,
970 int len )
972 Int32 n, n2, ret;
973 bzFile* bzf = (bzFile*)b;
975 BZ_SETERR(BZ_OK);
976 if (bzf == NULL || buf == NULL || len < 0)
977 { BZ_SETERR(BZ_PARAM_ERROR); return; };
978 if (!(bzf->writing))
979 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
980 if (ferror(bzf->handle))
981 { BZ_SETERR(BZ_IO_ERROR); return; };
983 if (len == 0)
984 { BZ_SETERR(BZ_OK); return; };
986 bzf->strm.avail_in = len;
987 bzf->strm.next_in = buf;
989 while (True) {
990 bzf->strm.avail_out = BZ_MAX_UNUSED;
991 bzf->strm.next_out = bzf->buf;
992 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
993 if (ret != BZ_RUN_OK)
994 { BZ_SETERR(ret); return; };
996 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
997 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
998 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
999 n, bzf->handle );
1000 if (n != n2 || ferror(bzf->handle))
1001 { BZ_SETERR(BZ_IO_ERROR); return; };
1004 if (bzf->strm.avail_in == 0)
1005 { BZ_SETERR(BZ_OK); return; };
1010 /*---------------------------------------------------*/
1011 void BZ_API(BZ2_bzWriteClose)
1012 ( int* bzerror,
1013 BZFILE* b,
1014 int abandon,
1015 unsigned int* nbytes_in,
1016 unsigned int* nbytes_out )
1018 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1019 nbytes_in, NULL, nbytes_out, NULL );
1023 void BZ_API(BZ2_bzWriteClose64)
1024 ( int* bzerror,
1025 BZFILE* b,
1026 int abandon,
1027 unsigned int* nbytes_in_lo32,
1028 unsigned int* nbytes_in_hi32,
1029 unsigned int* nbytes_out_lo32,
1030 unsigned int* nbytes_out_hi32 )
1032 Int32 n, n2, ret;
1033 bzFile* bzf = (bzFile*)b;
1035 if (bzf == NULL)
1036 { BZ_SETERR(BZ_OK); return; };
1037 if (!(bzf->writing))
1038 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1039 if (ferror(bzf->handle))
1040 { BZ_SETERR(BZ_IO_ERROR); return; };
1042 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1043 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1044 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1045 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1047 if ((!abandon) && bzf->lastErr == BZ_OK) {
1048 while (True) {
1049 bzf->strm.avail_out = BZ_MAX_UNUSED;
1050 bzf->strm.next_out = bzf->buf;
1051 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1052 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1053 { BZ_SETERR(ret); return; };
1055 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1056 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1057 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1058 n, bzf->handle );
1059 if (n != n2 || ferror(bzf->handle))
1060 { BZ_SETERR(BZ_IO_ERROR); return; };
1063 if (ret == BZ_STREAM_END) break;
1067 if ( !abandon && !ferror ( bzf->handle ) ) {
1068 fflush ( bzf->handle );
1069 if (ferror(bzf->handle))
1070 { BZ_SETERR(BZ_IO_ERROR); return; };
1073 if (nbytes_in_lo32 != NULL)
1074 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1075 if (nbytes_in_hi32 != NULL)
1076 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1077 if (nbytes_out_lo32 != NULL)
1078 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1079 if (nbytes_out_hi32 != NULL)
1080 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1082 BZ_SETERR(BZ_OK);
1083 BZ2_bzCompressEnd ( &(bzf->strm) );
1084 free ( bzf );
1088 /*---------------------------------------------------*/
1089 BZFILE* BZ_API(BZ2_bzReadOpen)
1090 ( int* bzerror,
1091 FILE* f,
1092 int verbosity,
1093 int small,
1094 void* unused,
1095 int nUnused )
1097 bzFile* bzf = NULL;
1098 int ret;
1100 BZ_SETERR(BZ_OK);
1102 if (f == NULL ||
1103 (small != 0 && small != 1) ||
1104 (verbosity < 0 || verbosity > 4) ||
1105 (unused == NULL && nUnused != 0) ||
1106 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1107 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1109 if (ferror(f))
1110 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1112 bzf = malloc ( sizeof(bzFile) );
1113 if (bzf == NULL)
1114 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1116 BZ_SETERR(BZ_OK);
1118 bzf->initialisedOk = False;
1119 bzf->handle = f;
1120 bzf->bufN = 0;
1121 bzf->writing = False;
1122 bzf->strm.bzalloc = NULL;
1123 bzf->strm.bzfree = NULL;
1124 bzf->strm.opaque = NULL;
1126 while (nUnused > 0) {
1127 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1128 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1129 nUnused--;
1132 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1133 if (ret != BZ_OK)
1134 { BZ_SETERR(ret); free(bzf); return NULL; };
1136 bzf->strm.avail_in = bzf->bufN;
1137 bzf->strm.next_in = bzf->buf;
1139 bzf->initialisedOk = True;
1140 return bzf;
1144 /*---------------------------------------------------*/
1145 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1147 bzFile* bzf = (bzFile*)b;
1149 BZ_SETERR(BZ_OK);
1150 if (bzf == NULL)
1151 { BZ_SETERR(BZ_OK); return; };
1153 if (bzf->writing)
1154 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1156 if (bzf->initialisedOk)
1157 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1158 free ( bzf );
1162 /*---------------------------------------------------*/
1163 int BZ_API(BZ2_bzRead)
1164 ( int* bzerror,
1165 BZFILE* b,
1166 void* buf,
1167 int len )
1169 Int32 n, ret;
1170 bzFile* bzf = (bzFile*)b;
1172 BZ_SETERR(BZ_OK);
1174 if (bzf == NULL || buf == NULL || len < 0)
1175 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1177 if (bzf->writing)
1178 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1180 if (len == 0)
1181 { BZ_SETERR(BZ_OK); return 0; };
1183 bzf->strm.avail_out = len;
1184 bzf->strm.next_out = buf;
1186 while (True) {
1188 if (ferror(bzf->handle))
1189 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1191 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1192 n = fread ( bzf->buf, sizeof(UChar),
1193 BZ_MAX_UNUSED, bzf->handle );
1194 if (ferror(bzf->handle))
1195 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1196 bzf->bufN = n;
1197 bzf->strm.avail_in = bzf->bufN;
1198 bzf->strm.next_in = bzf->buf;
1201 ret = BZ2_bzDecompress ( &(bzf->strm) );
1203 if (ret != BZ_OK && ret != BZ_STREAM_END)
1204 { BZ_SETERR(ret); return 0; };
1206 if (ret == BZ_OK && myfeof(bzf->handle) &&
1207 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1208 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1210 if (ret == BZ_STREAM_END)
1211 { BZ_SETERR(BZ_STREAM_END);
1212 return len - bzf->strm.avail_out; };
1213 if (bzf->strm.avail_out == 0)
1214 { BZ_SETERR(BZ_OK); return len; };
1218 return 0; /*not reached*/
1222 /*---------------------------------------------------*/
1223 void BZ_API(BZ2_bzReadGetUnused)
1224 ( int* bzerror,
1225 BZFILE* b,
1226 void** unused,
1227 int* nUnused )
1229 bzFile* bzf = (bzFile*)b;
1230 if (bzf == NULL)
1231 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1232 if (bzf->lastErr != BZ_STREAM_END)
1233 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1234 if (unused == NULL || nUnused == NULL)
1235 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1237 BZ_SETERR(BZ_OK);
1238 *nUnused = bzf->strm.avail_in;
1239 *unused = bzf->strm.next_in;
1241 #endif
1244 /*---------------------------------------------------*/
1245 /*--- Misc convenience stuff ---*/
1246 /*---------------------------------------------------*/
1248 /*---------------------------------------------------*/
1249 int BZ_API(BZ2_bzBuffToBuffCompress)
1250 ( char* dest,
1251 unsigned int* destLen,
1252 char* source,
1253 unsigned int sourceLen,
1254 int blockSize100k,
1255 int verbosity,
1256 int workFactor )
1258 bz_stream strm;
1259 int ret;
1261 if (dest == NULL || destLen == NULL ||
1262 source == NULL ||
1263 blockSize100k < 1 || blockSize100k > 9 ||
1264 verbosity < 0 || verbosity > 4 ||
1265 workFactor < 0 || workFactor > 250)
1266 return BZ_PARAM_ERROR;
1268 if (workFactor == 0) workFactor = 30;
1269 strm.bzalloc = NULL;
1270 strm.bzfree = NULL;
1271 strm.opaque = NULL;
1272 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1273 verbosity, workFactor );
1274 if (ret != BZ_OK) return ret;
1276 strm.next_in = source;
1277 strm.next_out = dest;
1278 strm.avail_in = sourceLen;
1279 strm.avail_out = *destLen;
1281 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1282 if (ret == BZ_FINISH_OK) goto output_overflow;
1283 if (ret != BZ_STREAM_END) goto errhandler;
1285 /* normal termination */
1286 *destLen -= strm.avail_out;
1287 BZ2_bzCompressEnd ( &strm );
1288 return BZ_OK;
1290 output_overflow:
1291 BZ2_bzCompressEnd ( &strm );
1292 return BZ_OUTBUFF_FULL;
1294 errhandler:
1295 BZ2_bzCompressEnd ( &strm );
1296 return ret;
1300 /*---------------------------------------------------*/
1301 int BZ_API(BZ2_bzBuffToBuffDecompress)
1302 ( char* dest,
1303 unsigned int* destLen,
1304 char* source,
1305 unsigned int sourceLen,
1306 int small,
1307 int verbosity )
1309 bz_stream strm;
1310 int ret;
1312 if (dest == NULL || destLen == NULL ||
1313 source == NULL ||
1314 (small != 0 && small != 1) ||
1315 verbosity < 0 || verbosity > 4)
1316 return BZ_PARAM_ERROR;
1318 strm.bzalloc = NULL;
1319 strm.bzfree = NULL;
1320 strm.opaque = NULL;
1321 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1322 if (ret != BZ_OK) return ret;
1324 strm.next_in = source;
1325 strm.next_out = dest;
1326 strm.avail_in = sourceLen;
1327 strm.avail_out = *destLen;
1329 ret = BZ2_bzDecompress ( &strm );
1330 if (ret == BZ_OK) goto output_overflow_or_eof;
1331 if (ret != BZ_STREAM_END) goto errhandler;
1333 /* normal termination */
1334 *destLen -= strm.avail_out;
1335 BZ2_bzDecompressEnd ( &strm );
1336 return BZ_OK;
1338 output_overflow_or_eof:
1339 if (strm.avail_out > 0) {
1340 BZ2_bzDecompressEnd ( &strm );
1341 return BZ_UNEXPECTED_EOF;
1342 } else {
1343 BZ2_bzDecompressEnd ( &strm );
1344 return BZ_OUTBUFF_FULL;
1347 errhandler:
1348 BZ2_bzDecompressEnd ( &strm );
1349 return ret;
1353 /*---------------------------------------------------*/
1354 /*--
1355 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1356 to support better zlib compatibility.
1357 This code is not _officially_ part of libbzip2 (yet);
1358 I haven't tested it, documented it, or considered the
1359 threading-safeness of it.
1360 If this code breaks, please contact both Yoshioka and me.
1361 --*/
1362 /*---------------------------------------------------*/
1364 /*---------------------------------------------------*/
1365 /*--
1366 return version like "0.9.5d, 4-Sept-1999".
1367 --*/
1368 const char * BZ_API(BZ2_bzlibVersion)(void)
1370 return BZ_VERSION;
1374 #ifndef BZ_NO_STDIO
1375 /*---------------------------------------------------*/
1377 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1378 # include <fcntl.h>
1379 # include <io.h>
1380 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1381 #else
1382 # define SET_BINARY_MODE(file)
1383 #endif
1384 static
1385 BZFILE * bzopen_or_bzdopen
1386 ( const char *path, /* no use when bzdopen */
1387 int fd, /* no use when bzdopen */
1388 const char *mode,
1389 int open_mode) /* bzopen: 0, bzdopen:1 */
1391 int bzerr;
1392 char unused[BZ_MAX_UNUSED];
1393 int blockSize100k = 9;
1394 int writing = 0;
1395 char mode2[10] = "";
1396 FILE *fp = NULL;
1397 BZFILE *bzfp = NULL;
1398 int verbosity = 0;
1399 int workFactor = 30;
1400 int smallMode = 0;
1401 int nUnused = 0;
1403 if (mode == NULL) return NULL;
1404 while (*mode) {
1405 switch (*mode) {
1406 case 'r':
1407 writing = 0; break;
1408 case 'w':
1409 writing = 1; break;
1410 case 's':
1411 smallMode = 1; break;
1412 default:
1413 if (isdigit((unsigned char)(*mode))) {
1414 blockSize100k = *mode-BZ_HDR_0;
1417 mode++;
1419 strcat(mode2, writing ? "w" : "r" );
1420 strcat(mode2,"b"); /* binary mode */
1422 if (open_mode==0) {
1423 if (path==NULL || strcmp(path,"")==0) {
1424 fp = (writing ? stdout : stdin);
1425 SET_BINARY_MODE(fp);
1426 } else {
1427 fp = fopen(path,mode2);
1429 } else {
1430 #ifdef BZ_STRICT_ANSI
1431 fp = NULL;
1432 #else
1433 fp = fdopen(fd,mode2);
1434 #endif
1436 if (fp == NULL) return NULL;
1438 if (writing) {
1439 /* Guard against total chaos and anarchy -- JRS */
1440 if (blockSize100k < 1) blockSize100k = 1;
1441 if (blockSize100k > 9) blockSize100k = 9;
1442 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1443 verbosity,workFactor);
1444 } else {
1445 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1446 unused,nUnused);
1448 if (bzfp == NULL) {
1449 if (fp != stdin && fp != stdout) fclose(fp);
1450 return NULL;
1452 return bzfp;
1456 /*---------------------------------------------------*/
1457 /*--
1458 open file for read or write.
1459 ex) bzopen("file","w9")
1460 case path="" or NULL => use stdin or stdout.
1461 --*/
1462 BZFILE * BZ_API(BZ2_bzopen)
1463 ( const char *path,
1464 const char *mode )
1466 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1470 /*---------------------------------------------------*/
1471 BZFILE * BZ_API(BZ2_bzdopen)
1472 ( int fd,
1473 const char *mode )
1475 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1479 /*---------------------------------------------------*/
1480 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1482 int bzerr, nread;
1483 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1484 nread = BZ2_bzRead(&bzerr,b,buf,len);
1485 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1486 return nread;
1487 } else {
1488 return -1;
1493 /*---------------------------------------------------*/
1494 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1496 int bzerr;
1498 BZ2_bzWrite(&bzerr,b,buf,len);
1499 if(bzerr == BZ_OK){
1500 return len;
1501 }else{
1502 return -1;
1507 /*---------------------------------------------------*/
1508 int BZ_API(BZ2_bzflush) (BZFILE *b)
1510 /* do nothing now... */
1511 return 0;
1515 /*---------------------------------------------------*/
1516 void BZ_API(BZ2_bzclose) (BZFILE* b)
1518 int bzerr;
1519 FILE *fp;
1521 if (b==NULL) {return;}
1522 fp = ((bzFile *)b)->handle;
1523 if(((bzFile*)b)->writing){
1524 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1525 if(bzerr != BZ_OK){
1526 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1528 }else{
1529 BZ2_bzReadClose(&bzerr,b);
1531 if(fp!=stdin && fp!=stdout){
1532 fclose(fp);
1537 /*---------------------------------------------------*/
1538 /*--
1539 return last error code
1540 --*/
1541 static const char *bzerrorstrings[] = {
1542 "OK"
1543 ,"SEQUENCE_ERROR"
1544 ,"PARAM_ERROR"
1545 ,"MEM_ERROR"
1546 ,"DATA_ERROR"
1547 ,"DATA_ERROR_MAGIC"
1548 ,"IO_ERROR"
1549 ,"UNEXPECTED_EOF"
1550 ,"OUTBUFF_FULL"
1551 ,"CONFIG_ERROR"
1552 ,"???" /* for future */
1553 ,"???" /* for future */
1554 ,"???" /* for future */
1555 ,"???" /* for future */
1556 ,"???" /* for future */
1557 ,"???" /* for future */
1561 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1563 int err = ((bzFile *)b)->lastErr;
1565 if(err>0) err = 0;
1566 *errnum = err;
1567 return bzerrorstrings[err*-1];
1569 #endif
1572 /*-------------------------------------------------------------*/
1573 /*--- end bzlib.c ---*/
1574 /*-------------------------------------------------------------*/