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