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