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     /*NOTREACHED*/
863 }
864 
865 
866 /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressEnd)867 int BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
868 {
869    DState* s;
870    if (strm == NULL) return BZ_PARAM_ERROR;
871    s = (DState*) strm->state;
872    if (s == NULL) return BZ_PARAM_ERROR;
873    if (s->strm != strm) return BZ_PARAM_ERROR;
874 
875    if (s->tt   != NULL) BZFREE(s->tt);
876    if (s->ll16 != NULL) BZFREE(s->ll16);
877    if (s->ll4  != NULL) BZFREE(s->ll4);
878 
879    BZFREE(strm->state);
880    strm->state = NULL;
881 
882    return BZ_OK;
883 }
884 
885 
886 #ifndef BZ_NO_STDIO
887 /*---------------------------------------------------*/
888 /*--- File I/O stuff                              ---*/
889 /*---------------------------------------------------*/
890 
891 #define BZ_SETERR(eee)                    \
892 {                                         \
893    if (bzerror != NULL) *bzerror = eee;   \
894    if (bzf != NULL) bzf->lastErr = eee;   \
895 }
896 
897 typedef
898    struct {
899       FILE*     handle;
900       Char      buf[BZ_MAX_UNUSED];
901       Int32     bufN;
902       Bool      writing;
903       bz_stream strm;
904       Int32     lastErr;
905       Bool      initialisedOk;
906    }
907    bzFile;
908 
909 
910 /*---------------------------------------------*/
myfeof(FILE * f)911 static Bool myfeof ( FILE* f )
912 {
913    Int32 c = fgetc ( f );
914    if (c == EOF) return True;
915    ungetc ( c, f );
916    return False;
917 }
918 
919 
920 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteOpen)921 BZFILE* BZ_API(BZ2_bzWriteOpen)
922                     ( int*  bzerror,
923                       FILE* f,
924                       int   blockSize100k,
925                       int   verbosity,
926                       int   workFactor )
927 {
928    Int32   ret;
929    bzFile* bzf = NULL;
930 
931    BZ_SETERR(BZ_OK);
932 
933    if (f == NULL ||
934        (blockSize100k < 1 || blockSize100k > 9) ||
935        (workFactor < 0 || workFactor > 250) ||
936        (verbosity < 0 || verbosity > 4))
937       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
938 
939    if (ferror(f))
940       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
941 
942    bzf = (bzFile*) malloc ( sizeof(bzFile) );
943    if (bzf == NULL)
944       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
945 
946    BZ_SETERR(BZ_OK);
947    bzf->initialisedOk = False;
948    bzf->bufN          = 0;
949    bzf->handle        = f;
950    bzf->writing       = True;
951    bzf->strm.bzalloc  = NULL;
952    bzf->strm.bzfree   = NULL;
953    bzf->strm.opaque   = NULL;
954 
955    if (workFactor == 0) workFactor = 30;
956    ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
957                               verbosity, workFactor );
958    if (ret != BZ_OK)
959       { BZ_SETERR(ret); free(bzf); return NULL; };
960 
961    bzf->strm.avail_in = 0;
962    bzf->initialisedOk = True;
963    return bzf;
964 }
965 
966 
967 
968 /*---------------------------------------------------*/
BZ_API(BZ2_bzWrite)969 void BZ_API(BZ2_bzWrite)
970              ( int*    bzerror,
971                BZFILE* b,
972                void*   buf,
973                int     len )
974 {
975    Int32 n, n2, ret;
976    bzFile* bzf = (bzFile*)b;
977 
978    BZ_SETERR(BZ_OK);
979    if (bzf == NULL || buf == NULL || len < 0)
980       { BZ_SETERR(BZ_PARAM_ERROR); return; };
981    if (!(bzf->writing))
982       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
983    if (ferror(bzf->handle))
984       { BZ_SETERR(BZ_IO_ERROR); return; };
985 
986    if (len == 0)
987       { BZ_SETERR(BZ_OK); return; };
988 
989    bzf->strm.avail_in = len;
990    bzf->strm.next_in  = (char*)buf;
991 
992    while (True) {
993       bzf->strm.avail_out = BZ_MAX_UNUSED;
994       bzf->strm.next_out = bzf->buf;
995       ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
996       if (ret != BZ_RUN_OK)
997          { BZ_SETERR(ret); return; };
998 
999       if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1000          n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1001          n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1002                        n, bzf->handle );
1003          if (n != n2 || ferror(bzf->handle))
1004             { BZ_SETERR(BZ_IO_ERROR); return; };
1005       }
1006 
1007       if (bzf->strm.avail_in == 0)
1008          { BZ_SETERR(BZ_OK); return; };
1009    }
1010 }
1011 
1012 
1013 /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteClose)1014 void BZ_API(BZ2_bzWriteClose)
1015                   ( int*          bzerror,
1016                     BZFILE*       b,
1017                     int           abandon,
1018                     unsigned int* nbytes_in,
1019                     unsigned int* nbytes_out )
1020 {
1021    BZ2_bzWriteClose64 ( bzerror, b, abandon,
1022                         nbytes_in, NULL, nbytes_out, NULL );
1023 }
1024 
1025 
BZ_API(BZ2_bzWriteClose64)1026 void BZ_API(BZ2_bzWriteClose64)
1027                   ( int*          bzerror,
1028                     BZFILE*       b,
1029                     int           abandon,
1030                     unsigned int* nbytes_in_lo32,
1031                     unsigned int* nbytes_in_hi32,
1032                     unsigned int* nbytes_out_lo32,
1033                     unsigned int* nbytes_out_hi32 )
1034 {
1035    Int32   n, n2, ret;
1036    bzFile* bzf = (bzFile*)b;
1037 
1038    if (bzf == NULL)
1039       { BZ_SETERR(BZ_OK); return; };
1040    if (!(bzf->writing))
1041       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1042    if (ferror(bzf->handle))
1043       { BZ_SETERR(BZ_IO_ERROR); return; };
1044 
1045    if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1046    if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1047    if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1048    if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1049 
1050    if ((!abandon) && bzf->lastErr == BZ_OK) {
1051       while (True) {
1052          bzf->strm.avail_out = BZ_MAX_UNUSED;
1053          bzf->strm.next_out = bzf->buf;
1054          ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1055          if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1056             { BZ_SETERR(ret); return; };
1057 
1058          if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1059             n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1060             n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1061                           n, bzf->handle );
1062             if (n != n2 || ferror(bzf->handle))
1063                { BZ_SETERR(BZ_IO_ERROR); return; };
1064          }
1065 
1066          if (ret == BZ_STREAM_END) break;
1067       }
1068    }
1069 
1070    if ( !abandon && !ferror ( bzf->handle ) ) {
1071       fflush ( bzf->handle );
1072       if (ferror(bzf->handle))
1073          { BZ_SETERR(BZ_IO_ERROR); return; };
1074    }
1075 
1076    if (nbytes_in_lo32 != NULL)
1077       *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1078    if (nbytes_in_hi32 != NULL)
1079       *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1080    if (nbytes_out_lo32 != NULL)
1081       *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1082    if (nbytes_out_hi32 != NULL)
1083       *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1084 
1085    BZ_SETERR(BZ_OK);
1086    BZ2_bzCompressEnd ( &(bzf->strm) );
1087    free ( bzf );
1088 }
1089 
1090 
1091 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadOpen)1092 BZFILE* BZ_API(BZ2_bzReadOpen)
1093                    ( int*  bzerror,
1094                      FILE* f,
1095                      int   verbosity,
1096                      int   small,
1097                      void* unused,
1098                      int   nUnused )
1099 {
1100    bzFile* bzf = NULL;
1101    int     ret;
1102 
1103    BZ_SETERR(BZ_OK);
1104 
1105    if (f == NULL ||
1106        (small != 0 && small != 1) ||
1107        (verbosity < 0 || verbosity > 4) ||
1108        (unused == NULL && nUnused != 0) ||
1109        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1110       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1111 
1112    if (ferror(f))
1113       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1114 
1115    bzf = (bzFile*) malloc ( sizeof(bzFile) );
1116    if (bzf == NULL)
1117       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1118 
1119    BZ_SETERR(BZ_OK);
1120 
1121    bzf->initialisedOk = False;
1122    bzf->handle        = f;
1123    bzf->bufN          = 0;
1124    bzf->writing       = False;
1125    bzf->strm.bzalloc  = NULL;
1126    bzf->strm.bzfree   = NULL;
1127    bzf->strm.opaque   = NULL;
1128 
1129    while (nUnused > 0) {
1130       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1131       unused = ((void*)( 1 + ((UChar*)(unused))  ));
1132       nUnused--;
1133    }
1134 
1135    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1136    if (ret != BZ_OK)
1137       { BZ_SETERR(ret); free(bzf); return NULL; };
1138 
1139    bzf->strm.avail_in = bzf->bufN;
1140    bzf->strm.next_in  = bzf->buf;
1141 
1142    bzf->initialisedOk = True;
1143    return bzf;
1144 }
1145 
1146 
1147 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadClose)1148 void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1149 {
1150    bzFile* bzf = (bzFile*)b;
1151 
1152    BZ_SETERR(BZ_OK);
1153    if (bzf == NULL)
1154       { BZ_SETERR(BZ_OK); return; };
1155 
1156    if (bzf->writing)
1157       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1158 
1159    if (bzf->initialisedOk)
1160       (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1161    free ( bzf );
1162 }
1163 
1164 
1165 /*---------------------------------------------------*/
BZ_API(BZ2_bzRead)1166 int BZ_API(BZ2_bzRead)
1167            ( int*    bzerror,
1168              BZFILE* b,
1169              void*   buf,
1170              int     len )
1171 {
1172    Int32   n, ret;
1173    bzFile* bzf = (bzFile*)b;
1174 
1175    BZ_SETERR(BZ_OK);
1176 
1177    if (bzf == NULL || buf == NULL || len < 0)
1178       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1179 
1180    if (bzf->writing)
1181       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1182 
1183    if (len == 0)
1184       { BZ_SETERR(BZ_OK); return 0; };
1185 
1186    bzf->strm.avail_out = len;
1187    bzf->strm.next_out = (char*) buf;
1188 
1189    while (True) {
1190 
1191       if (ferror(bzf->handle))
1192          { BZ_SETERR(BZ_IO_ERROR); return 0; };
1193 
1194       if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1195          n = fread ( bzf->buf, sizeof(UChar),
1196                      BZ_MAX_UNUSED, bzf->handle );
1197          if (ferror(bzf->handle))
1198             { BZ_SETERR(BZ_IO_ERROR); return 0; };
1199          bzf->bufN = n;
1200          bzf->strm.avail_in = bzf->bufN;
1201          bzf->strm.next_in = bzf->buf;
1202       }
1203 
1204       ret = BZ2_bzDecompress ( &(bzf->strm) );
1205 
1206       if (ret != BZ_OK && ret != BZ_STREAM_END)
1207          { BZ_SETERR(ret); return 0; };
1208 
1209       if (ret == BZ_OK && myfeof(bzf->handle) &&
1210           bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1211          { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
1212 
1213       if (ret == BZ_STREAM_END)
1214          { BZ_SETERR(BZ_STREAM_END);
1215            return len - bzf->strm.avail_out; };
1216       if (bzf->strm.avail_out == 0)
1217          { BZ_SETERR(BZ_OK); return len; };
1218 
1219    }
1220 
1221    return 0; /*not reached*/
1222 }
1223 
1224 
1225 /*---------------------------------------------------*/
BZ_API(BZ2_bzReadGetUnused)1226 void BZ_API(BZ2_bzReadGetUnused)
1227                      ( int*    bzerror,
1228                        BZFILE* b,
1229                        void**  unused,
1230                        int*    nUnused )
1231 {
1232    bzFile* bzf = (bzFile*)b;
1233    if (bzf == NULL)
1234       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1235    if (bzf->lastErr != BZ_STREAM_END)
1236       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1237    if (unused == NULL || nUnused == NULL)
1238       { BZ_SETERR(BZ_PARAM_ERROR); return; };
1239 
1240    BZ_SETERR(BZ_OK);
1241    *nUnused = bzf->strm.avail_in;
1242    *unused = bzf->strm.next_in;
1243 }
1244 #endif
1245 
1246 
1247 /*---------------------------------------------------*/
1248 /*--- Misc convenience stuff                      ---*/
1249 /*---------------------------------------------------*/
1250 
1251 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffCompress)1252 int BZ_API(BZ2_bzBuffToBuffCompress)
1253                          ( char*         dest,
1254                            unsigned int* destLen,
1255                            char*         source,
1256                            unsigned int  sourceLen,
1257                            int           blockSize100k,
1258                            int           verbosity,
1259                            int           workFactor )
1260 {
1261    bz_stream strm;
1262    int ret;
1263 
1264    if (dest == NULL || destLen == NULL ||
1265        source == NULL ||
1266        blockSize100k < 1 || blockSize100k > 9 ||
1267        verbosity < 0 || verbosity > 4 ||
1268        workFactor < 0 || workFactor > 250)
1269       return BZ_PARAM_ERROR;
1270 
1271    if (workFactor == 0) workFactor = 30;
1272    strm.bzalloc = NULL;
1273    strm.bzfree = NULL;
1274    strm.opaque = NULL;
1275    ret = BZ2_bzCompressInit ( &strm, blockSize100k,
1276                               verbosity, workFactor );
1277    if (ret != BZ_OK) return ret;
1278 
1279    strm.next_in = source;
1280    strm.next_out = dest;
1281    strm.avail_in = sourceLen;
1282    strm.avail_out = *destLen;
1283 
1284    ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1285    if (ret == BZ_FINISH_OK) goto output_overflow;
1286    if (ret != BZ_STREAM_END) goto errhandler;
1287 
1288    /* normal termination */
1289    *destLen -= strm.avail_out;
1290    BZ2_bzCompressEnd ( &strm );
1291    return BZ_OK;
1292 
1293    output_overflow:
1294    BZ2_bzCompressEnd ( &strm );
1295    return BZ_OUTBUFF_FULL;
1296 
1297    errhandler:
1298    BZ2_bzCompressEnd ( &strm );
1299    return ret;
1300 }
1301 
1302 
1303 /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffDecompress)1304 int BZ_API(BZ2_bzBuffToBuffDecompress)
1305                            ( char*         dest,
1306                              unsigned int* destLen,
1307                              char*         source,
1308                              unsigned int  sourceLen,
1309                              int           small,
1310                              int           verbosity )
1311 {
1312    bz_stream strm;
1313    int ret;
1314 
1315    if (dest == NULL || destLen == NULL ||
1316        source == NULL ||
1317        (small != 0 && small != 1) ||
1318        verbosity < 0 || verbosity > 4)
1319           return BZ_PARAM_ERROR;
1320 
1321    strm.bzalloc = NULL;
1322    strm.bzfree = NULL;
1323    strm.opaque = NULL;
1324    ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1325    if (ret != BZ_OK) return ret;
1326 
1327    strm.next_in = source;
1328    strm.next_out = dest;
1329    strm.avail_in = sourceLen;
1330    strm.avail_out = *destLen;
1331 
1332    ret = BZ2_bzDecompress ( &strm );
1333    if (ret == BZ_OK) goto output_overflow_or_eof;
1334    if (ret != BZ_STREAM_END) goto errhandler;
1335 
1336    /* normal termination */
1337    *destLen -= strm.avail_out;
1338    BZ2_bzDecompressEnd ( &strm );
1339    return BZ_OK;
1340 
1341    output_overflow_or_eof:
1342    if (strm.avail_out > 0) {
1343       BZ2_bzDecompressEnd ( &strm );
1344       return BZ_UNEXPECTED_EOF;
1345    } else {
1346       BZ2_bzDecompressEnd ( &strm );
1347       return BZ_OUTBUFF_FULL;
1348    };
1349 
1350    errhandler:
1351    BZ2_bzDecompressEnd ( &strm );
1352    return ret;
1353 }
1354 
1355 
1356 /*---------------------------------------------------*/
1357 /*--
1358    Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
1359    to support better zlib compatibility.
1360    This code is not _officially_ part of libbzip2 (yet);
1361    I haven't tested it, documented it, or considered the
1362    threading-safeness of it.
1363    If this code breaks, please contact both Yoshioka and me.
1364 --*/
1365 /*---------------------------------------------------*/
1366 
1367 /*---------------------------------------------------*/
1368 /*--
1369    return version like "0.9.5d, 4-Sept-1999".
1370 --*/
BZ_API(BZ2_bzlibVersion)1371 const char * BZ_API(BZ2_bzlibVersion)(void)
1372 {
1373    return BZ_VERSION;
1374 }
1375 
1376 
1377 #ifndef BZ_NO_STDIO
1378 /*---------------------------------------------------*/
1379 
1380 #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1381 #   include <fcntl.h>
1382 #   include <io.h>
1383 #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1384 #else
1385 #   define SET_BINARY_MODE(file)
1386 #endif
1387 static
bzopen_or_bzdopen(const char * path,int fd,const char * mode,int open_mode)1388 BZFILE * bzopen_or_bzdopen
1389                ( const char *path,   /* no use when bzdopen */
1390                  int fd,             /* no use when bzdopen */
1391                  const char *mode,
1392                  int open_mode)      /* bzopen: 0, bzdopen:1 */
1393 {
1394    int    bzerr;
1395    char   unused[BZ_MAX_UNUSED];
1396    int    blockSize100k = 9;
1397    int    writing       = 0;
1398    char   mode2[10]     = "";
1399    FILE   *fp           = NULL;
1400    BZFILE *bzfp         = NULL;
1401    int    verbosity     = 0;
1402    int    workFactor    = 30;
1403    int    smallMode     = 0;
1404    int    nUnused       = 0;
1405 
1406    if (mode == NULL) return NULL;
1407    while (*mode) {
1408       switch (*mode) {
1409       case 'r':
1410          writing = 0; break;
1411       case 'w':
1412          writing = 1; break;
1413       case 's':
1414          smallMode = 1; break;
1415       default:
1416          if (isdigit((unsigned char)(*mode))) {
1417             blockSize100k = *mode-BZ_HDR_0;
1418          }
1419       }
1420       mode++;
1421    }
1422    strcat(mode2, writing ? "w" : "r" );
1423    strcat(mode2,"b");   /* binary mode */
1424 
1425    if (open_mode==0) {
1426       if (path==NULL || strcmp(path,"")==0) {
1427         fp = (writing ? stdout : stdin);
1428         SET_BINARY_MODE(fp);
1429       } else {
1430         fp = fopen(path,mode2);
1431       }
1432    } else {
1433 #ifdef BZ_STRICT_ANSI
1434       fp = NULL;
1435 #else
1436       fp = fdopen(fd,mode2);
1437 #endif
1438    }
1439    if (fp == NULL) return NULL;
1440 
1441    if (writing) {
1442       /* Guard against total chaos and anarchy -- JRS */
1443       if (blockSize100k < 1) blockSize100k = 1;
1444       if (blockSize100k > 9) blockSize100k = 9;
1445       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
1446                              verbosity,workFactor);
1447    } else {
1448       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
1449                             unused,nUnused);
1450    }
1451    if (bzfp == NULL) {
1452       if (fp != stdin && fp != stdout) fclose(fp);
1453       return NULL;
1454    }
1455    return bzfp;
1456 }
1457 
1458 
1459 /*---------------------------------------------------*/
1460 /*--
1461    open file for read or write.
1462       ex) bzopen("file","w9")
1463       case path="" or NULL => use stdin or stdout.
1464 --*/
BZ_API(BZ2_bzopen)1465 BZFILE * BZ_API(BZ2_bzopen)
1466                ( const char *path,
1467                  const char *mode )
1468 {
1469    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1470 }
1471 
1472 
1473 /*---------------------------------------------------*/
BZ_API(BZ2_bzdopen)1474 BZFILE * BZ_API(BZ2_bzdopen)
1475                ( int fd,
1476                  const char *mode )
1477 {
1478    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1479 }
1480 
1481 
1482 /*---------------------------------------------------*/
BZ_API(BZ2_bzread)1483 int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1484 {
1485    int bzerr, nread;
1486    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1487    nread = BZ2_bzRead(&bzerr,b,buf,len);
1488    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1489       return nread;
1490    } else {
1491       return -1;
1492    }
1493 }
1494 
1495 
1496 /*---------------------------------------------------*/
BZ_API(BZ2_bzwrite)1497 int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1498 {
1499    int bzerr;
1500 
1501    BZ2_bzWrite(&bzerr,b,buf,len);
1502    if(bzerr == BZ_OK){
1503       return len;
1504    }else{
1505       return -1;
1506    }
1507 }
1508 
1509 
1510 /*---------------------------------------------------*/
BZ_API(BZ2_bzflush)1511 int BZ_API(BZ2_bzflush) (BZFILE *b)
1512 {
1513    /* do nothing now... */
1514    return 0;
1515 }
1516 
1517 
1518 /*---------------------------------------------------*/
BZ_API(BZ2_bzclose)1519 void BZ_API(BZ2_bzclose) (BZFILE* b)
1520 {
1521    int bzerr;
1522    FILE *fp;
1523 
1524    if (b==NULL) {return;}
1525    fp = ((bzFile *)b)->handle;
1526    if(((bzFile*)b)->writing){
1527       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1528       if(bzerr != BZ_OK){
1529          BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
1530       }
1531    }else{
1532       BZ2_bzReadClose(&bzerr,b);
1533    }
1534    if(fp!=stdin && fp!=stdout){
1535       fclose(fp);
1536    }
1537 }
1538 
1539 
1540 /*---------------------------------------------------*/
1541 /*--
1542    return last error code
1543 --*/
1544 static const char *bzerrorstrings[] = {
1545        "OK"
1546       ,"SEQUENCE_ERROR"
1547       ,"PARAM_ERROR"
1548       ,"MEM_ERROR"
1549       ,"DATA_ERROR"
1550       ,"DATA_ERROR_MAGIC"
1551       ,"IO_ERROR"
1552       ,"UNEXPECTED_EOF"
1553       ,"OUTBUFF_FULL"
1554       ,"CONFIG_ERROR"
1555       ,"???"   /* for future */
1556       ,"???"   /* for future */
1557       ,"???"   /* for future */
1558       ,"???"   /* for future */
1559       ,"???"   /* for future */
1560       ,"???"   /* for future */
1561 };
1562 
1563 
BZ_API(BZ2_bzerror)1564 const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1565 {
1566    int err = ((bzFile *)b)->lastErr;
1567 
1568    if(err>0) err = 0;
1569    *errnum = err;
1570    return bzerrorstrings[err*-1];
1571 }
1572 #endif
1573 
1574 
1575 /*-------------------------------------------------------------*/
1576 /*--- end                                           bzlib.c ---*/
1577 /*-------------------------------------------------------------*/
1578