xref: /illumos-gate/usr/src/common/bzip2/bzlib.c (revision 7957da45b8e66b8cd6e917ac6bd8965817d7ef06)
1 
2 /*-------------------------------------------------------------*/
3 /*--- Library top-level functions.                          ---*/
4 /*---                                               bzlib.c ---*/
5 /*-------------------------------------------------------------*/
6 
7 /* ------------------------------------------------------------------
8    This file is part of bzip2/libbzip2, a program and library for
9    lossless, block-sorting data compression.
10 
11    bzip2/libbzip2 version 1.0.6 of 6 September 2010
12    Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
13 
14    Please read the WARNING, DISCLAIMER and PATENTS sections in the
15    README file.
16 
17    This program is released under the terms of the license contained
18    in the file LICENSE.
19    ------------------------------------------------------------------ */
20 
21 /* CHANGES
22    0.9.0    -- original version.
23    0.9.0a/b -- no changes in this file.
24    0.9.0c   -- made zero-length BZ_FLUSH work correctly in bzCompress().
25      fixed bzWrite/bzRead to ignore zero-length requests.
26      fixed bzread to correctly handle read requests after EOF.
27      wrong parameter order in call to bzDecompressInit in
28      bzBuffToBuffDecompress.  Fixed.
29 */
30 
31 #include "bzlib_private.h"
32 
33 #ifndef BZ_NO_COMPRESS
34 
35 /*---------------------------------------------------*/
36 /*--- Compression stuff                           ---*/
37 /*---------------------------------------------------*/
38 
39 
40 /*---------------------------------------------------*/
41 #ifndef BZ_NO_STDIO
42 void BZ2_bz__AssertH__fail ( int errcode )
43 {
44    fprintf(stderr,
45       "\n\nbzip2/libbzip2: internal error number %d.\n"
46       "This is a bug in bzip2/libbzip2, %s.\n"
47       "Please report it to me at: jseward@bzip.org.  If this happened\n"
48       "when you were using some program which uses libbzip2 as a\n"
49       "component, you should also report this bug to the author(s)\n"
50       "of that program.  Please make an effort to report this bug;\n"
51       "timely and accurate bug reports eventually lead to higher\n"
52       "quality software.  Thanks.  Julian Seward, 10 December 2007.\n\n",
53       errcode,
54       BZ2_bzlibVersion()
55    );
56 
57    if (errcode == 1007) {
58    fprintf(stderr,
59       "\n*** A special note about internal error number 1007 ***\n"
60       "\n"
61       "Experience suggests that a common cause of i.e. 1007\n"
62       "is unreliable memory or other hardware.  The 1007 assertion\n"
63       "just happens to cross-check the results of huge numbers of\n"
64       "memory reads/writes, and so acts (unintendedly) as a stress\n"
65       "test of your memory system.\n"
66       "\n"
67       "I suggest the following: try compressing the file again,\n"
68       "possibly monitoring progress in detail with the -vv flag.\n"
69       "\n"
70       "* If the error cannot be reproduced, and/or happens at different\n"
71       "  points in compression, you may have a flaky memory system.\n"
72       "  Try a memory-test program.  I have used Memtest86\n"
73       "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
74       "  Memtest86 tests memory much more thorougly than your BIOSs\n"
75       "  power-on test, and may find failures that the BIOS doesn't.\n"
76       "\n"
77       "* If the error can be repeatably reproduced, this is a bug in\n"
78       "  bzip2, and I would very much like to hear about it.  Please\n"
79       "  let me know, and, ideally, save a copy of the file causing the\n"
80       "  problem -- without which I will be unable to investigate it.\n"
81       "\n"
82    );
83    }
84 
85    exit(3);
86 }
87 #endif
88 
89 #endif /* BZ_NO_COMPRESS */
90 
91 /*---------------------------------------------------*/
92 static
93 int bz_config_ok ( void )
94 {
95    if (sizeof(int)   != 4) return 0;
96    if (sizeof(short) != 2) return 0;
97    if (sizeof(char)  != 1) return 0;
98    return 1;
99 }
100 
101 /*
102  * Added for Solaris kernel
103  */
104 #define BZES \
105 BZE(BZ_OK) \
106 BZE(BZ_RUN_OK) \
107 BZE(BZ_FLUSH_OK) \
108 BZE(BZ_FINISH_OK) \
109 BZE(BZ_STREAM_END) \
110 BZE(BZ_SEQUENCE_ERROR) \
111 BZE(BZ_PARAM_ERROR) \
112 BZE(BZ_MEM_ERROR) \
113 BZE(BZ_DATA_ERROR) \
114 BZE(BZ_DATA_ERROR_MAGIC) \
115 BZE(BZ_IO_ERROR) \
116 BZE(BZ_UNEXPECTED_EOF) \
117 BZE(BZ_OUTBUFF_FULL) \
118 BZE(BZ_CONFIG_ERROR)
119 
120 BZ_EXTERN const char * BZ_API(BZ2_bzErrorString) (
121       int error_code
122    )
123 {
124 	switch (error_code)
125 	{
126 #define BZE(x) case x: return (#x);
127 BZES
128 #undef BZE
129 	}
130 	return ("BZ_UNKNOWN_ERROR");
131 }
132 
133 #ifndef BZ_LOADER
134 #include <sys/sysmacros.h>
135 #endif
136 
137 #ifdef _KERNEL
138 
139 #include <sys/types.h>
140 #include <sys/cmn_err.h>
141 #include <sys/kmem.h>
142 
143 void
144 bz_internal_error(int errcode)
145 {
146 	panic("bzip2 internal error: %s\n", BZ2_bzErrorString(errcode));
147 }
148 
149 /*---------------------------------------------------*/
150 typedef struct {
151 	char *buf;
152 	size_t sz;
153 } bzap;
154 
155 static
156 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
157 {
158 	size_t sz = sizeof (bzap) + BZ2_BZALLOC_ALIGN + (items * size);
159 	uintptr_t p = (uintptr_t)kmem_alloc(sz, KM_SLEEP);
160 
161 	if (p != NULL) {
162 		bzap *pp = (bzap *)((p + sizeof (bzap) + BZ2_BZALLOC_ALIGN - 1) &
163 		    -BZ2_BZALLOC_ALIGN);
164 		pp[-1].buf = (void *)p;
165 		pp[-1].sz = sz;
166 		return (pp);
167 	}
168 	return (NULL);
169 }
170 
171 static
172 void default_bzfree ( void* opaque, void* addr )
173 {
174 	if (addr != NULL) {
175 		bzap *pp = (bzap *)addr - 1;
176 		kmem_free(pp->buf, pp->sz);
177 	}
178 }
179 
180 #else
181 
182 /*---------------------------------------------------*/
183 static
184 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
185 {
186    void* v = malloc ( items * size );
187    return v;
188 }
189 
190 static
191 void default_bzfree ( void* opaque, void* addr )
192 {
193    if (addr != NULL) free ( addr );
194 }
195 #endif	/* _KERNEL */
196 
197 /*---------------------------------------------------*/
198 #ifndef BZ_NO_COMPRESS
199 static
200 void prepare_new_block ( EState* s )
201 {
202    Int32 i;
203    s->nblock = 0;
204    s->numZ = 0;
205    s->state_out_pos = 0;
206    BZ_INITIALISE_CRC ( s->blockCRC );
207    for (i = 0; i < 256; i++) s->inUse[i] = False;
208    s->blockNo++;
209 }
210 
211 
212 /*---------------------------------------------------*/
213 static
214 void init_RL ( EState* s )
215 {
216    s->state_in_ch  = 256;
217    s->state_in_len = 0;
218 }
219 
220 
221 static
222 Bool isempty_RL ( EState* s )
223 {
224    if (s->state_in_ch < 256 && s->state_in_len > 0)
225       return False; else
226       return True;
227 }
228 
229 
230 /*---------------------------------------------------*/
231 int BZ_API(BZ2_bzCompressInit)
232                     ( bz_stream* strm,
233                      int        blockSize100k,
234                      int        verbosity,
235                      int        workFactor )
236 {
237    Int32   n;
238    EState* s;
239 
240    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
241 
242    if (strm == NULL ||
243        blockSize100k < 1 || blockSize100k > 9 ||
244        workFactor < 0 || workFactor > 250)
245      return BZ_PARAM_ERROR;
246 
247    if (workFactor == 0) workFactor = 30;
248    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
249    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
250 
251    s = BZALLOC( sizeof(EState) );
252    if (s == NULL) return BZ_MEM_ERROR;
253    s->strm = strm;
254 
255    s->arr1 = NULL;
256    s->arr2 = NULL;
257    s->ftab = NULL;
258 
259    n       = 100000 * blockSize100k;
260    s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
261    s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
262    s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
263 
264    if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
265       if (s->arr1 != NULL) BZFREE(s->arr1);
266       if (s->arr2 != NULL) BZFREE(s->arr2);
267       if (s->ftab != NULL) BZFREE(s->ftab);
268       if (s       != NULL) BZFREE(s);
269       return BZ_MEM_ERROR;
270    }
271 
272    s->blockNo           = 0;
273    s->state             = BZ_S_INPUT;
274    s->mode              = BZ_M_RUNNING;
275    s->combinedCRC       = 0;
276    s->blockSize100k     = blockSize100k;
277    s->nblockMAX         = 100000 * blockSize100k - 19;
278    s->verbosity         = verbosity;
279    s->workFactor        = workFactor;
280 
281    s->block             = (UChar*)s->arr2;
282    s->mtfv              = (UInt16*)s->arr1;
283    s->zbits             = NULL;
284    s->ptr               = (UInt32*)s->arr1;
285 
286    strm->state          = s;
287    strm->total_in_lo32  = 0;
288    strm->total_in_hi32  = 0;
289    strm->total_out_lo32 = 0;
290    strm->total_out_hi32 = 0;
291    init_RL ( s );
292    prepare_new_block ( s );
293    return BZ_OK;
294 }
295 
296 /*---------------------------------------------------*/
297 /*
298  * returns the BZALLOC size needed for bzCompressInit
299  */
300 int BZ_API(BZ2_bzCompressInitSize) (
301                      int        blockSize100k)
302 {
303    Int32   n, t;
304 
305    n       = 100000 * blockSize100k;
306    t       = 0;
307    t += ( sizeof(EState) );
308    t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
309    t += ( n                  * sizeof(UInt32) );
310    t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
311    t += ( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
312    t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
313    t += ( 65537              * sizeof(UInt32) );
314    t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
315    return (t);
316 }
317 
318 /*---------------------------------------------------*/
319 /*
320  * added to allow reuse of bz_stream without malloc/free
321  */
322 int BZ_API(BZ2_bzCompressReset) ( bz_stream *strm )
323 {
324    EState* s = strm->state;
325 
326    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
327 
328    if (s == NULL) return BZ_MEM_ERROR;
329    s->strm = strm;
330 
331    s->blockNo           = 0;
332    s->state             = BZ_S_INPUT;
333    s->mode              = BZ_M_RUNNING;
334    s->combinedCRC       = 0;
335    s->nblockMAX         = 100000 * s->blockSize100k - 19;
336 
337    s->block             = (UChar*)s->arr2;
338    s->mtfv              = (UInt16*)s->arr1;
339    s->zbits             = NULL;
340    s->ptr               = (UInt32*)s->arr1;
341 
342    strm->state          = s;
343    strm->total_in_lo32  = 0;
344    strm->total_in_hi32  = 0;
345    strm->total_out_lo32 = 0;
346    strm->total_out_hi32 = 0;
347    init_RL ( s );
348    prepare_new_block ( s );
349    return BZ_OK;
350 }
351 
352 
353 /*---------------------------------------------------*/
354 static
355 void add_pair_to_block ( EState* s )
356 {
357    Int32 i;
358    UChar ch = (UChar)(s->state_in_ch);
359    for (i = 0; i < s->state_in_len; i++) {
360       BZ_UPDATE_CRC( s->blockCRC, ch );
361    }
362    s->inUse[s->state_in_ch] = True;
363    switch (s->state_in_len) {
364       case 1:
365          s->block[s->nblock] = (UChar)ch; s->nblock++;
366          break;
367       case 2:
368          s->block[s->nblock] = (UChar)ch; s->nblock++;
369          s->block[s->nblock] = (UChar)ch; s->nblock++;
370          break;
371       case 3:
372          s->block[s->nblock] = (UChar)ch; s->nblock++;
373          s->block[s->nblock] = (UChar)ch; s->nblock++;
374          s->block[s->nblock] = (UChar)ch; s->nblock++;
375          break;
376       default:
377          s->inUse[s->state_in_len-4] = True;
378          s->block[s->nblock] = (UChar)ch; s->nblock++;
379          s->block[s->nblock] = (UChar)ch; s->nblock++;
380          s->block[s->nblock] = (UChar)ch; s->nblock++;
381          s->block[s->nblock] = (UChar)ch; s->nblock++;
382          s->block[s->nblock] = ((UChar)(s->state_in_len-4));
383          s->nblock++;
384          break;
385    }
386 }
387 
388 
389 /*---------------------------------------------------*/
390 static
391 void flush_RL ( EState* s )
392 {
393    if (s->state_in_ch < 256) add_pair_to_block ( s );
394    init_RL ( s );
395 }
396 
397 
398 /*---------------------------------------------------*/
399 #define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
400 {                                                 \
401    UInt32 zchh = (UInt32)(zchh0);                 \
402    /*-- fast track the common case --*/           \
403    if (zchh != zs->state_in_ch &&                 \
404        zs->state_in_len == 1) {                   \
405       UChar ch = (UChar)(zs->state_in_ch);        \
406       BZ_UPDATE_CRC( zs->blockCRC, ch );          \
407       zs->inUse[zs->state_in_ch] = True;          \
408       zs->block[zs->nblock] = (UChar)ch;          \
409       zs->nblock++;                               \
410       zs->state_in_ch = zchh;                     \
411    }                                              \
412    else                                           \
413    /*-- general, uncommon cases --*/              \
414    if (zchh != zs->state_in_ch ||                 \
415       zs->state_in_len == 255) {                  \
416       if (zs->state_in_ch < 256)                  \
417          add_pair_to_block ( zs );                \
418       zs->state_in_ch = zchh;                     \
419       zs->state_in_len = 1;                       \
420    } else {                                       \
421       zs->state_in_len++;                         \
422    }                                              \
423 }
424 
425 
426 /*---------------------------------------------------*/
427 static
428 Bool copy_input_until_stop ( EState* s )
429 {
430    Bool progress_in = False;
431 
432    if (s->mode == BZ_M_RUNNING) {
433 
434       /*-- fast track the common case --*/
435       while (True) {
436          /*-- block full? --*/
437          if (s->nblock >= s->nblockMAX) break;
438          /*-- no input? --*/
439          if (s->strm->avail_in == 0) break;
440          progress_in = True;
441          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
442          s->strm->next_in++;
443          s->strm->avail_in--;
444          s->strm->total_in_lo32++;
445          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
446       }
447 
448    } else {
449 
450       /*-- general, uncommon case --*/
451       while (True) {
452          /*-- block full? --*/
453          if (s->nblock >= s->nblockMAX) break;
454          /*-- no input? --*/
455          if (s->strm->avail_in == 0) break;
456          /*-- flush/finish end? --*/
457          if (s->avail_in_expect == 0) break;
458          progress_in = True;
459          ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
460          s->strm->next_in++;
461          s->strm->avail_in--;
462          s->strm->total_in_lo32++;
463          if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
464          s->avail_in_expect--;
465       }
466    }
467    return progress_in;
468 }
469 
470 
471 /*---------------------------------------------------*/
472 static
473 Bool copy_output_until_stop ( EState* s )
474 {
475    Bool progress_out = False;
476 
477    while (True) {
478 
479       /*-- no output space? --*/
480       if (s->strm->avail_out == 0) break;
481 
482       /*-- block done? --*/
483       if (s->state_out_pos >= s->numZ) break;
484 
485       progress_out = True;
486       *(s->strm->next_out) = s->zbits[s->state_out_pos];
487       s->state_out_pos++;
488       s->strm->avail_out--;
489       s->strm->next_out++;
490       s->strm->total_out_lo32++;
491       if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
492    }
493 
494    return progress_out;
495 }
496 
497 
498 /*---------------------------------------------------*/
499 static
500 Bool handle_compress ( bz_stream* strm )
501 {
502    Bool progress_in  = False;
503    Bool progress_out = False;
504    EState* s = strm->state;
505 
506    while (True) {
507 
508       if (s->state == BZ_S_OUTPUT) {
509          progress_out |= copy_output_until_stop ( s );
510          if (s->state_out_pos < s->numZ) break;
511          if (s->mode == BZ_M_FINISHING &&
512              s->avail_in_expect == 0 &&
513              isempty_RL(s)) break;
514          prepare_new_block ( s );
515          s->state = BZ_S_INPUT;
516          if (s->mode == BZ_M_FLUSHING &&
517              s->avail_in_expect == 0 &&
518              isempty_RL(s)) break;
519       }
520 
521       if (s->state == BZ_S_INPUT) {
522          progress_in |= copy_input_until_stop ( s );
523          if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
524             flush_RL ( s );
525             BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
526             s->state = BZ_S_OUTPUT;
527          }
528          else
529          if (s->nblock >= s->nblockMAX) {
530             BZ2_compressBlock ( s, False );
531             s->state = BZ_S_OUTPUT;
532          }
533          else
534          if (s->strm->avail_in == 0) {
535             break;
536          }
537       }
538 
539    }
540 
541    return progress_in || progress_out;
542 }
543 
544 
545 /*---------------------------------------------------*/
546 int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
547 {
548    Bool progress;
549    EState* s;
550    if (strm == NULL) return BZ_PARAM_ERROR;
551    s = strm->state;
552    if (s == NULL) return BZ_PARAM_ERROR;
553    if (s->strm != strm) return BZ_PARAM_ERROR;
554 
555    preswitch:
556    switch (s->mode) {
557 
558       case BZ_M_IDLE:
559          return BZ_SEQUENCE_ERROR;
560 
561       case BZ_M_RUNNING:
562          if (action == BZ_RUN) {
563             progress = handle_compress ( strm );
564             return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
565          }
566          else
567 	 if (action == BZ_FLUSH) {
568             s->avail_in_expect = strm->avail_in;
569             s->mode = BZ_M_FLUSHING;
570             goto preswitch;
571          }
572          else
573          if (action == BZ_FINISH) {
574             s->avail_in_expect = strm->avail_in;
575             s->mode = BZ_M_FINISHING;
576             goto preswitch;
577          }
578          else
579             return BZ_PARAM_ERROR;
580 
581       case BZ_M_FLUSHING:
582          if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
583          if (s->avail_in_expect != s->strm->avail_in)
584             return BZ_SEQUENCE_ERROR;
585          progress = handle_compress ( strm );
586          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
587              s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
588          s->mode = BZ_M_RUNNING;
589          return BZ_RUN_OK;
590 
591       case BZ_M_FINISHING:
592          if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
593          if (s->avail_in_expect != s->strm->avail_in)
594             return BZ_SEQUENCE_ERROR;
595          progress = handle_compress ( strm );
596          if (!progress) return BZ_SEQUENCE_ERROR;
597          if (s->avail_in_expect > 0 || !isempty_RL(s) ||
598              s->state_out_pos < s->numZ) return BZ_FINISH_OK;
599          s->mode = BZ_M_IDLE;
600          return BZ_STREAM_END;
601    }
602    return BZ_OK; /*--not reached--*/
603 }
604 
605 
606 /*---------------------------------------------------*/
607 int BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
608 {
609    EState* s;
610    if (strm == NULL) return BZ_PARAM_ERROR;
611    s = strm->state;
612    if (s == NULL) return BZ_PARAM_ERROR;
613    if (s->strm != strm) return BZ_PARAM_ERROR;
614 
615    if (s->arr1 != NULL) BZFREE(s->arr1);
616    if (s->arr2 != NULL) BZFREE(s->arr2);
617    if (s->ftab != NULL) BZFREE(s->ftab);
618    BZFREE(strm->state);
619 
620    strm->state = NULL;
621 
622    return BZ_OK;
623 }
624 
625 #endif /* BZ_NO_COMPRESS */
626 
627 /*---------------------------------------------------*/
628 /*--- Decompression stuff                         ---*/
629 /*---------------------------------------------------*/
630 
631 /*---------------------------------------------------*/
632 int BZ_API(BZ2_bzDecompressInit)
633                      ( bz_stream* strm,
634                        int        verbosity,
635                        int        small )
636 {
637    DState* s;
638 
639    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
640 
641    if (strm == NULL) return BZ_PARAM_ERROR;
642    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
643    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
644 
645    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
646    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
647 
648    s = BZALLOC( sizeof(DState) );
649    if (s == NULL) return BZ_MEM_ERROR;
650    s->strm                  = strm;
651    strm->state              = s;
652    s->state                 = BZ_X_MAGIC_1;
653    s->bsLive                = 0;
654    s->bsBuff                = 0;
655    s->calculatedCombinedCRC = 0;
656    strm->total_in_lo32      = 0;
657    strm->total_in_hi32      = 0;
658    strm->total_out_lo32     = 0;
659    strm->total_out_hi32     = 0;
660    s->smallDecompress       = (Bool)small;
661    s->ll4                   = NULL;
662    s->ll16                  = NULL;
663    s->tt                    = NULL;
664    s->currBlockNo           = 0;
665    s->verbosity             = verbosity;
666 
667    return BZ_OK;
668 }
669 
670 /*---------------------------------------------------*/
671 /*
672  * added to allow reuse of bz_stream without malloc/free
673  */
674 int BZ_API(BZ2_bzDecompressReset) ( bz_stream* strm )
675 {
676    DState* s;
677 
678    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
679 
680    if (strm == NULL) return BZ_PARAM_ERROR;
681 
682    s = strm->state;
683    s->strm                  = strm;
684 
685    s->state                 = BZ_X_MAGIC_1;
686    s->bsLive                = 0;
687    s->bsBuff                = 0;
688    s->calculatedCombinedCRC = 0;
689    strm->total_in_lo32      = 0;
690    strm->total_in_hi32      = 0;
691    strm->total_out_lo32     = 0;
692    strm->total_out_hi32     = 0;
693 
694    s->ll4                   = NULL;
695    s->ll16                  = NULL;
696    s->tt                    = NULL;
697    s->currBlockNo           = 0;
698 
699 
700    return BZ_OK;
701 }
702 
703 
704 /*---------------------------------------------------*/
705 /* Return  True iff data corruption is discovered.
706    Returns False if there is no problem.
707 */
708 static
709 Bool unRLE_obuf_to_output_FAST ( DState* s )
710 {
711    UChar k1;
712 
713    if (s->blockRandomised) {
714 
715       while (True) {
716          /* try to finish existing run */
717          while (True) {
718             if (s->strm->avail_out == 0) return False;
719             if (s->state_out_len == 0) break;
720             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
721             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
722             s->state_out_len--;
723             s->strm->next_out++;
724             s->strm->avail_out--;
725             s->strm->total_out_lo32++;
726             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
727          }
728 
729          /* can a new run be started? */
730          if (s->nblock_used == s->save_nblock+1) return False;
731 
732          /* Only caused by corrupt data stream? */
733          if (s->nblock_used > s->save_nblock+1)
734             return True;
735 
736          s->state_out_len = 1;
737          s->state_out_ch = s->k0;
738          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
739          k1 ^= BZ_RAND_MASK; s->nblock_used++;
740          if (s->nblock_used == s->save_nblock+1) continue;
741          if (k1 != s->k0) { s->k0 = k1; continue; };
742 
743          s->state_out_len = 2;
744          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
745          k1 ^= BZ_RAND_MASK; s->nblock_used++;
746          if (s->nblock_used == s->save_nblock+1) continue;
747          if (k1 != s->k0) { s->k0 = k1; continue; };
748 
749          s->state_out_len = 3;
750          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
751          k1 ^= BZ_RAND_MASK; s->nblock_used++;
752          if (s->nblock_used == s->save_nblock+1) continue;
753          if (k1 != s->k0) { s->k0 = k1; continue; };
754 
755          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
756          k1 ^= BZ_RAND_MASK; s->nblock_used++;
757          s->state_out_len = ((Int32)k1) + 4;
758          BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
759          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
760       }
761 
762    } else {
763 
764       /* restore */
765       UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
766       UChar         c_state_out_ch       = s->state_out_ch;
767       Int32         c_state_out_len      = s->state_out_len;
768       Int32         c_nblock_used        = s->nblock_used;
769       Int32         c_k0                 = s->k0;
770       UInt32*       c_tt                 = s->tt;
771       UInt32        c_tPos               = s->tPos;
772       char*         cs_next_out          = s->strm->next_out;
773       unsigned int  cs_avail_out         = s->strm->avail_out;
774       Int32         ro_blockSize100k     = s->blockSize100k;
775       /* end restore */
776 
777       UInt32       avail_out_INIT = cs_avail_out;
778       Int32        s_save_nblockPP = s->save_nblock+1;
779       unsigned int total_out_lo32_old;
780 
781       while (True) {
782 
783          /* try to finish existing run */
784          if (c_state_out_len > 0) {
785             while (True) {
786                if (cs_avail_out == 0) goto return_notr;
787                if (c_state_out_len == 1) break;
788                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
789                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
790                c_state_out_len--;
791                cs_next_out++;
792                cs_avail_out--;
793             }
794             s_state_out_len_eq_one:
795             {
796                if (cs_avail_out == 0) {
797                   c_state_out_len = 1; goto return_notr;
798                };
799                *( (UChar*)(cs_next_out) ) = c_state_out_ch;
800                BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
801                cs_next_out++;
802                cs_avail_out--;
803             }
804          }
805          /* Only caused by corrupt data stream? */
806          if (c_nblock_used > s_save_nblockPP)
807             return True;
808 
809          /* can a new run be started? */
810          if (c_nblock_used == s_save_nblockPP) {
811             c_state_out_len = 0; goto return_notr;
812          };
813          c_state_out_ch = c_k0;
814          BZ_GET_FAST_C(k1); c_nblock_used++;
815          if (k1 != c_k0) {
816             c_k0 = k1; goto s_state_out_len_eq_one;
817          };
818          if (c_nblock_used == s_save_nblockPP)
819             goto s_state_out_len_eq_one;
820 
821          c_state_out_len = 2;
822          BZ_GET_FAST_C(k1); c_nblock_used++;
823          if (c_nblock_used == s_save_nblockPP) continue;
824          if (k1 != c_k0) { c_k0 = k1; continue; };
825 
826          c_state_out_len = 3;
827          BZ_GET_FAST_C(k1); c_nblock_used++;
828          if (c_nblock_used == s_save_nblockPP) continue;
829          if (k1 != c_k0) { c_k0 = k1; continue; };
830 
831          BZ_GET_FAST_C(k1); c_nblock_used++;
832          c_state_out_len = ((Int32)k1) + 4;
833          BZ_GET_FAST_C(c_k0); c_nblock_used++;
834       }
835 
836       return_notr:
837       total_out_lo32_old = s->strm->total_out_lo32;
838       s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
839       if (s->strm->total_out_lo32 < total_out_lo32_old)
840          s->strm->total_out_hi32++;
841 
842       /* save */
843       s->calculatedBlockCRC = c_calculatedBlockCRC;
844       s->state_out_ch       = c_state_out_ch;
845       s->state_out_len      = c_state_out_len;
846       s->nblock_used        = c_nblock_used;
847       s->k0                 = c_k0;
848       s->tt                 = c_tt;
849       s->tPos               = c_tPos;
850       s->strm->next_out     = cs_next_out;
851       s->strm->avail_out    = cs_avail_out;
852       /* end save */
853    }
854    return False;
855 }
856 
857 
858 
859 /*---------------------------------------------------*/
860 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
861 {
862    Int32 nb, na, mid;
863    nb = 0;
864    na = 256;
865    do {
866       mid = (nb + na) >> 1;
867       if (indx >= cftab[mid]) nb = mid; else na = mid;
868    }
869    while (na - nb != 1);
870    return nb;
871 }
872 
873 
874 /*---------------------------------------------------*/
875 /* Return  True iff data corruption is discovered.
876    Returns False if there is no problem.
877 */
878 static
879 Bool unRLE_obuf_to_output_SMALL ( DState* s )
880 {
881    UChar k1;
882 
883    if (s->blockRandomised) {
884 
885       while (True) {
886          /* try to finish existing run */
887          while (True) {
888             if (s->strm->avail_out == 0) return False;
889             if (s->state_out_len == 0) break;
890             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
891             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
892             s->state_out_len--;
893             s->strm->next_out++;
894             s->strm->avail_out--;
895             s->strm->total_out_lo32++;
896             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
897          }
898 
899          /* can a new run be started? */
900          if (s->nblock_used == s->save_nblock+1) return False;
901 
902          /* Only caused by corrupt data stream? */
903          if (s->nblock_used > s->save_nblock+1)
904             return True;
905 
906          s->state_out_len = 1;
907          s->state_out_ch = s->k0;
908          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
909          k1 ^= BZ_RAND_MASK; s->nblock_used++;
910          if (s->nblock_used == s->save_nblock+1) continue;
911          if (k1 != s->k0) { s->k0 = k1; continue; };
912 
913          s->state_out_len = 2;
914          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
915          k1 ^= BZ_RAND_MASK; s->nblock_used++;
916          if (s->nblock_used == s->save_nblock+1) continue;
917          if (k1 != s->k0) { s->k0 = k1; continue; };
918 
919          s->state_out_len = 3;
920          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
921          k1 ^= BZ_RAND_MASK; s->nblock_used++;
922          if (s->nblock_used == s->save_nblock+1) continue;
923          if (k1 != s->k0) { s->k0 = k1; continue; };
924 
925          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
926          k1 ^= BZ_RAND_MASK; s->nblock_used++;
927          s->state_out_len = ((Int32)k1) + 4;
928          BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
929          s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
930       }
931 
932    } else {
933 
934       while (True) {
935          /* try to finish existing run */
936          while (True) {
937             if (s->strm->avail_out == 0) return False;
938             if (s->state_out_len == 0) break;
939             *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
940             BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
941             s->state_out_len--;
942             s->strm->next_out++;
943             s->strm->avail_out--;
944             s->strm->total_out_lo32++;
945             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
946          }
947 
948          /* can a new run be started? */
949          if (s->nblock_used == s->save_nblock+1) return False;
950 
951          /* Only caused by corrupt data stream? */
952          if (s->nblock_used > s->save_nblock+1)
953             return True;
954 
955          s->state_out_len = 1;
956          s->state_out_ch = s->k0;
957          BZ_GET_SMALL(k1); s->nblock_used++;
958          if (s->nblock_used == s->save_nblock+1) continue;
959          if (k1 != s->k0) { s->k0 = k1; continue; };
960 
961          s->state_out_len = 2;
962          BZ_GET_SMALL(k1); s->nblock_used++;
963          if (s->nblock_used == s->save_nblock+1) continue;
964          if (k1 != s->k0) { s->k0 = k1; continue; };
965 
966          s->state_out_len = 3;
967          BZ_GET_SMALL(k1); s->nblock_used++;
968          if (s->nblock_used == s->save_nblock+1) continue;
969          if (k1 != s->k0) { s->k0 = k1; continue; };
970 
971          BZ_GET_SMALL(k1); s->nblock_used++;
972          s->state_out_len = ((Int32)k1) + 4;
973          BZ_GET_SMALL(s->k0); s->nblock_used++;
974       }
975 
976    }
977 }
978 
979 
980 /*---------------------------------------------------*/
981 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
982 {
983    Bool    corrupt;
984    DState* s;
985    if (strm == NULL) return BZ_PARAM_ERROR;
986    s = strm->state;
987    if (s == NULL) return BZ_PARAM_ERROR;
988    if (s->strm != strm) return BZ_PARAM_ERROR;
989 
990    while (True) {
991       if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
992       if (s->state == BZ_X_OUTPUT) {
993          if (s->smallDecompress)
994             corrupt = unRLE_obuf_to_output_SMALL ( s ); else
995             corrupt = unRLE_obuf_to_output_FAST  ( s );
996          if (corrupt) return BZ_DATA_ERROR;
997          if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
998             BZ_FINALISE_CRC ( s->calculatedBlockCRC );
999             if (s->verbosity >= 3)
1000                VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
1001                           s->calculatedBlockCRC );
1002             if (s->verbosity >= 2) VPrintf0 ( "]" );
1003             if (s->calculatedBlockCRC != s->storedBlockCRC)
1004                return BZ_DATA_ERROR;
1005             s->calculatedCombinedCRC
1006                = (s->calculatedCombinedCRC << 1) |
1007                     (s->calculatedCombinedCRC >> 31);
1008             s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
1009             s->state = BZ_X_BLKHDR_1;
1010          } else {
1011             return BZ_OK;
1012          }
1013       }
1014       if (s->state >= BZ_X_MAGIC_1) {
1015          Int32 r = BZ2_decompress ( s );
1016          if (r == BZ_STREAM_END) {
1017             if (s->verbosity >= 3)
1018                VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x",
1019                           s->storedCombinedCRC, s->calculatedCombinedCRC );
1020             if (s->calculatedCombinedCRC != s->storedCombinedCRC)
1021                return BZ_DATA_ERROR;
1022             return r;
1023          }
1024          if (s->state != BZ_X_OUTPUT) return r;
1025       }
1026    }
1027 
1028 #if 0
1029    AssertH ( 0, 6001 );
1030 
1031    return 0;  /*NOTREACHED*/
1032 #endif
1033 }
1034 
1035 
1036 /*---------------------------------------------------*/
1037 int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
1038 {
1039    DState* s;
1040    if (strm == NULL) return BZ_PARAM_ERROR;
1041    s = strm->state;
1042    if (s == NULL) return BZ_PARAM_ERROR;
1043    if (s->strm != strm) return BZ_PARAM_ERROR;
1044 
1045    if (s->tt   != NULL) BZFREE(s->tt);
1046    if (s->ll16 != NULL) BZFREE(s->ll16);
1047    if (s->ll4  != NULL) BZFREE(s->ll4);
1048 
1049    BZFREE(strm->state);
1050    strm->state = NULL;
1051 
1052    return BZ_OK;
1053 }
1054 
1055 #ifndef BZ_NO_COMPRESS
1056 
1057 #ifndef BZ_NO_STDIO
1058 /*---------------------------------------------------*/
1059 /*--- File I/O stuff                              ---*/
1060 /*---------------------------------------------------*/
1061 
1062 #define BZ_SETERR(eee)                    \
1063 {                                         \
1064    if (bzerror != NULL) *bzerror = eee;   \
1065    if (bzf != NULL) bzf->lastErr = eee;   \
1066 }
1067 
1068 typedef
1069    struct {
1070       FILE*     handle;
1071       Char      buf[BZ_MAX_UNUSED];
1072       Int32     bufN;
1073       Bool      writing;
1074       bz_stream strm;
1075       Int32     lastErr;
1076       Bool      initialisedOk;
1077    }
1078    bzFile;
1079 
1080 
1081 /*---------------------------------------------*/
1082 static Bool myfeof ( FILE* f )
1083 {
1084    Int32 c = fgetc ( f );
1085    if (c == EOF) return True;
1086    ungetc ( c, f );
1087    return False;
1088 }
1089 
1090 
1091 /*---------------------------------------------------*/
1092 BZFILE* BZ_API(BZ2_bzWriteOpen)
1093                     ( int*  bzerror,
1094                       FILE* f,
1095                       int   blockSize100k,
1096                       int   verbosity,
1097                       int   workFactor )
1098 {
1099    Int32   ret;
1100    bzFile* bzf = NULL;
1101 
1102    BZ_SETERR(BZ_OK);
1103 
1104    if (f == NULL ||
1105        (blockSize100k < 1 || blockSize100k > 9) ||
1106        (workFactor < 0 || workFactor > 250) ||
1107        (verbosity < 0 || verbosity > 4))
1108       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1109 
1110    if (ferror(f))
1111       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1112 
1113    bzf = malloc ( sizeof(bzFile) );
1114    if (bzf == NULL)
1115       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1116 
1117    BZ_SETERR(BZ_OK);
1118    bzf->initialisedOk = False;
1119    bzf->bufN          = 0;
1120    bzf->handle        = f;
1121    bzf->writing       = True;
1122    bzf->strm.bzalloc  = NULL;
1123    bzf->strm.bzfree   = NULL;
1124    bzf->strm.opaque   = NULL;
1125 
1126    if (workFactor == 0) workFactor = 30;
1127    ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
1128                               verbosity, workFactor );
1129    if (ret != BZ_OK)
1130       { BZ_SETERR(ret); free(bzf); return NULL; };
1131 
1132    bzf->strm.avail_in = 0;
1133    bzf->initialisedOk = True;
1134    return bzf;
1135 }
1136 
1137 
1138 
1139 /*---------------------------------------------------*/
1140 void BZ_API(BZ2_bzWrite)
1141              ( int*    bzerror,
1142                BZFILE* b,
1143                void*   buf,
1144                int     len )
1145 {
1146    Int32 n, n2, ret;
1147    bzFile* bzf = (bzFile*)b;
1148 
1149    BZ_SETERR(BZ_OK);
1150    if (bzf == NULL || buf == NULL || len < 0)
1151       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1152    if (!(bzf->writing))
1153       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1154    if (ferror(bzf->handle))
1155       { BZ_SETERR(BZ_IO_ERROR); return; };
1156 
1157    if (len == 0)
1158       { BZ_SETERR(BZ_OK); return; };
1159 
1160    bzf->strm.avail_in = len;
1161    bzf->strm.next_in  = buf;
1162 
1163    while (True) {
1164       bzf->strm.avail_out = BZ_MAX_UNUSED;
1165       bzf->strm.next_out = bzf->buf;
1166       ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1167       if (ret != BZ_RUN_OK)
1168          { BZ_SETERR(ret); return; };
1169 
1170       if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1171          n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1172          n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1173                        n, bzf->handle );
1174          if (n != n2 || ferror(bzf->handle))
1175             { BZ_SETERR(BZ_IO_ERROR); return; };
1176       }
1177 
1178       if (bzf->strm.avail_in == 0)
1179          { BZ_SETERR(BZ_OK); return; };
1180    }
1181 }
1182 
1183 
1184 /*---------------------------------------------------*/
1185 void BZ_API(BZ2_bzWriteClose)
1186                   ( int*          bzerror,
1187                     BZFILE*       b,
1188                     int           abandon,
1189                     unsigned int* nbytes_in,
1190                     unsigned int* nbytes_out )
1191 {
1192    BZ2_bzWriteClose64 ( bzerror, b, abandon,
1193                         nbytes_in, NULL, nbytes_out, NULL );
1194 }
1195 
1196 
1197 void BZ_API(BZ2_bzWriteClose64)
1198                   ( int*          bzerror,
1199                     BZFILE*       b,
1200                     int           abandon,
1201                     unsigned int* nbytes_in_lo32,
1202                     unsigned int* nbytes_in_hi32,
1203                     unsigned int* nbytes_out_lo32,
1204                     unsigned int* nbytes_out_hi32 )
1205 {
1206    Int32   n, n2, ret;
1207    bzFile* bzf = (bzFile*)b;
1208 
1209    if (bzf == NULL)
1210       { BZ_SETERR(BZ_OK); return; };
1211    if (!(bzf->writing))
1212       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1213    if (ferror(bzf->handle))
1214       { BZ_SETERR(BZ_IO_ERROR); return; };
1215 
1216    if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1217    if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1218    if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1219    if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1220 
1221    if ((!abandon) && bzf->lastErr == BZ_OK) {
1222       while (True) {
1223          bzf->strm.avail_out = BZ_MAX_UNUSED;
1224          bzf->strm.next_out = bzf->buf;
1225          ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1226          if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1227             { BZ_SETERR(ret); return; };
1228 
1229          if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1230             n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1231             n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1232                           n, bzf->handle );
1233             if (n != n2 || ferror(bzf->handle))
1234                { BZ_SETERR(BZ_IO_ERROR); return; };
1235          }
1236 
1237          if (ret == BZ_STREAM_END) break;
1238       }
1239    }
1240 
1241    if ( !abandon && !ferror ( bzf->handle ) ) {
1242       fflush ( bzf->handle );
1243       if (ferror(bzf->handle))
1244          { BZ_SETERR(BZ_IO_ERROR); return; };
1245    }
1246 
1247    if (nbytes_in_lo32 != NULL)
1248       *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1249    if (nbytes_in_hi32 != NULL)
1250       *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1251    if (nbytes_out_lo32 != NULL)
1252       *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1253    if (nbytes_out_hi32 != NULL)
1254       *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1255 
1256    BZ_SETERR(BZ_OK);
1257    (void) BZ2_bzCompressEnd ( &(bzf->strm) );
1258    free ( bzf );
1259 }
1260 
1261 
1262 /*---------------------------------------------------*/
1263 BZFILE* BZ_API(BZ2_bzReadOpen)
1264                    ( int*  bzerror,
1265                      FILE* f,
1266                      int   verbosity,
1267                      int   small,
1268                      void* unused,
1269                      int   nUnused )
1270 {
1271    bzFile* bzf = NULL;
1272    int     ret;
1273 
1274    BZ_SETERR(BZ_OK);
1275 
1276    if (f == NULL ||
1277        (small != 0 && small != 1) ||
1278        (verbosity < 0 || verbosity > 4) ||
1279        (unused == NULL && nUnused != 0) ||
1280        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1281       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1282 
1283    if (ferror(f))
1284       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1285 
1286    bzf = malloc ( sizeof(bzFile) );
1287    if (bzf == NULL)
1288       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1289 
1290    BZ_SETERR(BZ_OK);
1291 
1292    bzf->initialisedOk = False;
1293    bzf->handle        = f;
1294    bzf->bufN          = 0;
1295    bzf->writing       = False;
1296    bzf->strm.bzalloc  = NULL;
1297    bzf->strm.bzfree   = NULL;
1298    bzf->strm.opaque   = NULL;
1299 
1300    while (nUnused > 0) {
1301       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1302       unused = ((void*)( 1 + ((UChar*)(unused))  ));
1303       nUnused--;
1304    }
1305 
1306    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1307    if (ret != BZ_OK)
1308       { BZ_SETERR(ret); free(bzf); return NULL; };
1309 
1310    bzf->strm.avail_in = bzf->bufN;
1311    bzf->strm.next_in  = bzf->buf;
1312 
1313    bzf->initialisedOk = True;
1314    return bzf;
1315 }
1316 
1317 
1318 /*---------------------------------------------------*/
1319 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1320 {
1321    bzFile* bzf = (bzFile*)b;
1322 
1323    BZ_SETERR(BZ_OK);
1324    if (bzf == NULL)
1325       { BZ_SETERR(BZ_OK); return; };
1326 
1327    if (bzf->writing)
1328       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1329 
1330    if (bzf->initialisedOk)
1331       (void) BZ2_bzDecompressEnd ( &(bzf->strm) );
1332    free ( bzf );
1333 }
1334 
1335 
1336 /*---------------------------------------------------*/
1337 int BZ_API(BZ2_bzRead)
1338            ( int*    bzerror,
1339              BZFILE* b,
1340              void*   buf,
1341              int     len )
1342 {
1343    Int32   n, ret;
1344    bzFile* bzf = (bzFile*)b;
1345 
1346    BZ_SETERR(BZ_OK);
1347 
1348    if (bzf == NULL || buf == NULL || len < 0)
1349       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1350 
1351    if (bzf->writing)
1352       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1353 
1354    if (len == 0)
1355       { BZ_SETERR(BZ_OK); return 0; };
1356 
1357    bzf->strm.avail_out = len;
1358    bzf->strm.next_out = buf;
1359 
1360    while (True) {
1361 
1362       if (ferror(bzf->handle))
1363          { BZ_SETERR(BZ_IO_ERROR); return 0; };
1364 
1365       if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1366          n = fread ( bzf->buf, sizeof(UChar),
1367                      BZ_MAX_UNUSED, bzf->handle );
1368          if (ferror(bzf->handle))
1369             { BZ_SETERR(BZ_IO_ERROR); return 0; };
1370          bzf->bufN = n;
1371          bzf->strm.avail_in = bzf->bufN;
1372          bzf->strm.next_in = bzf->buf;
1373       }
1374 
1375       ret = BZ2_bzDecompress ( &(bzf->strm) );
1376 
1377       if (ret != BZ_OK && ret != BZ_STREAM_END)
1378          { BZ_SETERR(ret); return 0; };
1379 
1380       if (ret == BZ_OK && myfeof(bzf->handle) &&
1381           bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1382          { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1383 
1384       if (ret == BZ_STREAM_END)
1385          { BZ_SETERR(BZ_STREAM_END);
1386            return len - bzf->strm.avail_out; };
1387       if (bzf->strm.avail_out == 0)
1388          { BZ_SETERR(BZ_OK); return len; };
1389 
1390    }
1391 
1392    return 0; /*not reached*/
1393 }
1394 
1395 
1396 /*---------------------------------------------------*/
1397 void BZ_API(BZ2_bzReadGetUnused)
1398                      ( int*    bzerror,
1399                        BZFILE* b,
1400                        void**  unused,
1401                        int*    nUnused )
1402 {
1403    bzFile* bzf = (bzFile*)b;
1404    if (bzf == NULL)
1405       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1406    if (bzf->lastErr != BZ_STREAM_END)
1407       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1408    if (unused == NULL || nUnused == NULL)
1409       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1410 
1411    BZ_SETERR(BZ_OK);
1412    *nUnused = bzf->strm.avail_in;
1413    *unused = bzf->strm.next_in;
1414 }
1415 #endif
1416 
1417 
1418 /*---------------------------------------------------*/
1419 /*--- Misc convenience stuff                      ---*/
1420 /*---------------------------------------------------*/
1421 
1422 /*---------------------------------------------------*/
1423 int BZ_API(BZ2_bzBuffToBuffCompress)
1424                          ( char*         dest,
1425                            unsigned int* destLen,
1426                            char*         source,
1427                            unsigned int  sourceLen,
1428                            int           blockSize100k,
1429                            int           verbosity,
1430                            int           workFactor )
1431 {
1432    bz_stream strm;
1433    int ret;
1434 
1435    if (dest == NULL || destLen == NULL ||
1436        source == NULL ||
1437        blockSize100k < 1 || blockSize100k > 9 ||
1438        verbosity < 0 || verbosity > 4 ||
1439        workFactor < 0 || workFactor > 250)
1440       return BZ_PARAM_ERROR;
1441 
1442    if (workFactor == 0) workFactor = 30;
1443    strm.bzalloc = NULL;
1444    strm.bzfree = NULL;
1445    strm.opaque = NULL;
1446    ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1447                               verbosity, workFactor );
1448    if (ret != BZ_OK) return ret;
1449 
1450    strm.next_in = source;
1451    strm.next_out = dest;
1452    strm.avail_in = sourceLen;
1453    strm.avail_out = *destLen;
1454 
1455    ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1456    if (ret == BZ_FINISH_OK) goto output_overflow;
1457    if (ret != BZ_STREAM_END) goto errhandler;
1458 
1459    /* normal termination */
1460    *destLen -= strm.avail_out;
1461    (void) BZ2_bzCompressEnd ( &strm );
1462    return BZ_OK;
1463 
1464    output_overflow:
1465    (void) BZ2_bzCompressEnd ( &strm );
1466    return BZ_OUTBUFF_FULL;
1467 
1468    errhandler:
1469    (void) BZ2_bzCompressEnd ( &strm );
1470    return ret;
1471 }
1472 
1473 
1474 /*---------------------------------------------------*/
1475 int BZ_API(BZ2_bzBuffToBuffDecompress)
1476                            ( char*         dest,
1477                              unsigned int* destLen,
1478                              char*         source,
1479                              unsigned int  sourceLen,
1480                              int           small,
1481                              int           verbosity )
1482 {
1483    bz_stream strm;
1484    int ret;
1485 
1486    if (dest == NULL || destLen == NULL ||
1487        source == NULL ||
1488        (small != 0 && small != 1) ||
1489        verbosity < 0 || verbosity > 4)
1490           return BZ_PARAM_ERROR;
1491 
1492    strm.bzalloc = NULL;
1493    strm.bzfree = NULL;
1494    strm.opaque = NULL;
1495    ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1496    if (ret != BZ_OK) return ret;
1497 
1498    strm.next_in = source;
1499    strm.next_out = dest;
1500    strm.avail_in = sourceLen;
1501    strm.avail_out = *destLen;
1502 
1503    ret = BZ2_bzDecompress ( &strm );
1504    if (ret == BZ_OK) goto output_overflow_or_eof;
1505    if (ret != BZ_STREAM_END) goto errhandler;
1506 
1507    /* normal termination */
1508    *destLen -= strm.avail_out;
1509    (void) BZ2_bzDecompressEnd ( &strm );
1510    return BZ_OK;
1511 
1512    output_overflow_or_eof:
1513    if (strm.avail_out > 0) {
1514       (void) BZ2_bzDecompressEnd ( &strm );
1515       return BZ_UNEXPECTED_EOF;
1516    } else {
1517       (void) BZ2_bzDecompressEnd ( &strm );
1518       return BZ_OUTBUFF_FULL;
1519    }
1520 
1521    errhandler:
1522    (void) BZ2_bzDecompressEnd ( &strm );
1523    return ret;
1524 }
1525 
1526 
1527 /*---------------------------------------------------*/
1528 /*--
1529    Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1530    to support better zlib compatibility.
1531    This code is not _officially_ part of libbzip2 (yet);
1532    I haven't tested it, documented it, or considered the
1533    threading-safeness of it.
1534    If this code breaks, please contact both Yoshioka and me.
1535 --*/
1536 /*---------------------------------------------------*/
1537 
1538 /*---------------------------------------------------*/
1539 /*--
1540    return version like "0.9.5d, 4-Sept-1999".
1541 --*/
1542 const char * BZ_API(BZ2_bzlibVersion)(void)
1543 {
1544    return BZ_VERSION;
1545 }
1546 
1547 
1548 #ifndef BZ_NO_STDIO
1549 /*---------------------------------------------------*/
1550 
1551 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1552 #   include <fcntl.h>
1553 #   include <io.h>
1554 #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1555 #else
1556 #   define SET_BINARY_MODE(file)
1557 #endif
1558 static
1559 BZFILE * bzopen_or_bzdopen
1560                ( const char *path,   /* no use when bzdopen */
1561                  int fd,             /* no use when bzdopen */
1562                  const char *mode,
1563                  int open_mode)      /* bzopen: 0, bzdopen:1 */
1564 {
1565    int    bzerr;
1566    char   unused[BZ_MAX_UNUSED];
1567    int    blockSize100k = 9;
1568    int    writing       = 0;
1569    char   mode2[10]     = "";
1570    FILE   *fp           = NULL;
1571    BZFILE *bzfp         = NULL;
1572    int    verbosity     = 0;
1573    int    workFactor    = 30;
1574    int    smallMode     = 0;
1575    int    nUnused       = 0;
1576 
1577    if (mode == NULL) return NULL;
1578    while (*mode) {
1579       switch (*mode) {
1580       case 'r':
1581          writing = 0; break;
1582       case 'w':
1583          writing = 1; break;
1584       case 's':
1585          smallMode = 1; break;
1586       default:
1587          if (isdigit((int)(*mode))) {
1588             blockSize100k = *mode-BZ_HDR_0;
1589          }
1590       }
1591       mode++;
1592    }
1593    strcat(mode2, writing ? "w" : "r" );
1594    strcat(mode2,"b");   /* binary mode */
1595 
1596    if (open_mode==0) {
1597       if (path==NULL || strcmp(path,"")==0) {
1598         fp = (writing ? stdout : stdin);
1599         SET_BINARY_MODE(fp);
1600       } else {
1601         fp = fopen(path,mode2);
1602       }
1603    } else {
1604 #ifdef BZ_STRICT_ANSI
1605       fp = NULL;
1606 #else
1607       fp = fdopen(fd,mode2);
1608 #endif
1609    }
1610    if (fp == NULL) return NULL;
1611 
1612    if (writing) {
1613       /* Guard against total chaos and anarchy -- JRS */
1614       if (blockSize100k < 1) blockSize100k = 1;
1615       if (blockSize100k > 9) blockSize100k = 9;
1616       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1617                              verbosity,workFactor);
1618    } else {
1619       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1620                             unused,nUnused);
1621    }
1622    if (bzfp == NULL) {
1623       if (fp != stdin && fp != stdout) fclose(fp);
1624       return NULL;
1625    }
1626    return bzfp;
1627 }
1628 
1629 
1630 /*---------------------------------------------------*/
1631 /*--
1632    open file for read or write.
1633       ex) bzopen("file","w9")
1634       case path="" or NULL => use stdin or stdout.
1635 --*/
1636 BZFILE * BZ_API(BZ2_bzopen)
1637                ( const char *path,
1638                  const char *mode )
1639 {
1640    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1641 }
1642 
1643 
1644 /*---------------------------------------------------*/
1645 BZFILE * BZ_API(BZ2_bzdopen)
1646                ( int fd,
1647                  const char *mode )
1648 {
1649    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1650 }
1651 
1652 
1653 /*---------------------------------------------------*/
1654 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1655 {
1656    int bzerr, nread;
1657    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1658    nread = BZ2_bzRead(&bzerr,b,buf,len);
1659    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1660       return nread;
1661    } else {
1662       return -1;
1663    }
1664 }
1665 
1666 
1667 /*---------------------------------------------------*/
1668 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1669 {
1670    int bzerr;
1671 
1672    BZ2_bzWrite(&bzerr,b,buf,len);
1673    if(bzerr == BZ_OK){
1674       return len;
1675    }else{
1676       return -1;
1677    }
1678 }
1679 
1680 
1681 /*---------------------------------------------------*/
1682 int BZ_API(BZ2_bzflush) (BZFILE *b)
1683 {
1684    /* do nothing now... */
1685    return 0;
1686 }
1687 
1688 
1689 /*---------------------------------------------------*/
1690 void BZ_API(BZ2_bzclose) (BZFILE* b)
1691 {
1692    int bzerr;
1693    FILE *fp;
1694 
1695    if (b==NULL) {return;}
1696    fp = ((bzFile *)b)->handle;
1697    if(((bzFile*)b)->writing){
1698       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1699       if(bzerr != BZ_OK){
1700          BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1701       }
1702    }else{
1703       BZ2_bzReadClose(&bzerr,b);
1704    }
1705    if(fp!=stdin && fp!=stdout){
1706       fclose(fp);
1707    }
1708 }
1709 
1710 
1711 /*---------------------------------------------------*/
1712 /*--
1713    return last error code
1714 --*/
1715 static const char *bzerrorstrings[] = {
1716        "OK"
1717       ,"SEQUENCE_ERROR"
1718       ,"PARAM_ERROR"
1719       ,"MEM_ERROR"
1720       ,"DATA_ERROR"
1721       ,"DATA_ERROR_MAGIC"
1722       ,"IO_ERROR"
1723       ,"UNEXPECTED_EOF"
1724       ,"OUTBUFF_FULL"
1725       ,"CONFIG_ERROR"
1726       ,"???"   /* for future */
1727       ,"???"   /* for future */
1728       ,"???"   /* for future */
1729       ,"???"   /* for future */
1730       ,"???"   /* for future */
1731       ,"???"   /* for future */
1732 };
1733 
1734 
1735 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1736 {
1737    int err = ((bzFile *)b)->lastErr;
1738 
1739    if(err>0) err = 0;
1740    *errnum = err;
1741    return bzerrorstrings[err*-1];
1742 }
1743 #endif
1744 
1745 #endif /* BZ_NO_COMPRESS */
1746 
1747 /*-------------------------------------------------------------*/
1748 /*--- end                                           bzlib.c ---*/
1749 /*-------------------------------------------------------------*/
1750