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