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