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