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