add a -quick target for -create-patch
[AROS.git] / external / bz2 / bzlib.c
blobbd358a793b84bd4dc17cbea8a10d27249c007de6
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.6 of 6 September 2010
12 Copyright (C) 1996-2010 Julian Seward <jseward@bzip.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"
34 /*---------------------------------------------------*/
35 /*--- Compression stuff ---*/
36 /*---------------------------------------------------*/
39 /*---------------------------------------------------*/
40 #ifndef BZ_NO_STDIO
41 void BZ2_bz__AssertH__fail ( int errcode )
43 fprintf(stderr,
44 "\n\nbzip2/libbzip2: internal error number %d.\n"
45 "This is a bug in bzip2/libbzip2, %s.\n"
46 "Please report it to me at: jseward@bzip.org. If this happened\n"
47 "when you were using some program which uses libbzip2 as a\n"
48 "component, you should also report this bug to the author(s)\n"
49 "of that program. Please make an effort to report this bug;\n"
50 "timely and accurate bug reports eventually lead to higher\n"
51 "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
52 errcode,
53 BZ2_bzlibVersion()
56 if (errcode == 1007) {
57 fprintf(stderr,
58 "\n*** A special note about internal error number 1007 ***\n"
59 "\n"
60 "Experience suggests that a common cause of i.e. 1007\n"
61 "is unreliable memory or other hardware. The 1007 assertion\n"
62 "just happens to cross-check the results of huge numbers of\n"
63 "memory reads/writes, and so acts (unintendedly) as a stress\n"
64 "test of your memory system.\n"
65 "\n"
66 "I suggest the following: try compressing the file again,\n"
67 "possibly monitoring progress in detail with the -vv flag.\n"
68 "\n"
69 "* If the error cannot be reproduced, and/or happens at different\n"
70 " points in compression, you may have a flaky memory system.\n"
71 " Try a memory-test program. I have used Memtest86\n"
72 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
73 " Memtest86 tests memory much more thorougly than your BIOSs\n"
74 " power-on test, and may find failures that the BIOS doesn't.\n"
75 "\n"
76 "* If the error can be repeatably reproduced, this is a bug in\n"
77 " bzip2, and I would very much like to hear about it. Please\n"
78 " let me know, and, ideally, save a copy of the file causing the\n"
79 " problem -- without which I will be unable to investigate it.\n"
80 "\n"
84 exit(3);
86 #endif
89 /*---------------------------------------------------*/
90 static
91 int bz_config_ok ( void )
93 if (sizeof(int) != 4) return 0;
94 if (sizeof(short) != 2) return 0;
95 if (sizeof(char) != 1) return 0;
96 return 1;
100 /*---------------------------------------------------*/
101 static
102 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
104 void* v = malloc ( items * size );
105 return v;
108 static
109 void default_bzfree ( void* opaque, void* addr )
111 if (addr != NULL) free ( addr );
115 /*---------------------------------------------------*/
116 static
117 void prepare_new_block ( EState* s )
119 Int32 i;
120 s->nblock = 0;
121 s->numZ = 0;
122 s->state_out_pos = 0;
123 BZ_INITIALISE_CRC ( s->blockCRC );
124 for (i = 0; i < 256; i++) s->inUse[i] = False;
125 s->blockNo++;
129 /*---------------------------------------------------*/
130 static
131 void init_RL ( EState* s )
133 s->state_in_ch = 256;
134 s->state_in_len = 0;
138 static
139 Bool isempty_RL ( EState* s )
141 if (s->state_in_ch < 256 && s->state_in_len > 0)
142 return False; else
143 return True;
147 /*---------------------------------------------------*/
148 int BZ_API(BZ2_bzCompressInit)
149 ( bz_stream* strm,
150 int blockSize100k,
151 int verbosity,
152 int workFactor )
154 Int32 n;
155 EState* s;
157 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
159 if (strm == NULL ||
160 blockSize100k < 1 || blockSize100k > 9 ||
161 workFactor < 0 || workFactor > 250)
162 return BZ_PARAM_ERROR;
164 if (workFactor == 0) workFactor = 30;
165 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
166 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
168 s = BZALLOC( sizeof(EState) );
169 if (s == NULL) return BZ_MEM_ERROR;
170 s->strm = strm;
172 s->arr1 = NULL;
173 s->arr2 = NULL;
174 s->ftab = NULL;
176 n = 100000 * blockSize100k;
177 s->arr1 = BZALLOC( n * sizeof(UInt32) );
178 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
179 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
181 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
182 if (s->arr1 != NULL) BZFREE(s->arr1);
183 if (s->arr2 != NULL) BZFREE(s->arr2);
184 if (s->ftab != NULL) BZFREE(s->ftab);
185 if (s != NULL) BZFREE(s);
186 return BZ_MEM_ERROR;
189 s->blockNo = 0;
190 s->state = BZ_S_INPUT;
191 s->mode = BZ_M_RUNNING;
192 s->combinedCRC = 0;
193 s->blockSize100k = blockSize100k;
194 s->nblockMAX = 100000 * blockSize100k - 19;
195 s->verbosity = verbosity;
196 s->workFactor = workFactor;
198 s->block = (UChar*)s->arr2;
199 s->mtfv = (UInt16*)s->arr1;
200 s->zbits = NULL;
201 s->ptr = (UInt32*)s->arr1;
203 strm->state = s;
204 strm->total_in_lo32 = 0;
205 strm->total_in_hi32 = 0;
206 strm->total_out_lo32 = 0;
207 strm->total_out_hi32 = 0;
208 init_RL ( s );
209 prepare_new_block ( s );
210 return BZ_OK;
214 /*---------------------------------------------------*/
215 static
216 void add_pair_to_block ( EState* s )
218 Int32 i;
219 UChar ch = (UChar)(s->state_in_ch);
220 for (i = 0; i < s->state_in_len; i++) {
221 BZ_UPDATE_CRC( s->blockCRC, ch );
223 s->inUse[s->state_in_ch] = True;
224 switch (s->state_in_len) {
225 case 1:
226 s->block[s->nblock] = (UChar)ch; s->nblock++;
227 break;
228 case 2:
229 s->block[s->nblock] = (UChar)ch; s->nblock++;
230 s->block[s->nblock] = (UChar)ch; s->nblock++;
231 break;
232 case 3:
233 s->block[s->nblock] = (UChar)ch; s->nblock++;
234 s->block[s->nblock] = (UChar)ch; s->nblock++;
235 s->block[s->nblock] = (UChar)ch; s->nblock++;
236 break;
237 default:
238 s->inUse[s->state_in_len-4] = True;
239 s->block[s->nblock] = (UChar)ch; s->nblock++;
240 s->block[s->nblock] = (UChar)ch; s->nblock++;
241 s->block[s->nblock] = (UChar)ch; s->nblock++;
242 s->block[s->nblock] = (UChar)ch; s->nblock++;
243 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
244 s->nblock++;
245 break;
250 /*---------------------------------------------------*/
251 static
252 void flush_RL ( EState* s )
254 if (s->state_in_ch < 256) add_pair_to_block ( s );
255 init_RL ( s );
259 /*---------------------------------------------------*/
260 #define ADD_CHAR_TO_BLOCK(zs,zchh0) \
262 UInt32 zchh = (UInt32)(zchh0); \
263 /*-- fast track the common case --*/ \
264 if (zchh != zs->state_in_ch && \
265 zs->state_in_len == 1) { \
266 UChar ch = (UChar)(zs->state_in_ch); \
267 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
268 zs->inUse[zs->state_in_ch] = True; \
269 zs->block[zs->nblock] = (UChar)ch; \
270 zs->nblock++; \
271 zs->state_in_ch = zchh; \
273 else \
274 /*-- general, uncommon cases --*/ \
275 if (zchh != zs->state_in_ch || \
276 zs->state_in_len == 255) { \
277 if (zs->state_in_ch < 256) \
278 add_pair_to_block ( zs ); \
279 zs->state_in_ch = zchh; \
280 zs->state_in_len = 1; \
281 } else { \
282 zs->state_in_len++; \
287 /*---------------------------------------------------*/
288 static
289 Bool copy_input_until_stop ( EState* s )
291 Bool progress_in = False;
293 if (s->mode == BZ_M_RUNNING) {
295 /*-- fast track the common case --*/
296 while (True) {
297 /*-- block full? --*/
298 if (s->nblock >= s->nblockMAX) break;
299 /*-- no input? --*/
300 if (s->strm->avail_in == 0) break;
301 progress_in = True;
302 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
303 s->strm->next_in++;
304 s->strm->avail_in--;
305 s->strm->total_in_lo32++;
306 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
309 } else {
311 /*-- general, uncommon case --*/
312 while (True) {
313 /*-- block full? --*/
314 if (s->nblock >= s->nblockMAX) break;
315 /*-- no input? --*/
316 if (s->strm->avail_in == 0) break;
317 /*-- flush/finish end? --*/
318 if (s->avail_in_expect == 0) break;
319 progress_in = True;
320 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
321 s->strm->next_in++;
322 s->strm->avail_in--;
323 s->strm->total_in_lo32++;
324 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
325 s->avail_in_expect--;
328 return progress_in;
332 /*---------------------------------------------------*/
333 static
334 Bool copy_output_until_stop ( EState* s )
336 Bool progress_out = False;
338 while (True) {
340 /*-- no output space? --*/
341 if (s->strm->avail_out == 0) break;
343 /*-- block done? --*/
344 if (s->state_out_pos >= s->numZ) break;
346 progress_out = True;
347 *(s->strm->next_out) = s->zbits[s->state_out_pos];
348 s->state_out_pos++;
349 s->strm->avail_out--;
350 s->strm->next_out++;
351 s->strm->total_out_lo32++;
352 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
355 return progress_out;
359 /*---------------------------------------------------*/
360 static
361 Bool handle_compress ( bz_stream* strm )
363 Bool progress_in = False;
364 Bool progress_out = False;
365 EState* s = strm->state;
367 while (True) {
369 if (s->state == BZ_S_OUTPUT) {
370 progress_out |= copy_output_until_stop ( s );
371 if (s->state_out_pos < s->numZ) break;
372 if (s->mode == BZ_M_FINISHING &&
373 s->avail_in_expect == 0 &&
374 isempty_RL(s)) break;
375 prepare_new_block ( s );
376 s->state = BZ_S_INPUT;
377 if (s->mode == BZ_M_FLUSHING &&
378 s->avail_in_expect == 0 &&
379 isempty_RL(s)) break;
382 if (s->state == BZ_S_INPUT) {
383 progress_in |= copy_input_until_stop ( s );
384 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
385 flush_RL ( s );
386 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
387 s->state = BZ_S_OUTPUT;
389 else
390 if (s->nblock >= s->nblockMAX) {
391 BZ2_compressBlock ( s, False );
392 s->state = BZ_S_OUTPUT;
394 else
395 if (s->strm->avail_in == 0) {
396 break;
402 return progress_in || progress_out;
406 /*---------------------------------------------------*/
407 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
409 Bool progress;
410 EState* s;
411 if (strm == NULL) return BZ_PARAM_ERROR;
412 s = strm->state;
413 if (s == NULL) return BZ_PARAM_ERROR;
414 if (s->strm != strm) return BZ_PARAM_ERROR;
416 preswitch:
417 switch (s->mode) {
419 case BZ_M_IDLE:
420 return BZ_SEQUENCE_ERROR;
422 case BZ_M_RUNNING:
423 if (action == BZ_RUN) {
424 progress = handle_compress ( strm );
425 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
427 else
428 if (action == BZ_FLUSH) {
429 s->avail_in_expect = strm->avail_in;
430 s->mode = BZ_M_FLUSHING;
431 goto preswitch;
433 else
434 if (action == BZ_FINISH) {
435 s->avail_in_expect = strm->avail_in;
436 s->mode = BZ_M_FINISHING;
437 goto preswitch;
439 else
440 return BZ_PARAM_ERROR;
442 case BZ_M_FLUSHING:
443 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
444 if (s->avail_in_expect != s->strm->avail_in)
445 return BZ_SEQUENCE_ERROR;
446 progress = handle_compress ( strm );
447 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
448 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
449 s->mode = BZ_M_RUNNING;
450 return BZ_RUN_OK;
452 case BZ_M_FINISHING:
453 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
454 if (s->avail_in_expect != s->strm->avail_in)
455 return BZ_SEQUENCE_ERROR;
456 progress = handle_compress ( strm );
457 if (!progress) return BZ_SEQUENCE_ERROR;
458 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
459 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
460 s->mode = BZ_M_IDLE;
461 return BZ_STREAM_END;
463 return BZ_OK; /*--not reached--*/
467 /*---------------------------------------------------*/
468 int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
470 EState* s;
471 if (strm == NULL) return BZ_PARAM_ERROR;
472 s = strm->state;
473 if (s == NULL) return BZ_PARAM_ERROR;
474 if (s->strm != strm) return BZ_PARAM_ERROR;
476 if (s->arr1 != NULL) BZFREE(s->arr1);
477 if (s->arr2 != NULL) BZFREE(s->arr2);
478 if (s->ftab != NULL) BZFREE(s->ftab);
479 BZFREE(strm->state);
481 strm->state = NULL;
483 return BZ_OK;
487 /*---------------------------------------------------*/
488 /*--- Decompression stuff ---*/
489 /*---------------------------------------------------*/
491 /*---------------------------------------------------*/
492 int BZ_API(BZ2_bzDecompressInit)
493 ( bz_stream* strm,
494 int verbosity,
495 int small )
497 DState* s;
499 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
501 if (strm == NULL) return BZ_PARAM_ERROR;
502 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
503 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
505 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
506 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
508 s = BZALLOC( sizeof(DState) );
509 if (s == NULL) return BZ_MEM_ERROR;
510 s->strm = strm;
511 strm->state = s;
512 s->state = BZ_X_MAGIC_1;
513 s->bsLive = 0;
514 s->bsBuff = 0;
515 s->calculatedCombinedCRC = 0;
516 strm->total_in_lo32 = 0;
517 strm->total_in_hi32 = 0;
518 strm->total_out_lo32 = 0;
519 strm->total_out_hi32 = 0;
520 s->smallDecompress = (Bool)small;
521 s->ll4 = NULL;
522 s->ll16 = NULL;
523 s->tt = NULL;
524 s->currBlockNo = 0;
525 s->verbosity = verbosity;
527 return BZ_OK;
531 /*---------------------------------------------------*/
532 /* Return True iff data corruption is discovered.
533 Returns False if there is no problem.
535 static
536 Bool unRLE_obuf_to_output_FAST ( DState* s )
538 UChar k1;
540 if (s->blockRandomised) {
542 while (True) {
543 /* try to finish existing run */
544 while (True) {
545 if (s->strm->avail_out == 0) return False;
546 if (s->state_out_len == 0) break;
547 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
548 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
549 s->state_out_len--;
550 s->strm->next_out++;
551 s->strm->avail_out--;
552 s->strm->total_out_lo32++;
553 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
556 /* can a new run be started? */
557 if (s->nblock_used == s->save_nblock+1) return False;
559 /* Only caused by corrupt data stream? */
560 if (s->nblock_used > s->save_nblock+1)
561 return True;
563 s->state_out_len = 1;
564 s->state_out_ch = s->k0;
565 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
566 k1 ^= BZ_RAND_MASK; s->nblock_used++;
567 if (s->nblock_used == s->save_nblock+1) continue;
568 if (k1 != s->k0) { s->k0 = k1; continue; };
570 s->state_out_len = 2;
571 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
572 k1 ^= BZ_RAND_MASK; s->nblock_used++;
573 if (s->nblock_used == s->save_nblock+1) continue;
574 if (k1 != s->k0) { s->k0 = k1; continue; };
576 s->state_out_len = 3;
577 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
578 k1 ^= BZ_RAND_MASK; s->nblock_used++;
579 if (s->nblock_used == s->save_nblock+1) continue;
580 if (k1 != s->k0) { s->k0 = k1; continue; };
582 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
583 k1 ^= BZ_RAND_MASK; s->nblock_used++;
584 s->state_out_len = ((Int32)k1) + 4;
585 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
586 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
589 } else {
591 /* restore */
592 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
593 UChar c_state_out_ch = s->state_out_ch;
594 Int32 c_state_out_len = s->state_out_len;
595 Int32 c_nblock_used = s->nblock_used;
596 Int32 c_k0 = s->k0;
597 UInt32* c_tt = s->tt;
598 UInt32 c_tPos = s->tPos;
599 char* cs_next_out = s->strm->next_out;
600 unsigned int cs_avail_out = s->strm->avail_out;
601 Int32 ro_blockSize100k = s->blockSize100k;
602 /* end restore */
604 UInt32 avail_out_INIT = cs_avail_out;
605 Int32 s_save_nblockPP = s->save_nblock+1;
606 unsigned int total_out_lo32_old;
608 while (True) {
610 /* try to finish existing run */
611 if (c_state_out_len > 0) {
612 while (True) {
613 if (cs_avail_out == 0) goto return_notr;
614 if (c_state_out_len == 1) break;
615 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
616 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
617 c_state_out_len--;
618 cs_next_out++;
619 cs_avail_out--;
621 s_state_out_len_eq_one:
623 if (cs_avail_out == 0) {
624 c_state_out_len = 1; goto return_notr;
626 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
627 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
628 cs_next_out++;
629 cs_avail_out--;
632 /* Only caused by corrupt data stream? */
633 if (c_nblock_used > s_save_nblockPP)
634 return True;
636 /* can a new run be started? */
637 if (c_nblock_used == s_save_nblockPP) {
638 c_state_out_len = 0; goto return_notr;
640 c_state_out_ch = c_k0;
641 BZ_GET_FAST_C(k1); c_nblock_used++;
642 if (k1 != c_k0) {
643 c_k0 = k1; goto s_state_out_len_eq_one;
645 if (c_nblock_used == s_save_nblockPP)
646 goto s_state_out_len_eq_one;
648 c_state_out_len = 2;
649 BZ_GET_FAST_C(k1); c_nblock_used++;
650 if (c_nblock_used == s_save_nblockPP) continue;
651 if (k1 != c_k0) { c_k0 = k1; continue; };
653 c_state_out_len = 3;
654 BZ_GET_FAST_C(k1); c_nblock_used++;
655 if (c_nblock_used == s_save_nblockPP) continue;
656 if (k1 != c_k0) { c_k0 = k1; continue; };
658 BZ_GET_FAST_C(k1); c_nblock_used++;
659 c_state_out_len = ((Int32)k1) + 4;
660 BZ_GET_FAST_C(c_k0); c_nblock_used++;
663 return_notr:
664 total_out_lo32_old = s->strm->total_out_lo32;
665 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
666 if (s->strm->total_out_lo32 < total_out_lo32_old)
667 s->strm->total_out_hi32++;
669 /* save */
670 s->calculatedBlockCRC = c_calculatedBlockCRC;
671 s->state_out_ch = c_state_out_ch;
672 s->state_out_len = c_state_out_len;
673 s->nblock_used = c_nblock_used;
674 s->k0 = c_k0;
675 s->tt = c_tt;
676 s->tPos = c_tPos;
677 s->strm->next_out = cs_next_out;
678 s->strm->avail_out = cs_avail_out;
679 /* end save */
681 return False;
686 /*---------------------------------------------------*/
687 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
689 Int32 nb, na, mid;
690 nb = 0;
691 na = 256;
692 do {
693 mid = (nb + na) >> 1;
694 if (indx >= cftab[mid]) nb = mid; else na = mid;
696 while (na - nb != 1);
697 return nb;
701 /*---------------------------------------------------*/
702 /* Return True iff data corruption is discovered.
703 Returns False if there is no problem.
705 static
706 Bool unRLE_obuf_to_output_SMALL ( DState* s )
708 UChar k1;
710 if (s->blockRandomised) {
712 while (True) {
713 /* try to finish existing run */
714 while (True) {
715 if (s->strm->avail_out == 0) return False;
716 if (s->state_out_len == 0) break;
717 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
718 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
719 s->state_out_len--;
720 s->strm->next_out++;
721 s->strm->avail_out--;
722 s->strm->total_out_lo32++;
723 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
726 /* can a new run be started? */
727 if (s->nblock_used == s->save_nblock+1) return False;
729 /* Only caused by corrupt data stream? */
730 if (s->nblock_used > s->save_nblock+1)
731 return True;
733 s->state_out_len = 1;
734 s->state_out_ch = s->k0;
735 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
736 k1 ^= BZ_RAND_MASK; s->nblock_used++;
737 if (s->nblock_used == s->save_nblock+1) continue;
738 if (k1 != s->k0) { s->k0 = k1; continue; };
740 s->state_out_len = 2;
741 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
742 k1 ^= BZ_RAND_MASK; s->nblock_used++;
743 if (s->nblock_used == s->save_nblock+1) continue;
744 if (k1 != s->k0) { s->k0 = k1; continue; };
746 s->state_out_len = 3;
747 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
748 k1 ^= BZ_RAND_MASK; s->nblock_used++;
749 if (s->nblock_used == s->save_nblock+1) continue;
750 if (k1 != s->k0) { s->k0 = k1; continue; };
752 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
753 k1 ^= BZ_RAND_MASK; s->nblock_used++;
754 s->state_out_len = ((Int32)k1) + 4;
755 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
756 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
759 } else {
761 while (True) {
762 /* try to finish existing run */
763 while (True) {
764 if (s->strm->avail_out == 0) return False;
765 if (s->state_out_len == 0) break;
766 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
767 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
768 s->state_out_len--;
769 s->strm->next_out++;
770 s->strm->avail_out--;
771 s->strm->total_out_lo32++;
772 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
775 /* can a new run be started? */
776 if (s->nblock_used == s->save_nblock+1) return False;
778 /* Only caused by corrupt data stream? */
779 if (s->nblock_used > s->save_nblock+1)
780 return True;
782 s->state_out_len = 1;
783 s->state_out_ch = s->k0;
784 BZ_GET_SMALL(k1); s->nblock_used++;
785 if (s->nblock_used == s->save_nblock+1) continue;
786 if (k1 != s->k0) { s->k0 = k1; continue; };
788 s->state_out_len = 2;
789 BZ_GET_SMALL(k1); s->nblock_used++;
790 if (s->nblock_used == s->save_nblock+1) continue;
791 if (k1 != s->k0) { s->k0 = k1; continue; };
793 s->state_out_len = 3;
794 BZ_GET_SMALL(k1); s->nblock_used++;
795 if (s->nblock_used == s->save_nblock+1) continue;
796 if (k1 != s->k0) { s->k0 = k1; continue; };
798 BZ_GET_SMALL(k1); s->nblock_used++;
799 s->state_out_len = ((Int32)k1) + 4;
800 BZ_GET_SMALL(s->k0); s->nblock_used++;
807 /*---------------------------------------------------*/
808 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
810 Bool corrupt;
811 DState* s;
812 if (strm == NULL) return BZ_PARAM_ERROR;
813 s = strm->state;
814 if (s == NULL) return BZ_PARAM_ERROR;
815 if (s->strm != strm) return BZ_PARAM_ERROR;
817 while (True) {
818 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
819 if (s->state == BZ_X_OUTPUT) {
820 if (s->smallDecompress)
821 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
822 corrupt = unRLE_obuf_to_output_FAST ( s );
823 if (corrupt) return BZ_DATA_ERROR;
824 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
825 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
826 if (s->verbosity >= 3)
827 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
828 s->calculatedBlockCRC );
829 if (s->verbosity >= 2) VPrintf0 ( "]" );
830 if (s->calculatedBlockCRC != s->storedBlockCRC)
831 return BZ_DATA_ERROR;
832 s->calculatedCombinedCRC
833 = (s->calculatedCombinedCRC << 1) |
834 (s->calculatedCombinedCRC >> 31);
835 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
836 s->state = BZ_X_BLKHDR_1;
837 } else {
838 return BZ_OK;
841 if (s->state >= BZ_X_MAGIC_1) {
842 Int32 r = BZ2_decompress ( s );
843 if (r == BZ_STREAM_END) {
844 if (s->verbosity >= 3)
845 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
846 s->storedCombinedCRC, s->calculatedCombinedCRC );
847 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
848 return BZ_DATA_ERROR;
849 return r;
851 if (s->state != BZ_X_OUTPUT) return r;
855 AssertH ( 0, 6001 );
857 return 0; /*NOTREACHED*/
861 /*---------------------------------------------------*/
862 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
864 DState* s;
865 if (strm == NULL) return BZ_PARAM_ERROR;
866 s = strm->state;
867 if (s == NULL) return BZ_PARAM_ERROR;
868 if (s->strm != strm) return BZ_PARAM_ERROR;
870 if (s->tt != NULL) BZFREE(s->tt);
871 if (s->ll16 != NULL) BZFREE(s->ll16);
872 if (s->ll4 != NULL) BZFREE(s->ll4);
874 BZFREE(strm->state);
875 strm->state = NULL;
877 return BZ_OK;
881 #ifndef BZ_NO_STDIO
882 /*---------------------------------------------------*/
883 /*--- File I/O stuff ---*/
884 /*---------------------------------------------------*/
886 #define BZ_SETERR(eee) \
888 if (bzerror != NULL) *bzerror = eee; \
889 if (bzf != NULL) bzf->lastErr = eee; \
892 typedef
893 struct {
894 FILE* handle;
895 Char buf[BZ_MAX_UNUSED];
896 Int32 bufN;
897 Bool writing;
898 bz_stream strm;
899 Int32 lastErr;
900 Bool initialisedOk;
902 bzFile;
905 /*---------------------------------------------*/
906 static Bool myfeof ( FILE* f )
908 Int32 c = fgetc ( f );
909 if (c == EOF) return True;
910 ungetc ( c, f );
911 return False;
915 /*---------------------------------------------------*/
916 BZFILE* BZ_API(BZ2_bzWriteOpen)
917 ( int* bzerror,
918 FILE* f,
919 int blockSize100k,
920 int verbosity,
921 int workFactor )
923 Int32 ret;
924 bzFile* bzf = NULL;
926 BZ_SETERR(BZ_OK);
928 if (f == NULL ||
929 (blockSize100k < 1 || blockSize100k > 9) ||
930 (workFactor < 0 || workFactor > 250) ||
931 (verbosity < 0 || verbosity > 4))
932 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
934 if (ferror(f))
935 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
937 bzf = malloc ( sizeof(bzFile) );
938 if (bzf == NULL)
939 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
941 BZ_SETERR(BZ_OK);
942 bzf->initialisedOk = False;
943 bzf->bufN = 0;
944 bzf->handle = f;
945 bzf->writing = True;
946 bzf->strm.bzalloc = NULL;
947 bzf->strm.bzfree = NULL;
948 bzf->strm.opaque = NULL;
950 if (workFactor == 0) workFactor = 30;
951 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
952 verbosity, workFactor );
953 if (ret != BZ_OK)
954 { BZ_SETERR(ret); free(bzf); return NULL; };
956 bzf->strm.avail_in = 0;
957 bzf->initialisedOk = True;
958 return bzf;
963 /*---------------------------------------------------*/
964 void BZ_API(BZ2_bzWrite)
965 ( int* bzerror,
966 BZFILE* b,
967 void* buf,
968 int len )
970 Int32 n, n2, ret;
971 bzFile* bzf = (bzFile*)b;
973 BZ_SETERR(BZ_OK);
974 if (bzf == NULL || buf == NULL || len < 0)
975 { BZ_SETERR(BZ_PARAM_ERROR); return; };
976 if (!(bzf->writing))
977 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
978 if (ferror(bzf->handle))
979 { BZ_SETERR(BZ_IO_ERROR); return; };
981 if (len == 0)
982 { BZ_SETERR(BZ_OK); return; };
984 bzf->strm.avail_in = len;
985 bzf->strm.next_in = buf;
987 while (True) {
988 bzf->strm.avail_out = BZ_MAX_UNUSED;
989 bzf->strm.next_out = bzf->buf;
990 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
991 if (ret != BZ_RUN_OK)
992 { BZ_SETERR(ret); return; };
994 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
995 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
996 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
997 n, bzf->handle );
998 if (n != n2 || ferror(bzf->handle))
999 { BZ_SETERR(BZ_IO_ERROR); return; };
1002 if (bzf->strm.avail_in == 0)
1003 { BZ_SETERR(BZ_OK); return; };
1008 /*---------------------------------------------------*/
1009 void BZ_API(BZ2_bzWriteClose)
1010 ( int* bzerror,
1011 BZFILE* b,
1012 int abandon,
1013 unsigned int* nbytes_in,
1014 unsigned int* nbytes_out )
1016 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1017 nbytes_in, NULL, nbytes_out, NULL );
1021 void BZ_API(BZ2_bzWriteClose64)
1022 ( int* bzerror,
1023 BZFILE* b,
1024 int abandon,
1025 unsigned int* nbytes_in_lo32,
1026 unsigned int* nbytes_in_hi32,
1027 unsigned int* nbytes_out_lo32,
1028 unsigned int* nbytes_out_hi32 )
1030 Int32 n, n2, ret;
1031 bzFile* bzf = (bzFile*)b;
1033 if (bzf == NULL)
1034 { BZ_SETERR(BZ_OK); return; };
1035 if (!(bzf->writing))
1036 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1037 if (ferror(bzf->handle))
1038 { BZ_SETERR(BZ_IO_ERROR); return; };
1040 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1041 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1042 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1043 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1045 if ((!abandon) && bzf->lastErr == BZ_OK) {
1046 while (True) {
1047 bzf->strm.avail_out = BZ_MAX_UNUSED;
1048 bzf->strm.next_out = bzf->buf;
1049 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1050 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1051 { BZ_SETERR(ret); return; };
1053 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1054 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1055 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1056 n, bzf->handle );
1057 if (n != n2 || ferror(bzf->handle))
1058 { BZ_SETERR(BZ_IO_ERROR); return; };
1061 if (ret == BZ_STREAM_END) break;
1065 if ( !abandon && !ferror ( bzf->handle ) ) {
1066 fflush ( bzf->handle );
1067 if (ferror(bzf->handle))
1068 { BZ_SETERR(BZ_IO_ERROR); return; };
1071 if (nbytes_in_lo32 != NULL)
1072 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1073 if (nbytes_in_hi32 != NULL)
1074 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1075 if (nbytes_out_lo32 != NULL)
1076 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1077 if (nbytes_out_hi32 != NULL)
1078 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1080 BZ_SETERR(BZ_OK);
1081 BZ2_bzCompressEnd ( &(bzf->strm) );
1082 free ( bzf );
1086 /*---------------------------------------------------*/
1087 BZFILE* BZ_API(BZ2_bzReadOpen)
1088 ( int* bzerror,
1089 FILE* f,
1090 int verbosity,
1091 int small,
1092 void* unused,
1093 int nUnused )
1095 bzFile* bzf = NULL;
1096 int ret;
1098 BZ_SETERR(BZ_OK);
1100 if (f == NULL ||
1101 (small != 0 && small != 1) ||
1102 (verbosity < 0 || verbosity > 4) ||
1103 (unused == NULL && nUnused != 0) ||
1104 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1105 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1107 if (ferror(f))
1108 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1110 bzf = malloc ( sizeof(bzFile) );
1111 if (bzf == NULL)
1112 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1114 BZ_SETERR(BZ_OK);
1116 bzf->initialisedOk = False;
1117 bzf->handle = f;
1118 bzf->bufN = 0;
1119 bzf->writing = False;
1120 bzf->strm.bzalloc = NULL;
1121 bzf->strm.bzfree = NULL;
1122 bzf->strm.opaque = NULL;
1124 while (nUnused > 0) {
1125 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1126 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1127 nUnused--;
1130 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1131 if (ret != BZ_OK)
1132 { BZ_SETERR(ret); free(bzf); return NULL; };
1134 bzf->strm.avail_in = bzf->bufN;
1135 bzf->strm.next_in = bzf->buf;
1137 bzf->initialisedOk = True;
1138 return bzf;
1142 /*---------------------------------------------------*/
1143 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1145 bzFile* bzf = (bzFile*)b;
1147 BZ_SETERR(BZ_OK);
1148 if (bzf == NULL)
1149 { BZ_SETERR(BZ_OK); return; };
1151 if (bzf->writing)
1152 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1154 if (bzf->initialisedOk)
1155 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1156 free ( bzf );
1160 /*---------------------------------------------------*/
1161 int BZ_API(BZ2_bzRead)
1162 ( int* bzerror,
1163 BZFILE* b,
1164 void* buf,
1165 int len )
1167 Int32 n, ret;
1168 bzFile* bzf = (bzFile*)b;
1170 BZ_SETERR(BZ_OK);
1172 if (bzf == NULL || buf == NULL || len < 0)
1173 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1175 if (bzf->writing)
1176 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1178 if (len == 0)
1179 { BZ_SETERR(BZ_OK); return 0; };
1181 bzf->strm.avail_out = len;
1182 bzf->strm.next_out = buf;
1184 while (True) {
1186 if (ferror(bzf->handle))
1187 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1189 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1190 n = fread ( bzf->buf, sizeof(UChar),
1191 BZ_MAX_UNUSED, bzf->handle );
1192 if (ferror(bzf->handle))
1193 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1194 bzf->bufN = n;
1195 bzf->strm.avail_in = bzf->bufN;
1196 bzf->strm.next_in = bzf->buf;
1199 ret = BZ2_bzDecompress ( &(bzf->strm) );
1201 if (ret != BZ_OK && ret != BZ_STREAM_END)
1202 { BZ_SETERR(ret); return 0; };
1204 if (ret == BZ_OK && myfeof(bzf->handle) &&
1205 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1206 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1208 if (ret == BZ_STREAM_END)
1209 { BZ_SETERR(BZ_STREAM_END);
1210 return len - bzf->strm.avail_out; };
1211 if (bzf->strm.avail_out == 0)
1212 { BZ_SETERR(BZ_OK); return len; };
1216 return 0; /*not reached*/
1220 /*---------------------------------------------------*/
1221 void BZ_API(BZ2_bzReadGetUnused)
1222 ( int* bzerror,
1223 BZFILE* b,
1224 void** unused,
1225 int* nUnused )
1227 bzFile* bzf = (bzFile*)b;
1228 if (bzf == NULL)
1229 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1230 if (bzf->lastErr != BZ_STREAM_END)
1231 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1232 if (unused == NULL || nUnused == NULL)
1233 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1235 BZ_SETERR(BZ_OK);
1236 *nUnused = bzf->strm.avail_in;
1237 *unused = bzf->strm.next_in;
1239 #endif
1242 /*---------------------------------------------------*/
1243 /*--- Misc convenience stuff ---*/
1244 /*---------------------------------------------------*/
1246 /*---------------------------------------------------*/
1247 int BZ_API(BZ2_bzBuffToBuffCompress)
1248 ( char* dest,
1249 unsigned int* destLen,
1250 char* source,
1251 unsigned int sourceLen,
1252 int blockSize100k,
1253 int verbosity,
1254 int workFactor )
1256 bz_stream strm;
1257 int ret;
1259 if (dest == NULL || destLen == NULL ||
1260 source == NULL ||
1261 blockSize100k < 1 || blockSize100k > 9 ||
1262 verbosity < 0 || verbosity > 4 ||
1263 workFactor < 0 || workFactor > 250)
1264 return BZ_PARAM_ERROR;
1266 if (workFactor == 0) workFactor = 30;
1267 strm.bzalloc = NULL;
1268 strm.bzfree = NULL;
1269 strm.opaque = NULL;
1270 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1271 verbosity, workFactor );
1272 if (ret != BZ_OK) return ret;
1274 strm.next_in = source;
1275 strm.next_out = dest;
1276 strm.avail_in = sourceLen;
1277 strm.avail_out = *destLen;
1279 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1280 if (ret == BZ_FINISH_OK) goto output_overflow;
1281 if (ret != BZ_STREAM_END) goto errhandler;
1283 /* normal termination */
1284 *destLen -= strm.avail_out;
1285 BZ2_bzCompressEnd ( &strm );
1286 return BZ_OK;
1288 output_overflow:
1289 BZ2_bzCompressEnd ( &strm );
1290 return BZ_OUTBUFF_FULL;
1292 errhandler:
1293 BZ2_bzCompressEnd ( &strm );
1294 return ret;
1298 /*---------------------------------------------------*/
1299 int BZ_API(BZ2_bzBuffToBuffDecompress)
1300 ( char* dest,
1301 unsigned int* destLen,
1302 char* source,
1303 unsigned int sourceLen,
1304 int small,
1305 int verbosity )
1307 bz_stream strm;
1308 int ret;
1310 if (dest == NULL || destLen == NULL ||
1311 source == NULL ||
1312 (small != 0 && small != 1) ||
1313 verbosity < 0 || verbosity > 4)
1314 return BZ_PARAM_ERROR;
1316 strm.bzalloc = NULL;
1317 strm.bzfree = NULL;
1318 strm.opaque = NULL;
1319 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1320 if (ret != BZ_OK) return ret;
1322 strm.next_in = source;
1323 strm.next_out = dest;
1324 strm.avail_in = sourceLen;
1325 strm.avail_out = *destLen;
1327 ret = BZ2_bzDecompress ( &strm );
1328 if (ret == BZ_OK) goto output_overflow_or_eof;
1329 if (ret != BZ_STREAM_END) goto errhandler;
1331 /* normal termination */
1332 *destLen -= strm.avail_out;
1333 BZ2_bzDecompressEnd ( &strm );
1334 return BZ_OK;
1336 output_overflow_or_eof:
1337 if (strm.avail_out > 0) {
1338 BZ2_bzDecompressEnd ( &strm );
1339 return BZ_UNEXPECTED_EOF;
1340 } else {
1341 BZ2_bzDecompressEnd ( &strm );
1342 return BZ_OUTBUFF_FULL;
1345 errhandler:
1346 BZ2_bzDecompressEnd ( &strm );
1347 return ret;
1351 /*---------------------------------------------------*/
1352 /*--
1353 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1354 to support better zlib compatibility.
1355 This code is not _officially_ part of libbzip2 (yet);
1356 I haven't tested it, documented it, or considered the
1357 threading-safeness of it.
1358 If this code breaks, please contact both Yoshioka and me.
1359 --*/
1360 /*---------------------------------------------------*/
1362 /*---------------------------------------------------*/
1363 /*--
1364 return version like "0.9.5d, 4-Sept-1999".
1365 --*/
1366 const char * BZ_API(BZ2_bzlibVersion)(void)
1368 return BZ_VERSION;
1372 #ifndef BZ_NO_STDIO
1373 /*---------------------------------------------------*/
1375 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1376 # include <fcntl.h>
1377 # include <io.h>
1378 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1379 #else
1380 # define SET_BINARY_MODE(file)
1381 #endif
1382 static
1383 BZFILE * bzopen_or_bzdopen
1384 ( const char *path, /* no use when bzdopen */
1385 int fd, /* no use when bzdopen */
1386 const char *mode,
1387 int open_mode) /* bzopen: 0, bzdopen:1 */
1389 int bzerr;
1390 char unused[BZ_MAX_UNUSED];
1391 int blockSize100k = 9;
1392 int writing = 0;
1393 char mode2[10] = "";
1394 FILE *fp = NULL;
1395 BZFILE *bzfp = NULL;
1396 int verbosity = 0;
1397 int workFactor = 30;
1398 int smallMode = 0;
1399 int nUnused = 0;
1401 if (mode == NULL) return NULL;
1402 while (*mode) {
1403 switch (*mode) {
1404 case 'r':
1405 writing = 0; break;
1406 case 'w':
1407 writing = 1; break;
1408 case 's':
1409 smallMode = 1; break;
1410 default:
1411 if (isdigit((int)(*mode))) {
1412 blockSize100k = *mode-BZ_HDR_0;
1415 mode++;
1417 strcat(mode2, writing ? "w" : "r" );
1418 strcat(mode2,"b"); /* binary mode */
1420 if (open_mode==0) {
1421 if (path==NULL || strcmp(path,"")==0) {
1422 fp = (writing ? stdout : stdin);
1423 SET_BINARY_MODE(fp);
1424 } else {
1425 fp = fopen(path,mode2);
1427 } else {
1428 #ifdef BZ_STRICT_ANSI
1429 fp = NULL;
1430 #else
1431 fp = fdopen(fd,mode2);
1432 #endif
1434 if (fp == NULL) return NULL;
1436 if (writing) {
1437 /* Guard against total chaos and anarchy -- JRS */
1438 if (blockSize100k < 1) blockSize100k = 1;
1439 if (blockSize100k > 9) blockSize100k = 9;
1440 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1441 verbosity,workFactor);
1442 } else {
1443 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1444 unused,nUnused);
1446 if (bzfp == NULL) {
1447 if (fp != stdin && fp != stdout) fclose(fp);
1448 return NULL;
1450 return bzfp;
1454 /*---------------------------------------------------*/
1455 /*--
1456 open file for read or write.
1457 ex) bzopen("file","w9")
1458 case path="" or NULL => use stdin or stdout.
1459 --*/
1460 BZFILE * BZ_API(BZ2_bzopen)
1461 ( const char *path,
1462 const char *mode )
1464 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1468 /*---------------------------------------------------*/
1469 BZFILE * BZ_API(BZ2_bzdopen)
1470 ( int fd,
1471 const char *mode )
1473 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1477 /*---------------------------------------------------*/
1478 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1480 int bzerr, nread;
1481 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1482 nread = BZ2_bzRead(&bzerr,b,buf,len);
1483 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1484 return nread;
1485 } else {
1486 return -1;
1491 /*---------------------------------------------------*/
1492 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1494 int bzerr;
1496 BZ2_bzWrite(&bzerr,b,buf,len);
1497 if(bzerr == BZ_OK){
1498 return len;
1499 }else{
1500 return -1;
1505 /*---------------------------------------------------*/
1506 int BZ_API(BZ2_bzflush) (BZFILE *b)
1508 /* do nothing now... */
1509 return 0;
1513 /*---------------------------------------------------*/
1514 void BZ_API(BZ2_bzclose) (BZFILE* b)
1516 int bzerr;
1517 FILE *fp;
1519 if (b==NULL) {return;}
1520 fp = ((bzFile *)b)->handle;
1521 if(((bzFile*)b)->writing){
1522 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1523 if(bzerr != BZ_OK){
1524 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1526 }else{
1527 BZ2_bzReadClose(&bzerr,b);
1529 if(fp!=stdin && fp!=stdout){
1530 fclose(fp);
1535 /*---------------------------------------------------*/
1536 /*--
1537 return last error code
1538 --*/
1539 static const char *bzerrorstrings[] = {
1540 "OK"
1541 ,"SEQUENCE_ERROR"
1542 ,"PARAM_ERROR"
1543 ,"MEM_ERROR"
1544 ,"DATA_ERROR"
1545 ,"DATA_ERROR_MAGIC"
1546 ,"IO_ERROR"
1547 ,"UNEXPECTED_EOF"
1548 ,"OUTBUFF_FULL"
1549 ,"CONFIG_ERROR"
1550 ,"???" /* for future */
1551 ,"???" /* for future */
1552 ,"???" /* for future */
1553 ,"???" /* for future */
1554 ,"???" /* for future */
1555 ,"???" /* for future */
1559 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1561 int err = ((bzFile *)b)->lastErr;
1563 if(err>0) err = 0;
1564 *errnum = err;
1565 return bzerrorstrings[err*-1];
1567 #endif
1570 /*-------------------------------------------------------------*/
1571 /*--- end bzlib.c ---*/
1572 /*-------------------------------------------------------------*/