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