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