bzlib.c revision 215041
1215976Sjmallett
2232812Sjmallett/*-------------------------------------------------------------*/
3215976Sjmallett/*--- Library top-level functions.                          ---*/
4215976Sjmallett/*---                                               bzlib.c ---*/
5215976Sjmallett/*-------------------------------------------------------------*/
6215976Sjmallett
7215976Sjmallett/* ------------------------------------------------------------------
8215976Sjmallett   This file is part of bzip2/libbzip2, a program and library for
9215976Sjmallett   lossless, block-sorting data compression.
10215976Sjmallett
11215976Sjmallett   bzip2/libbzip2 version 1.0.6 of 6 September 2010
12215976Sjmallett   Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
13215976Sjmallett
14215976Sjmallett   Please read the WARNING, DISCLAIMER and PATENTS sections in the
15215976Sjmallett   README file.
16215976Sjmallett
17215976Sjmallett   This program is released under the terms of the license contained
18232812Sjmallett   in the file LICENSE.
19215976Sjmallett   ------------------------------------------------------------------ */
20215976Sjmallett
21215976Sjmallett/* CHANGES
22215976Sjmallett   0.9.0    -- original version.
23215976Sjmallett   0.9.0a/b -- no changes in this file.
24215976Sjmallett   0.9.0c   -- made zero-length BZ_FLUSH work correctly in bzCompress().
25215976Sjmallett     fixed bzWrite/bzRead to ignore zero-length requests.
26215976Sjmallett     fixed bzread to correctly handle read requests after EOF.
27215976Sjmallett     wrong parameter order in call to bzDecompressInit in
28215976Sjmallett     bzBuffToBuffDecompress.  Fixed.
29232812Sjmallett*/
30215976Sjmallett
31215976Sjmallett#include <sys/cdefs.h>
32215976Sjmallett__FBSDID("$FreeBSD: head/contrib/bzip2/bzlib.c 215041 2010-11-09 18:32:57Z obrien $");
33215976Sjmallett
34215976Sjmallett#include "bzlib_private.h"
35215976Sjmallett
36215976Sjmallett#ifndef BZ_NO_COMPRESS
37215976Sjmallett
38215976Sjmallett/*---------------------------------------------------*/
39215976Sjmallett/*--- Compression stuff                           ---*/
40215976Sjmallett/*---------------------------------------------------*/
41215976Sjmallett
42215976Sjmallett
43215976Sjmallett/*---------------------------------------------------*/
44215976Sjmallett#ifndef BZ_NO_STDIO
45215976Sjmallettvoid BZ2_bz__AssertH__fail ( int errcode )
46215976Sjmallett{
47215976Sjmallett   fprintf(stderr,
48215976Sjmallett      "\n\nbzip2/libbzip2: internal error number %d.\n"
49215976Sjmallett      "This is a bug in bzip2/libbzip2, %s.\n"
50215976Sjmallett      "Please report it to me at: jseward@bzip.org.  If this happened\n"
51215976Sjmallett      "when you were using some program which uses libbzip2 as a\n"
52232812Sjmallett      "component, you should also report this bug to the author(s)\n"
53232812Sjmallett      "of that program.  Please make an effort to report this bug;\n"
54215976Sjmallett      "timely and accurate bug reports eventually lead to higher\n"
55215976Sjmallett      "quality software.  Thanks.  Julian Seward, 10 December 2007.\n\n",
56215976Sjmallett      errcode,
57215976Sjmallett      BZ2_bzlibVersion()
58215976Sjmallett   );
59232812Sjmallett
60232812Sjmallett   if (errcode == 1007) {
61232812Sjmallett   fprintf(stderr,
62232812Sjmallett      "\n*** A special note about internal error number 1007 ***\n"
63232812Sjmallett      "\n"
64215976Sjmallett      "Experience suggests that a common cause of i.e. 1007\n"
65215976Sjmallett      "is unreliable memory or other hardware.  The 1007 assertion\n"
66215976Sjmallett      "just happens to cross-check the results of huge numbers of\n"
67215976Sjmallett      "memory reads/writes, and so acts (unintendedly) as a stress\n"
68215976Sjmallett      "test of your memory system.\n"
69215976Sjmallett      "\n"
70215976Sjmallett      "I suggest the following: try compressing the file again,\n"
71215976Sjmallett      "possibly monitoring progress in detail with the -vv flag.\n"
72215976Sjmallett      "\n"
73215976Sjmallett      "* If the error cannot be reproduced, and/or happens at different\n"
74232812Sjmallett      "  points in compression, you may have a flaky memory system.\n"
75232812Sjmallett      "  Try a memory-test program.  I have used Memtest86\n"
76232812Sjmallett      "  (www.memtest86.com).  At the time of writing it is free (GPLd).\n"
77232812Sjmallett      "  Memtest86 tests memory much more thorougly than your BIOSs\n"
78232812Sjmallett      "  power-on test, and may find failures that the BIOS doesn't.\n"
79215976Sjmallett      "\n"
80215976Sjmallett      "* If the error can be repeatably reproduced, this is a bug in\n"
81215976Sjmallett      "  bzip2, and I would very much like to hear about it.  Please\n"
82215976Sjmallett      "  let me know, and, ideally, save a copy of the file causing the\n"
83215976Sjmallett      "  problem -- without which I will be unable to investigate it.\n"
84215976Sjmallett      "\n"
85215976Sjmallett   );
86215976Sjmallett   }
87215976Sjmallett
88215976Sjmallett   exit(3);
89232812Sjmallett}
90232812Sjmallett#endif
91232812Sjmallett
92232812Sjmallett#endif /* BZ_NO_COMPRESS */
93232812Sjmallett
94215976Sjmallett/*---------------------------------------------------*/
95215976Sjmallettstatic
96215976Sjmallettint bz_config_ok ( void )
97215976Sjmallett{
98215976Sjmallett   if (sizeof(int)   != 4) return 0;
99215976Sjmallett   if (sizeof(short) != 2) return 0;
100215976Sjmallett   if (sizeof(char)  != 1) return 0;
101215976Sjmallett   return 1;
102215976Sjmallett}
103215976Sjmallett
104232812Sjmallett
105232812Sjmallett/*---------------------------------------------------*/
106232812Sjmallettstatic
107232812Sjmallettvoid* default_bzalloc ( void* opaque, Int32 items, Int32 size )
108232812Sjmallett{
109215976Sjmallett   void* v = malloc ( items * size );
110215976Sjmallett   return v;
111215976Sjmallett}
112215976Sjmallett
113215976Sjmallettstatic
114215976Sjmallettvoid default_bzfree ( void* opaque, void* addr )
115215976Sjmallett{
116215976Sjmallett   if (addr != NULL) free ( addr );
117215976Sjmallett}
118215976Sjmallett
119232812Sjmallett#ifndef BZ_NO_COMPRESS
120232812Sjmallett
121232812Sjmallett/*---------------------------------------------------*/
122232812Sjmallettstatic
123232812Sjmallettvoid prepare_new_block ( EState* s )
124215976Sjmallett{
125215976Sjmallett   Int32 i;
126215976Sjmallett   s->nblock = 0;
127215976Sjmallett   s->numZ = 0;
128215976Sjmallett   s->state_out_pos = 0;
129215976Sjmallett   BZ_INITIALISE_CRC ( s->blockCRC );
130215976Sjmallett   for (i = 0; i < 256; i++) s->inUse[i] = False;
131215976Sjmallett   s->blockNo++;
132215976Sjmallett}
133215976Sjmallett
134232812Sjmallett
135232812Sjmallett/*---------------------------------------------------*/
136232812Sjmallettstatic
137232812Sjmallettvoid init_RL ( EState* s )
138232812Sjmallett{
139215976Sjmallett   s->state_in_ch  = 256;
140215976Sjmallett   s->state_in_len = 0;
141215976Sjmallett}
142215976Sjmallett
143215976Sjmallett
144215976Sjmallettstatic
145215976SjmallettBool isempty_RL ( EState* s )
146215976Sjmallett{
147215976Sjmallett   if (s->state_in_ch < 256 && s->state_in_len > 0)
148215976Sjmallett      return False; else
149232812Sjmallett      return True;
150232812Sjmallett}
151232812Sjmallett
152232812Sjmallett
153232812Sjmallett/*---------------------------------------------------*/
154215976Sjmallettint BZ_API(BZ2_bzCompressInit)
155215976Sjmallett                    ( bz_stream* strm,
156215976Sjmallett                     int        blockSize100k,
157215976Sjmallett                     int        verbosity,
158215976Sjmallett                     int        workFactor )
159215976Sjmallett{
160215976Sjmallett   Int32   n;
161215976Sjmallett   EState* s;
162215976Sjmallett
163215976Sjmallett   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
164232812Sjmallett
165232812Sjmallett   if (strm == NULL ||
166232812Sjmallett       blockSize100k < 1 || blockSize100k > 9 ||
167232812Sjmallett       workFactor < 0 || workFactor > 250)
168232812Sjmallett     return BZ_PARAM_ERROR;
169215976Sjmallett
170215976Sjmallett   if (workFactor == 0) workFactor = 30;
171215976Sjmallett   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
172215976Sjmallett   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
173215976Sjmallett
174215976Sjmallett   s = BZALLOC( sizeof(EState) );
175215976Sjmallett   if (s == NULL) return BZ_MEM_ERROR;
176215976Sjmallett   s->strm = strm;
177215976Sjmallett
178215976Sjmallett   s->arr1 = NULL;
179232812Sjmallett   s->arr2 = NULL;
180232812Sjmallett   s->ftab = NULL;
181232812Sjmallett
182232812Sjmallett   n       = 100000 * blockSize100k;
183232812Sjmallett   s->arr1 = BZALLOC( n                  * sizeof(UInt32) );
184215976Sjmallett   s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
185215976Sjmallett   s->ftab = BZALLOC( 65537              * sizeof(UInt32) );
186215976Sjmallett
187215976Sjmallett   if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
188215976Sjmallett      if (s->arr1 != NULL) BZFREE(s->arr1);
189215976Sjmallett      if (s->arr2 != NULL) BZFREE(s->arr2);
190215976Sjmallett      if (s->ftab != NULL) BZFREE(s->ftab);
191215976Sjmallett      if (s       != NULL) BZFREE(s);
192215976Sjmallett      return BZ_MEM_ERROR;
193215976Sjmallett   }
194232812Sjmallett
195232812Sjmallett   s->blockNo           = 0;
196232812Sjmallett   s->state             = BZ_S_INPUT;
197232812Sjmallett   s->mode              = BZ_M_RUNNING;
198232812Sjmallett   s->combinedCRC       = 0;
199215976Sjmallett   s->blockSize100k     = blockSize100k;
200215976Sjmallett   s->nblockMAX         = 100000 * blockSize100k - 19;
201215976Sjmallett   s->verbosity         = verbosity;
202215976Sjmallett   s->workFactor        = workFactor;
203215976Sjmallett
204215976Sjmallett   s->block             = (UChar*)s->arr2;
205215976Sjmallett   s->mtfv              = (UInt16*)s->arr1;
206215976Sjmallett   s->zbits             = NULL;
207215976Sjmallett   s->ptr               = (UInt32*)s->arr1;
208215976Sjmallett
209232812Sjmallett   strm->state          = s;
210232812Sjmallett   strm->total_in_lo32  = 0;
211232812Sjmallett   strm->total_in_hi32  = 0;
212232812Sjmallett   strm->total_out_lo32 = 0;
213215976Sjmallett   strm->total_out_hi32 = 0;
214215976Sjmallett   init_RL ( s );
215215976Sjmallett   prepare_new_block ( s );
216215976Sjmallett   return BZ_OK;
217215976Sjmallett}
218215976Sjmallett
219215976Sjmallett
220215976Sjmallett/*---------------------------------------------------*/
221215976Sjmallettstatic
222215976Sjmallettvoid add_pair_to_block ( EState* s )
223232812Sjmallett{
224232812Sjmallett   Int32 i;
225232812Sjmallett   UChar ch = (UChar)(s->state_in_ch);
226232812Sjmallett   for (i = 0; i < s->state_in_len; i++) {
227232812Sjmallett      BZ_UPDATE_CRC( s->blockCRC, ch );
228215976Sjmallett   }
229215976Sjmallett   s->inUse[s->state_in_ch] = True;
230215976Sjmallett   switch (s->state_in_len) {
231215976Sjmallett      case 1:
232215976Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
233215976Sjmallett         break;
234215976Sjmallett      case 2:
235215976Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
236215976Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
237215976Sjmallett         break;
238232812Sjmallett      case 3:
239232812Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
240232812Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
241232812Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
242232812Sjmallett         break;
243215976Sjmallett      default:
244215976Sjmallett         s->inUse[s->state_in_len-4] = True;
245215976Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
246215976Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
247215976Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
248215976Sjmallett         s->block[s->nblock] = (UChar)ch; s->nblock++;
249215976Sjmallett         s->block[s->nblock] = ((UChar)(s->state_in_len-4));
250215976Sjmallett         s->nblock++;
251215976Sjmallett         break;
252215976Sjmallett   }
253215976Sjmallett}
254215976Sjmallett
255215976Sjmallett
256215976Sjmallett/*---------------------------------------------------*/
257232812Sjmallettstatic
258215976Sjmallettvoid flush_RL ( EState* s )
259232812Sjmallett{
260232812Sjmallett   if (s->state_in_ch < 256) add_pair_to_block ( s );
261215976Sjmallett   init_RL ( s );
262215976Sjmallett}
263215976Sjmallett
264215976Sjmallett
265215976Sjmallett/*---------------------------------------------------*/
266215976Sjmallett#define ADD_CHAR_TO_BLOCK(zs,zchh0)               \
267215976Sjmallett{                                                 \
268215976Sjmallett   UInt32 zchh = (UInt32)(zchh0);                 \
269215976Sjmallett   /*-- fast track the common case --*/           \
270215976Sjmallett   if (zchh != zs->state_in_ch &&                 \
271215976Sjmallett       zs->state_in_len == 1) {                   \
272215976Sjmallett      UChar ch = (UChar)(zs->state_in_ch);        \
273215976Sjmallett      BZ_UPDATE_CRC( zs->blockCRC, ch );          \
274215976Sjmallett      zs->inUse[zs->state_in_ch] = True;          \
275215976Sjmallett      zs->block[zs->nblock] = (UChar)ch;          \
276215976Sjmallett      zs->nblock++;                               \
277215976Sjmallett      zs->state_in_ch = zchh;                     \
278232812Sjmallett   }                                              \
279215976Sjmallett   else                                           \
280215976Sjmallett   /*-- general, uncommon cases --*/              \
281232812Sjmallett   if (zchh != zs->state_in_ch ||                 \
282232812Sjmallett      zs->state_in_len == 255) {                  \
283232812Sjmallett      if (zs->state_in_ch < 256)                  \
284232812Sjmallett         add_pair_to_block ( zs );                \
285215976Sjmallett      zs->state_in_ch = zchh;                     \
286215976Sjmallett      zs->state_in_len = 1;                       \
287215976Sjmallett   } else {                                       \
288215976Sjmallett      zs->state_in_len++;                         \
289215976Sjmallett   }                                              \
290215976Sjmallett}
291215976Sjmallett
292215976Sjmallett
293215976Sjmallett/*---------------------------------------------------*/
294232812Sjmallettstatic
295215976SjmallettBool copy_input_until_stop ( EState* s )
296232812Sjmallett{
297232812Sjmallett   Bool progress_in = False;
298215976Sjmallett
299215976Sjmallett   if (s->mode == BZ_M_RUNNING) {
300215976Sjmallett
301215976Sjmallett      /*-- fast track the common case --*/
302215976Sjmallett      while (True) {
303215976Sjmallett         /*-- block full? --*/
304215976Sjmallett         if (s->nblock >= s->nblockMAX) break;
305215976Sjmallett         /*-- no input? --*/
306215976Sjmallett         if (s->strm->avail_in == 0) break;
307215976Sjmallett         progress_in = True;
308215976Sjmallett         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
309215976Sjmallett         s->strm->next_in++;
310215976Sjmallett         s->strm->avail_in--;
311215976Sjmallett         s->strm->total_in_lo32++;
312215976Sjmallett         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
313215976Sjmallett      }
314215976Sjmallett
315215976Sjmallett   } else {
316215976Sjmallett
317215976Sjmallett      /*-- general, uncommon case --*/
318215976Sjmallett      while (True) {
319215976Sjmallett         /*-- block full? --*/
320215976Sjmallett         if (s->nblock >= s->nblockMAX) break;
321215976Sjmallett         /*-- no input? --*/
322215976Sjmallett         if (s->strm->avail_in == 0) break;
323215976Sjmallett         /*-- flush/finish end? --*/
324215976Sjmallett         if (s->avail_in_expect == 0) break;
325215976Sjmallett         progress_in = True;
326215976Sjmallett         ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
327215976Sjmallett         s->strm->next_in++;
328215976Sjmallett         s->strm->avail_in--;
329215976Sjmallett         s->strm->total_in_lo32++;
330215976Sjmallett         if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
331215976Sjmallett         s->avail_in_expect--;
332215976Sjmallett      }
333215976Sjmallett   }
334215976Sjmallett   return progress_in;
335215976Sjmallett}
336215976Sjmallett
337215976Sjmallett
338215976Sjmallett/*---------------------------------------------------*/
339215976Sjmallettstatic
340215976SjmallettBool copy_output_until_stop ( EState* s )
341215976Sjmallett{
342215976Sjmallett   Bool progress_out = False;
343215976Sjmallett
344215976Sjmallett   while (True) {
345215976Sjmallett
346215976Sjmallett      /*-- no output space? --*/
347215976Sjmallett      if (s->strm->avail_out == 0) break;
348215976Sjmallett
349215976Sjmallett      /*-- block done? --*/
350215976Sjmallett      if (s->state_out_pos >= s->numZ) break;
351215976Sjmallett
352215976Sjmallett      progress_out = True;
353215976Sjmallett      *(s->strm->next_out) = s->zbits[s->state_out_pos];
354215976Sjmallett      s->state_out_pos++;
355232812Sjmallett      s->strm->avail_out--;
356215976Sjmallett      s->strm->next_out++;
357215976Sjmallett      s->strm->total_out_lo32++;
358232812Sjmallett      if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
359232812Sjmallett   }
360232812Sjmallett
361232812Sjmallett   return progress_out;
362215976Sjmallett}
363215976Sjmallett
364215976Sjmallett
365215976Sjmallett/*---------------------------------------------------*/
366215976Sjmallettstatic
367215976SjmallettBool handle_compress ( bz_stream* strm )
368215976Sjmallett{
369215976Sjmallett   Bool progress_in  = False;
370215976Sjmallett   Bool progress_out = False;
371215976Sjmallett   EState* s = strm->state;
372215976Sjmallett
373215976Sjmallett   while (True) {
374215976Sjmallett
375215976Sjmallett      if (s->state == BZ_S_OUTPUT) {
376215976Sjmallett         progress_out |= copy_output_until_stop ( s );
377215976Sjmallett         if (s->state_out_pos < s->numZ) break;
378215976Sjmallett         if (s->mode == BZ_M_FINISHING &&
379215976Sjmallett             s->avail_in_expect == 0 &&
380215976Sjmallett             isempty_RL(s)) break;
381215976Sjmallett         prepare_new_block ( s );
382215976Sjmallett         s->state = BZ_S_INPUT;
383215976Sjmallett         if (s->mode == BZ_M_FLUSHING &&
384215976Sjmallett             s->avail_in_expect == 0 &&
385215976Sjmallett             isempty_RL(s)) break;
386215976Sjmallett      }
387215976Sjmallett
388215976Sjmallett      if (s->state == BZ_S_INPUT) {
389215976Sjmallett         progress_in |= copy_input_until_stop ( s );
390215976Sjmallett         if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
391215976Sjmallett            flush_RL ( s );
392215976Sjmallett            BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
393215976Sjmallett            s->state = BZ_S_OUTPUT;
394215976Sjmallett         }
395215976Sjmallett         else
396215976Sjmallett         if (s->nblock >= s->nblockMAX) {
397215976Sjmallett            BZ2_compressBlock ( s, False );
398215976Sjmallett            s->state = BZ_S_OUTPUT;
399215976Sjmallett         }
400215976Sjmallett         else
401215976Sjmallett         if (s->strm->avail_in == 0) {
402215976Sjmallett            break;
403215976Sjmallett         }
404215976Sjmallett      }
405215976Sjmallett
406215976Sjmallett   }
407215976Sjmallett
408215976Sjmallett   return progress_in || progress_out;
409232812Sjmallett}
410215976Sjmallett
411215976Sjmallett
412232812Sjmallett/*---------------------------------------------------*/
413232812Sjmallettint BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
414232812Sjmallett{
415232812Sjmallett   Bool progress;
416215976Sjmallett   EState* s;
417215976Sjmallett   if (strm == NULL) return BZ_PARAM_ERROR;
418215976Sjmallett   s = strm->state;
419215976Sjmallett   if (s == NULL) return BZ_PARAM_ERROR;
420215976Sjmallett   if (s->strm != strm) return BZ_PARAM_ERROR;
421215976Sjmallett
422215976Sjmallett   preswitch:
423215976Sjmallett   switch (s->mode) {
424215976Sjmallett
425232812Sjmallett      case BZ_M_IDLE:
426215976Sjmallett         return BZ_SEQUENCE_ERROR;
427232812Sjmallett
428232812Sjmallett      case BZ_M_RUNNING:
429215976Sjmallett         if (action == BZ_RUN) {
430215976Sjmallett            progress = handle_compress ( strm );
431215976Sjmallett            return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
432215976Sjmallett         }
433215976Sjmallett         else
434215976Sjmallett	 if (action == BZ_FLUSH) {
435215976Sjmallett            s->avail_in_expect = strm->avail_in;
436215976Sjmallett            s->mode = BZ_M_FLUSHING;
437215976Sjmallett            goto preswitch;
438215976Sjmallett         }
439215976Sjmallett         else
440215976Sjmallett         if (action == BZ_FINISH) {
441215976Sjmallett            s->avail_in_expect = strm->avail_in;
442215976Sjmallett            s->mode = BZ_M_FINISHING;
443215976Sjmallett            goto preswitch;
444215976Sjmallett         }
445215976Sjmallett         else
446215976Sjmallett            return BZ_PARAM_ERROR;
447215976Sjmallett
448215976Sjmallett      case BZ_M_FLUSHING:
449215976Sjmallett         if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
450215976Sjmallett         if (s->avail_in_expect != s->strm->avail_in)
451215976Sjmallett            return BZ_SEQUENCE_ERROR;
452215976Sjmallett         progress = handle_compress ( strm );
453215976Sjmallett         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
454215976Sjmallett             s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
455215976Sjmallett         s->mode = BZ_M_RUNNING;
456215976Sjmallett         return BZ_RUN_OK;
457215976Sjmallett
458215976Sjmallett      case BZ_M_FINISHING:
459215976Sjmallett         if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
460215976Sjmallett         if (s->avail_in_expect != s->strm->avail_in)
461215976Sjmallett            return BZ_SEQUENCE_ERROR;
462215976Sjmallett         progress = handle_compress ( strm );
463215976Sjmallett         if (!progress) return BZ_SEQUENCE_ERROR;
464215976Sjmallett         if (s->avail_in_expect > 0 || !isempty_RL(s) ||
465215976Sjmallett             s->state_out_pos < s->numZ) return BZ_FINISH_OK;
466215976Sjmallett         s->mode = BZ_M_IDLE;
467215976Sjmallett         return BZ_STREAM_END;
468215976Sjmallett   }
469215976Sjmallett   return BZ_OK; /*--not reached--*/
470215976Sjmallett}
471215976Sjmallett
472215976Sjmallett
473215976Sjmallett/*---------------------------------------------------*/
474215976Sjmallettint BZ_API(BZ2_bzCompressEnd)  ( bz_stream *strm )
475215976Sjmallett{
476215976Sjmallett   EState* s;
477215976Sjmallett   if (strm == NULL) return BZ_PARAM_ERROR;
478215976Sjmallett   s = strm->state;
479215976Sjmallett   if (s == NULL) return BZ_PARAM_ERROR;
480215976Sjmallett   if (s->strm != strm) return BZ_PARAM_ERROR;
481215976Sjmallett
482215976Sjmallett   if (s->arr1 != NULL) BZFREE(s->arr1);
483215976Sjmallett   if (s->arr2 != NULL) BZFREE(s->arr2);
484232812Sjmallett   if (s->ftab != NULL) BZFREE(s->ftab);
485215976Sjmallett   BZFREE(strm->state);
486215976Sjmallett
487232812Sjmallett   strm->state = NULL;
488232812Sjmallett
489232812Sjmallett   return BZ_OK;
490232812Sjmallett}
491215976Sjmallett
492215976Sjmallett#endif /* BZ_NO_COMPRESS */
493215976Sjmallett
494215976Sjmallett/*---------------------------------------------------*/
495215976Sjmallett/*--- Decompression stuff                         ---*/
496215976Sjmallett/*---------------------------------------------------*/
497215976Sjmallett
498215976Sjmallett/*---------------------------------------------------*/
499215976Sjmallettint BZ_API(BZ2_bzDecompressInit)
500232812Sjmallett                     ( bz_stream* strm,
501215976Sjmallett                       int        verbosity,
502232812Sjmallett                       int        small )
503232812Sjmallett{
504215976Sjmallett   DState* s;
505215976Sjmallett
506215976Sjmallett   if (!bz_config_ok()) return BZ_CONFIG_ERROR;
507232812Sjmallett
508232812Sjmallett   if (strm == NULL) return BZ_PARAM_ERROR;
509232812Sjmallett   if (small != 0 && small != 1) return BZ_PARAM_ERROR;
510232812Sjmallett   if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
511232812Sjmallett
512232812Sjmallett   if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
513232812Sjmallett   if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
514232812Sjmallett
515232812Sjmallett   s = BZALLOC( sizeof(DState) );
516232812Sjmallett   if (s == NULL) return BZ_MEM_ERROR;
517232812Sjmallett   s->strm                  = strm;
518232812Sjmallett   strm->state              = s;
519232812Sjmallett   s->state                 = BZ_X_MAGIC_1;
520232812Sjmallett   s->bsLive                = 0;
521232812Sjmallett   s->bsBuff                = 0;
522232812Sjmallett   s->calculatedCombinedCRC = 0;
523232812Sjmallett   strm->total_in_lo32      = 0;
524232812Sjmallett   strm->total_in_hi32      = 0;
525215976Sjmallett   strm->total_out_lo32     = 0;
526215976Sjmallett   strm->total_out_hi32     = 0;
527215976Sjmallett   s->smallDecompress       = (Bool)small;
528215976Sjmallett   s->ll4                   = NULL;
529215976Sjmallett   s->ll16                  = NULL;
530215976Sjmallett   s->tt                    = NULL;
531215976Sjmallett   s->currBlockNo           = 0;
532232812Sjmallett   s->verbosity             = verbosity;
533215976Sjmallett
534215976Sjmallett   return BZ_OK;
535232812Sjmallett}
536232812Sjmallett
537232812Sjmallett
538232812Sjmallett/*---------------------------------------------------*/
539215976Sjmallett/* Return  True iff data corruption is discovered.
540215976Sjmallett   Returns False if there is no problem.
541215976Sjmallett*/
542215976Sjmallettstatic
543215976SjmallettBool unRLE_obuf_to_output_FAST ( DState* s )
544215976Sjmallett{
545215976Sjmallett   UChar k1;
546215976Sjmallett
547215976Sjmallett   if (s->blockRandomised) {
548232812Sjmallett
549215976Sjmallett      while (True) {
550232812Sjmallett         /* try to finish existing run */
551232812Sjmallett         while (True) {
552215976Sjmallett            if (s->strm->avail_out == 0) return False;
553215976Sjmallett            if (s->state_out_len == 0) break;
554215976Sjmallett            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
555215976Sjmallett            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
556215976Sjmallett            s->state_out_len--;
557215976Sjmallett            s->strm->next_out++;
558215976Sjmallett            s->strm->avail_out--;
559215976Sjmallett            s->strm->total_out_lo32++;
560215976Sjmallett            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
561215976Sjmallett         }
562232812Sjmallett
563215976Sjmallett         /* can a new run be started? */
564215976Sjmallett         if (s->nblock_used == s->save_nblock+1) return False;
565232812Sjmallett
566232812Sjmallett         /* Only caused by corrupt data stream? */
567232812Sjmallett         if (s->nblock_used > s->save_nblock+1)
568232812Sjmallett            return True;
569215976Sjmallett
570215976Sjmallett         s->state_out_len = 1;
571215976Sjmallett         s->state_out_ch = s->k0;
572215976Sjmallett         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
573215976Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
574215976Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
575215976Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
576215976Sjmallett
577215976Sjmallett         s->state_out_len = 2;
578215976Sjmallett         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
579232812Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
580215976Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
581232812Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
582232812Sjmallett
583215976Sjmallett         s->state_out_len = 3;
584215976Sjmallett         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
585215976Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
586215976Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
587215976Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
588215976Sjmallett
589215976Sjmallett         BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
590232812Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
591215976Sjmallett         s->state_out_len = ((Int32)k1) + 4;
592215976Sjmallett         BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
593232812Sjmallett         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
594232812Sjmallett      }
595232812Sjmallett
596232812Sjmallett   } else {
597215976Sjmallett
598215976Sjmallett      /* restore */
599215976Sjmallett      UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
600215976Sjmallett      UChar         c_state_out_ch       = s->state_out_ch;
601215976Sjmallett      Int32         c_state_out_len      = s->state_out_len;
602215976Sjmallett      Int32         c_nblock_used        = s->nblock_used;
603215976Sjmallett      Int32         c_k0                 = s->k0;
604215976Sjmallett      UInt32*       c_tt                 = s->tt;
605215976Sjmallett      UInt32        c_tPos               = s->tPos;
606215976Sjmallett      char*         cs_next_out          = s->strm->next_out;
607232812Sjmallett      unsigned int  cs_avail_out         = s->strm->avail_out;
608215976Sjmallett      Int32         ro_blockSize100k     = s->blockSize100k;
609232812Sjmallett      /* end restore */
610232812Sjmallett
611215976Sjmallett      UInt32       avail_out_INIT = cs_avail_out;
612215976Sjmallett      Int32        s_save_nblockPP = s->save_nblock+1;
613215976Sjmallett      unsigned int total_out_lo32_old;
614215976Sjmallett
615215976Sjmallett      while (True) {
616215976Sjmallett
617215976Sjmallett         /* try to finish existing run */
618215976Sjmallett         if (c_state_out_len > 0) {
619215976Sjmallett            while (True) {
620215976Sjmallett               if (cs_avail_out == 0) goto return_notr;
621215976Sjmallett               if (c_state_out_len == 1) break;
622215976Sjmallett               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
623215976Sjmallett               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
624215976Sjmallett               c_state_out_len--;
625215976Sjmallett               cs_next_out++;
626215976Sjmallett               cs_avail_out--;
627215976Sjmallett            }
628215976Sjmallett            s_state_out_len_eq_one:
629215976Sjmallett            {
630215976Sjmallett               if (cs_avail_out == 0) {
631215976Sjmallett                  c_state_out_len = 1; goto return_notr;
632232812Sjmallett               };
633215976Sjmallett               *( (UChar*)(cs_next_out) ) = c_state_out_ch;
634215976Sjmallett               BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
635232812Sjmallett               cs_next_out++;
636232812Sjmallett               cs_avail_out--;
637232812Sjmallett            }
638232812Sjmallett         }
639215976Sjmallett         /* Only caused by corrupt data stream? */
640215976Sjmallett         if (c_nblock_used > s_save_nblockPP)
641215976Sjmallett            return True;
642215976Sjmallett
643215976Sjmallett         /* can a new run be started? */
644215976Sjmallett         if (c_nblock_used == s_save_nblockPP) {
645215976Sjmallett            c_state_out_len = 0; goto return_notr;
646215976Sjmallett         };
647215976Sjmallett         c_state_out_ch = c_k0;
648215976Sjmallett         BZ_GET_FAST_C(k1); c_nblock_used++;
649232812Sjmallett         if (k1 != c_k0) {
650215976Sjmallett            c_k0 = k1; goto s_state_out_len_eq_one;
651232812Sjmallett         };
652232812Sjmallett         if (c_nblock_used == s_save_nblockPP)
653215976Sjmallett            goto s_state_out_len_eq_one;
654215976Sjmallett
655215976Sjmallett         c_state_out_len = 2;
656215976Sjmallett         BZ_GET_FAST_C(k1); c_nblock_used++;
657215976Sjmallett         if (c_nblock_used == s_save_nblockPP) continue;
658215976Sjmallett         if (k1 != c_k0) { c_k0 = k1; continue; };
659215976Sjmallett
660215976Sjmallett         c_state_out_len = 3;
661215976Sjmallett         BZ_GET_FAST_C(k1); c_nblock_used++;
662215976Sjmallett         if (c_nblock_used == s_save_nblockPP) continue;
663215976Sjmallett         if (k1 != c_k0) { c_k0 = k1; continue; };
664215976Sjmallett
665215976Sjmallett         BZ_GET_FAST_C(k1); c_nblock_used++;
666215976Sjmallett         c_state_out_len = ((Int32)k1) + 4;
667215976Sjmallett         BZ_GET_FAST_C(c_k0); c_nblock_used++;
668215976Sjmallett      }
669215976Sjmallett
670215976Sjmallett      return_notr:
671215976Sjmallett      total_out_lo32_old = s->strm->total_out_lo32;
672215976Sjmallett      s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
673215976Sjmallett      if (s->strm->total_out_lo32 < total_out_lo32_old)
674215976Sjmallett         s->strm->total_out_hi32++;
675215976Sjmallett
676215976Sjmallett      /* save */
677215976Sjmallett      s->calculatedBlockCRC = c_calculatedBlockCRC;
678232812Sjmallett      s->state_out_ch       = c_state_out_ch;
679215976Sjmallett      s->state_out_len      = c_state_out_len;
680215976Sjmallett      s->nblock_used        = c_nblock_used;
681232812Sjmallett      s->k0                 = c_k0;
682232812Sjmallett      s->tt                 = c_tt;
683232812Sjmallett      s->tPos               = c_tPos;
684232812Sjmallett      s->strm->next_out     = cs_next_out;
685215976Sjmallett      s->strm->avail_out    = cs_avail_out;
686215976Sjmallett      /* end save */
687215976Sjmallett   }
688215976Sjmallett   return False;
689215976Sjmallett}
690215976Sjmallett
691215976Sjmallett
692215976Sjmallett
693215976Sjmallett/*---------------------------------------------------*/
694215976Sjmallett__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
695215976Sjmallett{
696232812Sjmallett   Int32 nb, na, mid;
697215976Sjmallett   nb = 0;
698232812Sjmallett   na = 256;
699232812Sjmallett   do {
700215976Sjmallett      mid = (nb + na) >> 1;
701215976Sjmallett      if (indx >= cftab[mid]) nb = mid; else na = mid;
702215976Sjmallett   }
703215976Sjmallett   while (na - nb != 1);
704215976Sjmallett   return nb;
705215976Sjmallett}
706215976Sjmallett
707215976Sjmallett
708215976Sjmallett/*---------------------------------------------------*/
709215976Sjmallett/* Return  True iff data corruption is discovered.
710215976Sjmallett   Returns False if there is no problem.
711215976Sjmallett*/
712215976Sjmallettstatic
713215976SjmallettBool unRLE_obuf_to_output_SMALL ( DState* s )
714215976Sjmallett{
715215976Sjmallett   UChar k1;
716215976Sjmallett
717215976Sjmallett   if (s->blockRandomised) {
718215976Sjmallett
719215976Sjmallett      while (True) {
720215976Sjmallett         /* try to finish existing run */
721215976Sjmallett         while (True) {
722215976Sjmallett            if (s->strm->avail_out == 0) return False;
723215976Sjmallett            if (s->state_out_len == 0) break;
724215976Sjmallett            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
725215976Sjmallett            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
726215976Sjmallett            s->state_out_len--;
727215976Sjmallett            s->strm->next_out++;
728215976Sjmallett            s->strm->avail_out--;
729215976Sjmallett            s->strm->total_out_lo32++;
730215976Sjmallett            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
731215976Sjmallett         }
732215976Sjmallett
733215976Sjmallett         /* can a new run be started? */
734215976Sjmallett         if (s->nblock_used == s->save_nblock+1) return False;
735215976Sjmallett
736215976Sjmallett         /* Only caused by corrupt data stream? */
737215976Sjmallett         if (s->nblock_used > s->save_nblock+1)
738215976Sjmallett            return True;
739215976Sjmallett
740215976Sjmallett         s->state_out_len = 1;
741215976Sjmallett         s->state_out_ch = s->k0;
742215976Sjmallett         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
743215976Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
744232812Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
745215976Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
746215976Sjmallett
747232812Sjmallett         s->state_out_len = 2;
748232812Sjmallett         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
749232812Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
750232812Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
751215976Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
752215976Sjmallett
753215976Sjmallett         s->state_out_len = 3;
754215976Sjmallett         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
755215976Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
756215976Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
757215976Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
758215976Sjmallett
759215976Sjmallett         BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
760232812Sjmallett         k1 ^= BZ_RAND_MASK; s->nblock_used++;
761215976Sjmallett         s->state_out_len = ((Int32)k1) + 4;
762232812Sjmallett         BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
763232812Sjmallett         s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
764215976Sjmallett      }
765215976Sjmallett
766215976Sjmallett   } else {
767215976Sjmallett
768215976Sjmallett      while (True) {
769215976Sjmallett         /* try to finish existing run */
770215976Sjmallett         while (True) {
771215976Sjmallett            if (s->strm->avail_out == 0) return False;
772215976Sjmallett            if (s->state_out_len == 0) break;
773215976Sjmallett            *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
774232812Sjmallett            BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
775215976Sjmallett            s->state_out_len--;
776215976Sjmallett            s->strm->next_out++;
777232812Sjmallett            s->strm->avail_out--;
778232812Sjmallett            s->strm->total_out_lo32++;
779232812Sjmallett            if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
780232812Sjmallett         }
781215976Sjmallett
782215976Sjmallett         /* can a new run be started? */
783215976Sjmallett         if (s->nblock_used == s->save_nblock+1) return False;
784215976Sjmallett
785215976Sjmallett         /* Only caused by corrupt data stream? */
786215976Sjmallett         if (s->nblock_used > s->save_nblock+1)
787215976Sjmallett            return True;
788215976Sjmallett
789215976Sjmallett         s->state_out_len = 1;
790215976Sjmallett         s->state_out_ch = s->k0;
791232812Sjmallett         BZ_GET_SMALL(k1); s->nblock_used++;
792215976Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
793232812Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
794232812Sjmallett
795215976Sjmallett         s->state_out_len = 2;
796215976Sjmallett         BZ_GET_SMALL(k1); s->nblock_used++;
797215976Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
798215976Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
799215976Sjmallett
800215976Sjmallett         s->state_out_len = 3;
801215976Sjmallett         BZ_GET_SMALL(k1); s->nblock_used++;
802215976Sjmallett         if (s->nblock_used == s->save_nblock+1) continue;
803232812Sjmallett         if (k1 != s->k0) { s->k0 = k1; continue; };
804215976Sjmallett
805215976Sjmallett         BZ_GET_SMALL(k1); s->nblock_used++;
806232812Sjmallett         s->state_out_len = ((Int32)k1) + 4;
807232812Sjmallett         BZ_GET_SMALL(s->k0); s->nblock_used++;
808215976Sjmallett      }
809215976Sjmallett
810215976Sjmallett   }
811215976Sjmallett}
812215976Sjmallett
813215976Sjmallett
814215976Sjmallett/*---------------------------------------------------*/
815215976Sjmallettint BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
816215976Sjmallett{
817232812Sjmallett   Bool    corrupt;
818215976Sjmallett   DState* s;
819232812Sjmallett   if (strm == NULL) return BZ_PARAM_ERROR;
820232812Sjmallett   s = strm->state;
821215976Sjmallett   if (s == NULL) return BZ_PARAM_ERROR;
822215976Sjmallett   if (s->strm != strm) return BZ_PARAM_ERROR;
823215976Sjmallett
824215976Sjmallett   while (True) {
825215976Sjmallett      if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
826215976Sjmallett      if (s->state == BZ_X_OUTPUT) {
827215976Sjmallett         if (s->smallDecompress)
828215976Sjmallett            corrupt = unRLE_obuf_to_output_SMALL ( s ); else
829215976Sjmallett            corrupt = unRLE_obuf_to_output_FAST  ( s );
830215976Sjmallett         if (corrupt) return BZ_DATA_ERROR;
831215976Sjmallett         if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
832215976Sjmallett            BZ_FINALISE_CRC ( s->calculatedBlockCRC );
833215976Sjmallett            if (s->verbosity >= 3)
834215976Sjmallett               VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC,
835215976Sjmallett                          s->calculatedBlockCRC );
836232812Sjmallett            if (s->verbosity >= 2) VPrintf0 ( "]" );
837215976Sjmallett            if (s->calculatedBlockCRC != s->storedBlockCRC)
838215976Sjmallett               return BZ_DATA_ERROR;
839215976Sjmallett            s->calculatedCombinedCRC
840215976Sjmallett               = (s->calculatedCombinedCRC << 1) |
841215976Sjmallett                    (s->calculatedCombinedCRC >> 31);
842215976Sjmallett            s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
843215976Sjmallett            s->state = BZ_X_BLKHDR_1;
844215976Sjmallett         } else {
845215976Sjmallett            return BZ_OK;
846215976Sjmallett         }
847215976Sjmallett      }
848215976Sjmallett      if (s->state >= BZ_X_MAGIC_1) {
849215976Sjmallett         Int32 r = BZ2_decompress ( s );
850215976Sjmallett         if (r == BZ_STREAM_END) {
851215976Sjmallett            if (s->verbosity >= 3)
852215976Sjmallett               VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x",
853215976Sjmallett                          s->storedCombinedCRC, s->calculatedCombinedCRC );
854215976Sjmallett            if (s->calculatedCombinedCRC != s->storedCombinedCRC)
855215976Sjmallett               return BZ_DATA_ERROR;
856215976Sjmallett            return r;
857215976Sjmallett         }
858215976Sjmallett         if (s->state != BZ_X_OUTPUT) return r;
859215976Sjmallett      }
860215976Sjmallett   }
861215976Sjmallett
862215976Sjmallett   AssertH ( 0, 6001 );
863215976Sjmallett
864215976Sjmallett   return 0;  /*NOTREACHED*/
865232812Sjmallett}
866215976Sjmallett
867215976Sjmallett
868232812Sjmallett/*---------------------------------------------------*/
869232812Sjmallettint BZ_API(BZ2_bzDecompressEnd)  ( bz_stream *strm )
870232812Sjmallett{
871232812Sjmallett   DState* s;
872215976Sjmallett   if (strm == NULL) return BZ_PARAM_ERROR;
873215976Sjmallett   s = strm->state;
874215976Sjmallett   if (s == NULL) return BZ_PARAM_ERROR;
875215976Sjmallett   if (s->strm != strm) return BZ_PARAM_ERROR;
876215976Sjmallett
877215976Sjmallett   if (s->tt   != NULL) BZFREE(s->tt);
878215976Sjmallett   if (s->ll16 != NULL) BZFREE(s->ll16);
879215976Sjmallett   if (s->ll4  != NULL) BZFREE(s->ll4);
880215976Sjmallett
881232812Sjmallett   BZFREE(strm->state);
882215976Sjmallett   strm->state = NULL;
883232812Sjmallett
884232812Sjmallett   return BZ_OK;
885215976Sjmallett}
886215976Sjmallett
887215976Sjmallett#ifndef BZ_NO_COMPRESS
888215976Sjmallett
889215976Sjmallett#ifndef BZ_NO_STDIO
890215976Sjmallett/*---------------------------------------------------*/
891215976Sjmallett/*--- File I/O stuff                              ---*/
892215976Sjmallett/*---------------------------------------------------*/
893215976Sjmallett
894215976Sjmallett#define BZ_SETERR(eee)                    \
895215976Sjmallett{                                         \
896215976Sjmallett   if (bzerror != NULL) *bzerror = eee;   \
897215976Sjmallett   if (bzf != NULL) bzf->lastErr = eee;   \
898215976Sjmallett}
899215976Sjmallett
900215976Sjmalletttypedef
901232812Sjmallett   struct {
902232812Sjmallett      FILE*     handle;
903232812Sjmallett      Char      buf[BZ_MAX_UNUSED];
904232812Sjmallett      Int32     bufN;
905232812Sjmallett      Bool      writing;
906232812Sjmallett      bz_stream strm;
907232812Sjmallett      Int32     lastErr;
908232812Sjmallett      Bool      initialisedOk;
909232812Sjmallett   }
910232812Sjmallett   bzFile;
911215976Sjmallett
912215976Sjmallett
913215976Sjmallett/*---------------------------------------------*/
914215976Sjmallettstatic Bool myfeof ( FILE* f )
915215976Sjmallett{
916215976Sjmallett   Int32 c = fgetc ( f );
917215976Sjmallett   if (c == EOF) return True;
918215976Sjmallett   ungetc ( c, f );
919215976Sjmallett   return False;
920215976Sjmallett}
921215976Sjmallett
922215976Sjmallett
923215976Sjmallett/*---------------------------------------------------*/
924215976SjmallettBZFILE* BZ_API(BZ2_bzWriteOpen)
925215976Sjmallett                    ( int*  bzerror,
926215976Sjmallett                      FILE* f,
927215976Sjmallett                      int   blockSize100k,
928215976Sjmallett                      int   verbosity,
929215976Sjmallett                      int   workFactor )
930215976Sjmallett{
931215976Sjmallett   Int32   ret;
932215976Sjmallett   bzFile* bzf = NULL;
933215976Sjmallett
934215976Sjmallett   BZ_SETERR(BZ_OK);
935215976Sjmallett
936215976Sjmallett   if (f == NULL ||
937215976Sjmallett       (blockSize100k < 1 || blockSize100k > 9) ||
938215976Sjmallett       (workFactor < 0 || workFactor > 250) ||
939215976Sjmallett       (verbosity < 0 || verbosity > 4))
940215976Sjmallett      { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
941215976Sjmallett
942215976Sjmallett   if (ferror(f))
943215976Sjmallett      { BZ_SETERR(BZ_IO_ERROR); return NULL; };
944215976Sjmallett
945215976Sjmallett   bzf = malloc ( sizeof(bzFile) );
946215976Sjmallett   if (bzf == NULL)
947215976Sjmallett      { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
948215976Sjmallett
949215976Sjmallett   BZ_SETERR(BZ_OK);
950215976Sjmallett   bzf->initialisedOk = False;
951215976Sjmallett   bzf->bufN          = 0;
952215976Sjmallett   bzf->handle        = f;
953232812Sjmallett   bzf->writing       = True;
954215976Sjmallett   bzf->strm.bzalloc  = NULL;
955215976Sjmallett   bzf->strm.bzfree   = NULL;
956232812Sjmallett   bzf->strm.opaque   = NULL;
957232812Sjmallett
958232812Sjmallett   if (workFactor == 0) workFactor = 30;
959232812Sjmallett   ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
960215976Sjmallett                              verbosity, workFactor );
961215976Sjmallett   if (ret != BZ_OK)
962215976Sjmallett      { BZ_SETERR(ret); free(bzf); return NULL; };
963215976Sjmallett
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