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