Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / modules / libbz2 / src / bzlib.c
blobd504e412d25e6ebec86f67bb8c4d3f21c0101fbd
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.4 of 20 December 2006
12 Copyright (C) 1996-2006 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, 15 February 2005.\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 /* end restore */
603 UInt32 avail_out_INIT = cs_avail_out;
604 Int32 s_save_nblockPP = s->save_nblock+1;
605 unsigned int total_out_lo32_old;
607 while (True) {
609 /* try to finish existing run */
610 if (c_state_out_len > 0) {
611 while (True) {
612 if (cs_avail_out == 0) goto return_notr;
613 if (c_state_out_len == 1) break;
614 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
615 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
616 c_state_out_len--;
617 cs_next_out++;
618 cs_avail_out--;
620 s_state_out_len_eq_one:
622 if (cs_avail_out == 0) {
623 c_state_out_len = 1; goto return_notr;
625 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
626 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
627 cs_next_out++;
628 cs_avail_out--;
631 /* Only caused by corrupt data stream? */
632 if (c_nblock_used > s_save_nblockPP)
633 return True;
635 /* can a new run be started? */
636 if (c_nblock_used == s_save_nblockPP) {
637 c_state_out_len = 0; goto return_notr;
639 c_state_out_ch = c_k0;
640 BZ_GET_FAST_C(k1); c_nblock_used++;
641 if (k1 != c_k0) {
642 c_k0 = k1; goto s_state_out_len_eq_one;
644 if (c_nblock_used == s_save_nblockPP)
645 goto s_state_out_len_eq_one;
647 c_state_out_len = 2;
648 BZ_GET_FAST_C(k1); c_nblock_used++;
649 if (c_nblock_used == s_save_nblockPP) continue;
650 if (k1 != c_k0) { c_k0 = k1; continue; };
652 c_state_out_len = 3;
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 BZ_GET_FAST_C(k1); c_nblock_used++;
658 c_state_out_len = ((Int32)k1) + 4;
659 BZ_GET_FAST_C(c_k0); c_nblock_used++;
662 return_notr:
663 total_out_lo32_old = s->strm->total_out_lo32;
664 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
665 if (s->strm->total_out_lo32 < total_out_lo32_old)
666 s->strm->total_out_hi32++;
668 /* save */
669 s->calculatedBlockCRC = c_calculatedBlockCRC;
670 s->state_out_ch = c_state_out_ch;
671 s->state_out_len = c_state_out_len;
672 s->nblock_used = c_nblock_used;
673 s->k0 = c_k0;
674 s->tt = c_tt;
675 s->tPos = c_tPos;
676 s->strm->next_out = cs_next_out;
677 s->strm->avail_out = cs_avail_out;
678 /* end save */
680 return False;
685 /*---------------------------------------------------*/
686 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
688 Int32 nb, na, mid;
689 nb = 0;
690 na = 256;
691 do {
692 mid = (nb + na) >> 1;
693 if (indx >= cftab[mid]) nb = mid; else na = mid;
695 while (na - nb != 1);
696 return nb;
700 /*---------------------------------------------------*/
701 /* Return True iff data corruption is discovered.
702 Returns False if there is no problem.
704 static
705 Bool unRLE_obuf_to_output_SMALL ( DState* s )
707 UChar k1;
709 if (s->blockRandomised) {
711 while (True) {
712 /* try to finish existing run */
713 while (True) {
714 if (s->strm->avail_out == 0) return False;
715 if (s->state_out_len == 0) break;
716 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
717 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
718 s->state_out_len--;
719 s->strm->next_out++;
720 s->strm->avail_out--;
721 s->strm->total_out_lo32++;
722 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
725 /* can a new run be started? */
726 if (s->nblock_used == s->save_nblock+1) return False;
728 /* Only caused by corrupt data stream? */
729 if (s->nblock_used > s->save_nblock+1)
730 return True;
732 s->state_out_len = 1;
733 s->state_out_ch = s->k0;
734 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
735 k1 ^= BZ_RAND_MASK; s->nblock_used++;
736 if (s->nblock_used == s->save_nblock+1) continue;
737 if (k1 != s->k0) { s->k0 = k1; continue; };
739 s->state_out_len = 2;
740 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
741 k1 ^= BZ_RAND_MASK; s->nblock_used++;
742 if (s->nblock_used == s->save_nblock+1) continue;
743 if (k1 != s->k0) { s->k0 = k1; continue; };
745 s->state_out_len = 3;
746 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
747 k1 ^= BZ_RAND_MASK; s->nblock_used++;
748 if (s->nblock_used == s->save_nblock+1) continue;
749 if (k1 != s->k0) { s->k0 = k1; continue; };
751 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
752 k1 ^= BZ_RAND_MASK; s->nblock_used++;
753 s->state_out_len = ((Int32)k1) + 4;
754 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
755 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
758 } else {
760 while (True) {
761 /* try to finish existing run */
762 while (True) {
763 if (s->strm->avail_out == 0) return False;
764 if (s->state_out_len == 0) break;
765 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
766 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
767 s->state_out_len--;
768 s->strm->next_out++;
769 s->strm->avail_out--;
770 s->strm->total_out_lo32++;
771 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
774 /* can a new run be started? */
775 if (s->nblock_used == s->save_nblock+1) return False;
777 /* Only caused by corrupt data stream? */
778 if (s->nblock_used > s->save_nblock+1)
779 return True;
781 s->state_out_len = 1;
782 s->state_out_ch = s->k0;
783 BZ_GET_SMALL(k1); s->nblock_used++;
784 if (s->nblock_used == s->save_nblock+1) continue;
785 if (k1 != s->k0) { s->k0 = k1; continue; };
787 s->state_out_len = 2;
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 = 3;
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 BZ_GET_SMALL(k1); s->nblock_used++;
798 s->state_out_len = ((Int32)k1) + 4;
799 BZ_GET_SMALL(s->k0); s->nblock_used++;
806 /*---------------------------------------------------*/
807 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
809 Bool corrupt;
810 DState* s;
811 if (strm == NULL) return BZ_PARAM_ERROR;
812 s = strm->state;
813 if (s == NULL) return BZ_PARAM_ERROR;
814 if (s->strm != strm) return BZ_PARAM_ERROR;
816 while (True) {
817 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
818 if (s->state == BZ_X_OUTPUT) {
819 if (s->smallDecompress)
820 corrupt = unRLE_obuf_to_output_SMALL ( s ); else
821 corrupt = unRLE_obuf_to_output_FAST ( s );
822 if (corrupt) return BZ_DATA_ERROR;
823 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
824 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
825 if (s->verbosity >= 3)
826 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
827 s->calculatedBlockCRC );
828 if (s->verbosity >= 2) VPrintf0 ( "]" );
829 if (s->calculatedBlockCRC != s->storedBlockCRC)
830 return BZ_DATA_ERROR;
831 s->calculatedCombinedCRC
832 = (s->calculatedCombinedCRC << 1) |
833 (s->calculatedCombinedCRC >> 31);
834 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
835 s->state = BZ_X_BLKHDR_1;
836 } else {
837 return BZ_OK;
840 if (s->state >= BZ_X_MAGIC_1) {
841 Int32 r = BZ2_decompress ( s );
842 if (r == BZ_STREAM_END) {
843 if (s->verbosity >= 3)
844 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
845 s->storedCombinedCRC, s->calculatedCombinedCRC );
846 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
847 return BZ_DATA_ERROR;
848 return r;
850 if (s->state != BZ_X_OUTPUT) return r;
854 AssertH ( 0, 6001 );
856 return 0; /*NOTREACHED*/
860 /*---------------------------------------------------*/
861 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
863 DState* s;
864 if (strm == NULL) return BZ_PARAM_ERROR;
865 s = strm->state;
866 if (s == NULL) return BZ_PARAM_ERROR;
867 if (s->strm != strm) return BZ_PARAM_ERROR;
869 if (s->tt != NULL) BZFREE(s->tt);
870 if (s->ll16 != NULL) BZFREE(s->ll16);
871 if (s->ll4 != NULL) BZFREE(s->ll4);
873 BZFREE(strm->state);
874 strm->state = NULL;
876 return BZ_OK;
880 #ifndef BZ_NO_STDIO
881 /*---------------------------------------------------*/
882 /*--- File I/O stuff ---*/
883 /*---------------------------------------------------*/
885 #define BZ_SETERR(eee) \
887 if (bzerror != NULL) *bzerror = eee; \
888 if (bzf != NULL) bzf->lastErr = eee; \
891 typedef
892 struct {
893 FILE* handle;
894 Char buf[BZ_MAX_UNUSED];
895 Int32 bufN;
896 Bool writing;
897 bz_stream strm;
898 Int32 lastErr;
899 Bool initialisedOk;
901 bzFile;
904 /*---------------------------------------------*/
905 static Bool myfeof ( FILE* f )
907 Int32 c = fgetc ( f );
908 if (c == EOF) return True;
909 ungetc ( c, f );
910 return False;
914 /*---------------------------------------------------*/
915 BZFILE* BZ_API(BZ2_bzWriteOpen)
916 ( int* bzerror,
917 FILE* f,
918 int blockSize100k,
919 int verbosity,
920 int workFactor )
922 Int32 ret;
923 bzFile* bzf = NULL;
925 BZ_SETERR(BZ_OK);
927 if (f == NULL ||
928 (blockSize100k < 1 || blockSize100k > 9) ||
929 (workFactor < 0 || workFactor > 250) ||
930 (verbosity < 0 || verbosity > 4))
931 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
933 if (ferror(f))
934 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
936 bzf = malloc ( sizeof(bzFile) );
937 if (bzf == NULL)
938 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
940 BZ_SETERR(BZ_OK);
941 bzf->initialisedOk = False;
942 bzf->bufN = 0;
943 bzf->handle = f;
944 bzf->writing = True;
945 bzf->strm.bzalloc = NULL;
946 bzf->strm.bzfree = NULL;
947 bzf->strm.opaque = NULL;
949 if (workFactor == 0) workFactor = 30;
950 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
951 verbosity, workFactor );
952 if (ret != BZ_OK)
953 { BZ_SETERR(ret); free(bzf); return NULL; };
955 bzf->strm.avail_in = 0;
956 bzf->initialisedOk = True;
957 return bzf;
962 /*---------------------------------------------------*/
963 void BZ_API(BZ2_bzWrite)
964 ( int* bzerror,
965 BZFILE* b,
966 void* buf,
967 int len )
969 Int32 n, n2, ret;
970 bzFile* bzf = (bzFile*)b;
972 BZ_SETERR(BZ_OK);
973 if (bzf == NULL || buf == NULL || len < 0)
974 { BZ_SETERR(BZ_PARAM_ERROR); return; };
975 if (!(bzf->writing))
976 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
977 if (ferror(bzf->handle))
978 { BZ_SETERR(BZ_IO_ERROR); return; };
980 if (len == 0)
981 { BZ_SETERR(BZ_OK); return; };
983 bzf->strm.avail_in = len;
984 bzf->strm.next_in = buf;
986 while (True) {
987 bzf->strm.avail_out = BZ_MAX_UNUSED;
988 bzf->strm.next_out = bzf->buf;
989 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
990 if (ret != BZ_RUN_OK)
991 { BZ_SETERR(ret); return; };
993 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
994 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
995 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
996 n, bzf->handle );
997 if (n != n2 || ferror(bzf->handle))
998 { BZ_SETERR(BZ_IO_ERROR); return; };
1001 if (bzf->strm.avail_in == 0)
1002 { BZ_SETERR(BZ_OK); return; };
1007 /*---------------------------------------------------*/
1008 void BZ_API(BZ2_bzWriteClose)
1009 ( int* bzerror,
1010 BZFILE* b,
1011 int abandon,
1012 unsigned int* nbytes_in,
1013 unsigned int* nbytes_out )
1015 BZ2_bzWriteClose64 ( bzerror, b, abandon,
1016 nbytes_in, NULL, nbytes_out, NULL );
1020 void BZ_API(BZ2_bzWriteClose64)
1021 ( int* bzerror,
1022 BZFILE* b,
1023 int abandon,
1024 unsigned int* nbytes_in_lo32,
1025 unsigned int* nbytes_in_hi32,
1026 unsigned int* nbytes_out_lo32,
1027 unsigned int* nbytes_out_hi32 )
1029 Int32 n, n2, ret;
1030 bzFile* bzf = (bzFile*)b;
1032 if (bzf == NULL)
1033 { BZ_SETERR(BZ_OK); return; };
1034 if (!(bzf->writing))
1035 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1036 if (ferror(bzf->handle))
1037 { BZ_SETERR(BZ_IO_ERROR); return; };
1039 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1040 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1041 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1042 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1044 if ((!abandon) && bzf->lastErr == BZ_OK) {
1045 while (True) {
1046 bzf->strm.avail_out = BZ_MAX_UNUSED;
1047 bzf->strm.next_out = bzf->buf;
1048 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1049 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1050 { BZ_SETERR(ret); return; };
1052 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1053 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1054 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1055 n, bzf->handle );
1056 if (n != n2 || ferror(bzf->handle))
1057 { BZ_SETERR(BZ_IO_ERROR); return; };
1060 if (ret == BZ_STREAM_END) break;
1064 if ( !abandon && !ferror ( bzf->handle ) ) {
1065 fflush ( bzf->handle );
1066 if (ferror(bzf->handle))
1067 { BZ_SETERR(BZ_IO_ERROR); return; };
1070 if (nbytes_in_lo32 != NULL)
1071 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1072 if (nbytes_in_hi32 != NULL)
1073 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1074 if (nbytes_out_lo32 != NULL)
1075 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1076 if (nbytes_out_hi32 != NULL)
1077 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1079 BZ_SETERR(BZ_OK);
1080 BZ2_bzCompressEnd ( &(bzf->strm) );
1081 free ( bzf );
1085 /*---------------------------------------------------*/
1086 BZFILE* BZ_API(BZ2_bzReadOpen)
1087 ( int* bzerror,
1088 FILE* f,
1089 int verbosity,
1090 int small,
1091 void* unused,
1092 int nUnused )
1094 bzFile* bzf = NULL;
1095 int ret;
1097 BZ_SETERR(BZ_OK);
1099 if (f == NULL ||
1100 (small != 0 && small != 1) ||
1101 (verbosity < 0 || verbosity > 4) ||
1102 (unused == NULL && nUnused != 0) ||
1103 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1104 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1106 if (ferror(f))
1107 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1109 bzf = malloc ( sizeof(bzFile) );
1110 if (bzf == NULL)
1111 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1113 BZ_SETERR(BZ_OK);
1115 bzf->initialisedOk = False;
1116 bzf->handle = f;
1117 bzf->bufN = 0;
1118 bzf->writing = False;
1119 bzf->strm.bzalloc = NULL;
1120 bzf->strm.bzfree = NULL;
1121 bzf->strm.opaque = NULL;
1123 while (nUnused > 0) {
1124 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1125 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1126 nUnused--;
1129 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1130 if (ret != BZ_OK)
1131 { BZ_SETERR(ret); free(bzf); return NULL; };
1133 bzf->strm.avail_in = bzf->bufN;
1134 bzf->strm.next_in = bzf->buf;
1136 bzf->initialisedOk = True;
1137 return bzf;
1141 /*---------------------------------------------------*/
1142 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1144 bzFile* bzf = (bzFile*)b;
1146 BZ_SETERR(BZ_OK);
1147 if (bzf == NULL)
1148 { BZ_SETERR(BZ_OK); return; };
1150 if (bzf->writing)
1151 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1153 if (bzf->initialisedOk)
1154 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1155 free ( bzf );
1159 /*---------------------------------------------------*/
1160 int BZ_API(BZ2_bzRead)
1161 ( int* bzerror,
1162 BZFILE* b,
1163 void* buf,
1164 int len )
1166 Int32 n, ret;
1167 bzFile* bzf = (bzFile*)b;
1169 BZ_SETERR(BZ_OK);
1171 if (bzf == NULL || buf == NULL || len < 0)
1172 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1174 if (bzf->writing)
1175 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1177 if (len == 0)
1178 { BZ_SETERR(BZ_OK); return 0; };
1180 bzf->strm.avail_out = len;
1181 bzf->strm.next_out = buf;
1183 while (True) {
1185 if (ferror(bzf->handle))
1186 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1188 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1189 n = fread ( bzf->buf, sizeof(UChar),
1190 BZ_MAX_UNUSED, bzf->handle );
1191 if (ferror(bzf->handle))
1192 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1193 bzf->bufN = n;
1194 bzf->strm.avail_in = bzf->bufN;
1195 bzf->strm.next_in = bzf->buf;
1198 ret = BZ2_bzDecompress ( &(bzf->strm) );
1200 if (ret != BZ_OK && ret != BZ_STREAM_END)
1201 { BZ_SETERR(ret); return 0; };
1203 if (ret == BZ_OK && myfeof(bzf->handle) &&
1204 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1205 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1207 if (ret == BZ_STREAM_END)
1208 { BZ_SETERR(BZ_STREAM_END);
1209 return len - bzf->strm.avail_out; };
1210 if (bzf->strm.avail_out == 0)
1211 { BZ_SETERR(BZ_OK); return len; };
1215 return 0; /*not reached*/
1219 /*---------------------------------------------------*/
1220 void BZ_API(BZ2_bzReadGetUnused)
1221 ( int* bzerror,
1222 BZFILE* b,
1223 void** unused,
1224 int* nUnused )
1226 bzFile* bzf = (bzFile*)b;
1227 if (bzf == NULL)
1228 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1229 if (bzf->lastErr != BZ_STREAM_END)
1230 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1231 if (unused == NULL || nUnused == NULL)
1232 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1234 BZ_SETERR(BZ_OK);
1235 *nUnused = bzf->strm.avail_in;
1236 *unused = bzf->strm.next_in;
1238 #endif
1241 /*---------------------------------------------------*/
1242 /*--- Misc convenience stuff ---*/
1243 /*---------------------------------------------------*/
1245 /*---------------------------------------------------*/
1246 int BZ_API(BZ2_bzBuffToBuffCompress)
1247 ( char* dest,
1248 unsigned int* destLen,
1249 char* source,
1250 unsigned int sourceLen,
1251 int blockSize100k,
1252 int verbosity,
1253 int workFactor )
1255 bz_stream strm;
1256 int ret;
1258 if (dest == NULL || destLen == NULL ||
1259 source == NULL ||
1260 blockSize100k < 1 || blockSize100k > 9 ||
1261 verbosity < 0 || verbosity > 4 ||
1262 workFactor < 0 || workFactor > 250)
1263 return BZ_PARAM_ERROR;
1265 if (workFactor == 0) workFactor = 30;
1266 strm.bzalloc = NULL;
1267 strm.bzfree = NULL;
1268 strm.opaque = NULL;
1269 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1270 verbosity, workFactor );
1271 if (ret != BZ_OK) return ret;
1273 strm.next_in = source;
1274 strm.next_out = dest;
1275 strm.avail_in = sourceLen;
1276 strm.avail_out = *destLen;
1278 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1279 if (ret == BZ_FINISH_OK) goto output_overflow;
1280 if (ret != BZ_STREAM_END) goto errhandler;
1282 /* normal termination */
1283 *destLen -= strm.avail_out;
1284 BZ2_bzCompressEnd ( &strm );
1285 return BZ_OK;
1287 output_overflow:
1288 BZ2_bzCompressEnd ( &strm );
1289 return BZ_OUTBUFF_FULL;
1291 errhandler:
1292 BZ2_bzCompressEnd ( &strm );
1293 return ret;
1297 /*---------------------------------------------------*/
1298 int BZ_API(BZ2_bzBuffToBuffDecompress)
1299 ( char* dest,
1300 unsigned int* destLen,
1301 char* source,
1302 unsigned int sourceLen,
1303 int small,
1304 int verbosity )
1306 bz_stream strm;
1307 int ret;
1309 if (dest == NULL || destLen == NULL ||
1310 source == NULL ||
1311 (small != 0 && small != 1) ||
1312 verbosity < 0 || verbosity > 4)
1313 return BZ_PARAM_ERROR;
1315 strm.bzalloc = NULL;
1316 strm.bzfree = NULL;
1317 strm.opaque = NULL;
1318 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1319 if (ret != BZ_OK) return ret;
1321 strm.next_in = source;
1322 strm.next_out = dest;
1323 strm.avail_in = sourceLen;
1324 strm.avail_out = *destLen;
1326 ret = BZ2_bzDecompress ( &strm );
1327 if (ret == BZ_OK) goto output_overflow_or_eof;
1328 if (ret != BZ_STREAM_END) goto errhandler;
1330 /* normal termination */
1331 *destLen -= strm.avail_out;
1332 BZ2_bzDecompressEnd ( &strm );
1333 return BZ_OK;
1335 output_overflow_or_eof:
1336 if (strm.avail_out > 0) {
1337 BZ2_bzDecompressEnd ( &strm );
1338 return BZ_UNEXPECTED_EOF;
1339 } else {
1340 BZ2_bzDecompressEnd ( &strm );
1341 return BZ_OUTBUFF_FULL;
1344 errhandler:
1345 BZ2_bzDecompressEnd ( &strm );
1346 return ret;
1350 /*---------------------------------------------------*/
1351 /*--
1352 Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1353 to support better zlib compatibility.
1354 This code is not _officially_ part of libbzip2 (yet);
1355 I haven't tested it, documented it, or considered the
1356 threading-safeness of it.
1357 If this code breaks, please contact both Yoshioka and me.
1358 --*/
1359 /*---------------------------------------------------*/
1361 /*---------------------------------------------------*/
1362 /*--
1363 return version like "0.9.5d, 4-Sept-1999".
1364 --*/
1365 const char * BZ_API(BZ2_bzlibVersion)(void)
1367 return BZ_VERSION;
1371 #ifndef BZ_NO_STDIO
1372 /*---------------------------------------------------*/
1374 #if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(WINCE)
1375 # include <fcntl.h>
1376 # include <io.h>
1377 # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1378 #else
1379 # define SET_BINARY_MODE(file)
1380 #endif
1381 static
1382 BZFILE * bzopen_or_bzdopen
1383 ( const char *path, /* no use when bzdopen */
1384 int fd, /* no use when bzdopen */
1385 const char *mode,
1386 int open_mode) /* bzopen: 0, bzdopen:1 */
1388 int bzerr;
1389 char unused[BZ_MAX_UNUSED];
1390 int blockSize100k = 9;
1391 int writing = 0;
1392 char mode2[10] = "";
1393 FILE *fp = NULL;
1394 BZFILE *bzfp = NULL;
1395 int verbosity = 0;
1396 int workFactor = 30;
1397 int smallMode = 0;
1398 int nUnused = 0;
1400 if (mode == NULL) return NULL;
1401 while (*mode) {
1402 switch (*mode) {
1403 case 'r':
1404 writing = 0; break;
1405 case 'w':
1406 writing = 1; break;
1407 case 's':
1408 smallMode = 1; break;
1409 default:
1410 if (isdigit((int)(*mode))) {
1411 blockSize100k = *mode-BZ_HDR_0;
1414 mode++;
1416 strcat(mode2, writing ? "w" : "r" );
1417 strcat(mode2,"b"); /* binary mode */
1419 if (open_mode==0) {
1420 if (path==NULL || strcmp(path,"")==0) {
1421 fp = (writing ? stdout : stdin);
1422 SET_BINARY_MODE(fp);
1423 } else {
1424 fp = fopen(path,mode2);
1426 } else {
1427 #ifdef BZ_STRICT_ANSI
1428 fp = NULL;
1429 #else
1430 fp = fdopen(fd,mode2);
1431 #endif
1433 if (fp == NULL) return NULL;
1435 if (writing) {
1436 /* Guard against total chaos and anarchy -- JRS */
1437 if (blockSize100k < 1) blockSize100k = 1;
1438 if (blockSize100k > 9) blockSize100k = 9;
1439 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1440 verbosity,workFactor);
1441 } else {
1442 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1443 unused,nUnused);
1445 if (bzfp == NULL) {
1446 if (fp != stdin && fp != stdout) fclose(fp);
1447 return NULL;
1449 return bzfp;
1453 /*---------------------------------------------------*/
1454 /*--
1455 open file for read or write.
1456 ex) bzopen("file","w9")
1457 case path="" or NULL => use stdin or stdout.
1458 --*/
1459 BZFILE * BZ_API(BZ2_bzopen)
1460 ( const char *path,
1461 const char *mode )
1463 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1467 /*---------------------------------------------------*/
1468 BZFILE * BZ_API(BZ2_bzdopen)
1469 ( int fd,
1470 const char *mode )
1472 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1476 /*---------------------------------------------------*/
1477 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1479 int bzerr, nread;
1480 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1481 nread = BZ2_bzRead(&bzerr,b,buf,len);
1482 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1483 return nread;
1484 } else {
1485 return -1;
1490 /*---------------------------------------------------*/
1491 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1493 int bzerr;
1495 BZ2_bzWrite(&bzerr,b,buf,len);
1496 if(bzerr == BZ_OK){
1497 return len;
1498 }else{
1499 return -1;
1504 /*---------------------------------------------------*/
1505 int BZ_API(BZ2_bzflush) (BZFILE *b)
1507 /* do nothing now... */
1508 return 0;
1512 /*---------------------------------------------------*/
1513 void BZ_API(BZ2_bzclose) (BZFILE* b)
1515 int bzerr;
1516 FILE *fp;
1518 if (b==NULL) {return;}
1519 fp = ((bzFile *)b)->handle;
1520 if(((bzFile*)b)->writing){
1521 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1522 if(bzerr != BZ_OK){
1523 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1525 }else{
1526 BZ2_bzReadClose(&bzerr,b);
1528 if(fp!=stdin && fp!=stdout){
1529 fclose(fp);
1534 /*---------------------------------------------------*/
1535 /*--
1536 return last error code
1537 --*/
1538 static const char *bzerrorstrings[] = {
1539 "OK"
1540 ,"SEQUENCE_ERROR"
1541 ,"PARAM_ERROR"
1542 ,"MEM_ERROR"
1543 ,"DATA_ERROR"
1544 ,"DATA_ERROR_MAGIC"
1545 ,"IO_ERROR"
1546 ,"UNEXPECTED_EOF"
1547 ,"OUTBUFF_FULL"
1548 ,"CONFIG_ERROR"
1549 ,"???" /* for future */
1550 ,"???" /* for future */
1551 ,"???" /* for future */
1552 ,"???" /* for future */
1553 ,"???" /* for future */
1554 ,"???" /* for future */
1558 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1560 int err = ((bzFile *)b)->lastErr;
1562 if(err>0) err = 0;
1563 *errnum = err;
1564 return bzerrorstrings[err*-1];
1566 #endif
1569 /*-------------------------------------------------------------*/
1570 /*--- end bzlib.c ---*/
1571 /*-------------------------------------------------------------*/