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