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