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