File Coverage

bzlib.c
Criterion Covered Total %
statement 304 508 59.8
branch 147 452 32.5
condition n/a
subroutine n/a
pod n/a
total 451 960 46.9


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