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