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