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