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