blob: 377b269b06db55737347d396d60e0dac8ee3433c [file] [log] [blame]
wdenk710e3502003-08-29 20:57:53 +00001#include <config.h>
wdenk8f08c5b2004-10-11 22:43:02 +00002#include <common.h>
Simon Glass9bc15642020-02-03 07:36:16 -07003#include <malloc.h>
wdenk8f08c5b2004-10-11 22:43:02 +00004#include <watchdog.h>
wdenk710e3502003-08-29 20:57:53 +00005
6/*
7 * This file is a modified version of bzlib.c from the bzip2-1.0.2
8 * distribution which can be found at http://sources.redhat.com/bzip2/
9 */
10
11/*-------------------------------------------------------------*/
12/*--- Library top-level functions. ---*/
13/*--- bzlib.c ---*/
14/*-------------------------------------------------------------*/
15
16/*--
17 This file is a part of bzip2 and/or libbzip2, a program and
18 library for lossless, block-sorting data compression.
19
20 Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
21
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions
24 are met:
25
26 1. Redistributions of source code must retain the above copyright
27 notice, this list of conditions and the following disclaimer.
28
29 2. The origin of this software must not be misrepresented; you must
30 not claim that you wrote the original software. If you use this
31 software in a product, an acknowledgment in the product
32 documentation would be appreciated but is not required.
33
34 3. Altered source versions must be plainly marked as such, and must
35 not be misrepresented as being the original software.
36
37 4. The name of the author may not be used to endorse or promote
38 products derived from this software without specific prior written
39 permission.
40
41 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
42 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
45 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
47 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
50 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
51 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52
53 Julian Seward, Cambridge, UK.
54 jseward@acm.org
55 bzip2/libbzip2 version 1.0 of 21 March 2000
56
57 This program is based on (at least) the work of:
58 Mike Burrows
59 David Wheeler
60 Peter Fenwick
61 Alistair Moffat
62 Radford Neal
63 Ian H. Witten
64 Robert Sedgewick
65 Jon L. Bentley
66
67 For more information on these sources, see the manual.
68--*/
69
70/*--
71 CHANGES
72 ~~~~~~~
73 0.9.0 -- original version.
74
75 0.9.0a/b -- no changes in this file.
76
77 0.9.0c
78 * made zero-length BZ_FLUSH work correctly in bzCompress().
79 * fixed bzWrite/bzRead to ignore zero-length requests.
80 * fixed bzread to correctly handle read requests after EOF.
81 * wrong parameter order in call to bzDecompressInit in
wdenk9c53f402003-10-15 23:53:47 +000082 bzBuffToBuffDecompress. Fixed.
wdenk710e3502003-08-29 20:57:53 +000083--*/
84
85#include "bzlib_private.h"
86
87/*---------------------------------------------------*/
88/*--- Compression stuff ---*/
89/*---------------------------------------------------*/
90
91
92/*---------------------------------------------------*/
93#ifndef BZ_NO_STDIO
94void BZ2_bz__AssertH__fail ( int errcode )
95{
96 fprintf(stderr,
97 "\n\nbzip2/libbzip2: internal error number %d.\n"
98 "This is a bug in bzip2/libbzip2, %s.\n"
99 "Please report it to me at: jseward@acm.org. If this happened\n"
100 "when you were using some program which uses libbzip2 as a\n"
101 "component, you should also report this bug to the author(s)\n"
102 "of that program. Please make an effort to report this bug;\n"
103 "timely and accurate bug reports eventually lead to higher\n"
104 "quality software. Thanks. Julian Seward, 30 December 2001.\n\n",
105 errcode,
106 BZ2_bzlibVersion()
107 );
108
109 if (errcode == 1007) {
110 fprintf(stderr,
111 "\n*** A special note about internal error number 1007 ***\n"
112 "\n"
113 "Experience suggests that a common cause of i.e. 1007\n"
114 "is unreliable memory or other hardware. The 1007 assertion\n"
115 "just happens to cross-check the results of huge numbers of\n"
116 "memory reads/writes, and so acts (unintendedly) as a stress\n"
117 "test of your memory system.\n"
118 "\n"
119 "I suggest the following: try compressing the file again,\n"
120 "possibly monitoring progress in detail with the -vv flag.\n"
121 "\n"
122 "* If the error cannot be reproduced, and/or happens at different\n"
123 " points in compression, you may have a flaky memory system.\n"
124 " Try a memory-test program. I have used Memtest86\n"
125 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
126 " Memtest86 tests memory much more thorougly than your BIOSs\n"
127 " power-on test, and may find failures that the BIOS doesn't.\n"
128 "\n"
129 "* If the error can be repeatably reproduced, this is a bug in\n"
130 " bzip2, and I would very much like to hear about it. Please\n"
131 " let me know, and, ideally, save a copy of the file causing the\n"
132 " problem -- without which I will be unable to investigate it.\n"
133 "\n"
134 );
135 }
136
137 exit(3);
138}
139#endif
140
141
142/*---------------------------------------------------*/
143static
144int bz_config_ok ( void )
145{
146 if (sizeof(int) != 4) return 0;
147 if (sizeof(short) != 2) return 0;
148 if (sizeof(char) != 1) return 0;
149 return 1;
150}
151
152
153/*---------------------------------------------------*/
154static
155void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
156{
157 void* v = malloc ( items * size );
158 return v;
159}
160
161static
162void default_bzfree ( void* opaque, void* addr )
163{
164 if (addr != NULL) free ( addr );
165}
166
167#ifndef BZ_NO_COMPRESS
168/*---------------------------------------------------*/
169static
170void prepare_new_block ( EState* s )
171{
172 Int32 i;
173 s->nblock = 0;
174 s->numZ = 0;
175 s->state_out_pos = 0;
176 BZ_INITIALISE_CRC ( s->blockCRC );
177 for (i = 0; i < 256; i++) s->inUse[i] = False;
178 s->blockNo++;
179}
180
181
182/*---------------------------------------------------*/
183static
184void init_RL ( EState* s )
185{
186 s->state_in_ch = 256;
187 s->state_in_len = 0;
188}
189
190
191static
192Bool isempty_RL ( EState* s )
193{
194 if (s->state_in_ch < 256 && s->state_in_len > 0)
195 return False; else
196 return True;
197}
198
199/*---------------------------------------------------*/
200int BZ_API(BZ2_bzCompressInit)
wdenk9c53f402003-10-15 23:53:47 +0000201 ( bz_stream* strm,
202 int blockSize100k,
203 int verbosity,
204 int workFactor )
wdenk710e3502003-08-29 20:57:53 +0000205{
206 Int32 n;
207 EState* s;
208
209 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
210
211 if (strm == NULL ||
212 blockSize100k < 1 || blockSize100k > 9 ||
213 workFactor < 0 || workFactor > 250)
214 return BZ_PARAM_ERROR;
215
216 if (workFactor == 0) workFactor = 30;
217 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
218 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
219
220 s = BZALLOC( sizeof(EState) );
221 if (s == NULL) return BZ_MEM_ERROR;
222 s->strm = strm;
223
224 s->arr1 = NULL;
225 s->arr2 = NULL;
226 s->ftab = NULL;
227
228 n = 100000 * blockSize100k;
229 s->arr1 = BZALLOC( n * sizeof(UInt32) );
230 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
231 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
232
233 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
234 if (s->arr1 != NULL) BZFREE(s->arr1);
235 if (s->arr2 != NULL) BZFREE(s->arr2);
236 if (s->ftab != NULL) BZFREE(s->ftab);
237 if (s != NULL) BZFREE(s);
238 return BZ_MEM_ERROR;
239 }
240
241 s->blockNo = 0;
242 s->state = BZ_S_INPUT;
243 s->mode = BZ_M_RUNNING;
244 s->combinedCRC = 0;
245 s->blockSize100k = blockSize100k;
246 s->nblockMAX = 100000 * blockSize100k - 19;
247 s->verbosity = verbosity;
248 s->workFactor = workFactor;
249
250 s->block = (UChar*)s->arr2;
251 s->mtfv = (UInt16*)s->arr1;
252 s->zbits = NULL;
253 s->ptr = (UInt32*)s->arr1;
254
255 strm->state = s;
256 strm->total_in_lo32 = 0;
257 strm->total_in_hi32 = 0;
258 strm->total_out_lo32 = 0;
259 strm->total_out_hi32 = 0;
260 init_RL ( s );
261 prepare_new_block ( s );
262 return BZ_OK;
263}
264
265
266/*---------------------------------------------------*/
267static
268void add_pair_to_block ( EState* s )
269{
270 Int32 i;
271 UChar ch = (UChar)(s->state_in_ch);
272 for (i = 0; i < s->state_in_len; i++) {
273 BZ_UPDATE_CRC( s->blockCRC, ch );
274 }
275 s->inUse[s->state_in_ch] = True;
276 switch (s->state_in_len) {
277 case 1:
wdenk9c53f402003-10-15 23:53:47 +0000278 s->block[s->nblock] = (UChar)ch; s->nblock++;
279 break;
wdenk710e3502003-08-29 20:57:53 +0000280 case 2:
wdenk9c53f402003-10-15 23:53:47 +0000281 s->block[s->nblock] = (UChar)ch; s->nblock++;
282 s->block[s->nblock] = (UChar)ch; s->nblock++;
283 break;
wdenk710e3502003-08-29 20:57:53 +0000284 case 3:
wdenk9c53f402003-10-15 23:53:47 +0000285 s->block[s->nblock] = (UChar)ch; s->nblock++;
286 s->block[s->nblock] = (UChar)ch; s->nblock++;
287 s->block[s->nblock] = (UChar)ch; s->nblock++;
288 break;
wdenk710e3502003-08-29 20:57:53 +0000289 default:
wdenk9c53f402003-10-15 23:53:47 +0000290 s->inUse[s->state_in_len-4] = True;
291 s->block[s->nblock] = (UChar)ch; s->nblock++;
292 s->block[s->nblock] = (UChar)ch; s->nblock++;
293 s->block[s->nblock] = (UChar)ch; s->nblock++;
294 s->block[s->nblock] = (UChar)ch; s->nblock++;
295 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
296 s->nblock++;
297 break;
wdenk710e3502003-08-29 20:57:53 +0000298 }
299}
300
301
302/*---------------------------------------------------*/
303static
304void flush_RL ( EState* s )
305{
306 if (s->state_in_ch < 256) add_pair_to_block ( s );
307 init_RL ( s );
308}
309
310
311/*---------------------------------------------------*/
312#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
313{ \
314 UInt32 zchh = (UInt32)(zchh0); \
315 /*-- fast track the common case --*/ \
316 if (zchh != zs->state_in_ch && \
317 zs->state_in_len == 1) { \
318 UChar ch = (UChar)(zs->state_in_ch); \
319 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
320 zs->inUse[zs->state_in_ch] = True; \
321 zs->block[zs->nblock] = (UChar)ch; \
322 zs->nblock++; \
323 zs->state_in_ch = zchh; \
324 } \
325 else \
326 /*-- general, uncommon cases --*/ \
327 if (zchh != zs->state_in_ch || \
328 zs->state_in_len == 255) { \
329 if (zs->state_in_ch < 256) \
wdenk9c53f402003-10-15 23:53:47 +0000330 add_pair_to_block ( zs ); \
wdenk710e3502003-08-29 20:57:53 +0000331 zs->state_in_ch = zchh; \
332 zs->state_in_len = 1; \
333 } else { \
334 zs->state_in_len++; \
335 } \
336}
337
338
339/*---------------------------------------------------*/
340static
341Bool copy_input_until_stop ( EState* s )
342{
343 Bool progress_in = False;
344
345 if (s->mode == BZ_M_RUNNING) {
346
347 /*-- fast track the common case --*/
348 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000349 /*-- block full? --*/
350 if (s->nblock >= s->nblockMAX) break;
351 /*-- no input? --*/
352 if (s->strm->avail_in == 0) break;
353 progress_in = True;
354 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
355 s->strm->next_in++;
356 s->strm->avail_in--;
357 s->strm->total_in_lo32++;
358 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
wdenk710e3502003-08-29 20:57:53 +0000359 }
360
361 } else {
362
363 /*-- general, uncommon case --*/
364 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000365 /*-- block full? --*/
366 if (s->nblock >= s->nblockMAX) break;
367 /*-- no input? --*/
368 if (s->strm->avail_in == 0) break;
369 /*-- flush/finish end? --*/
370 if (s->avail_in_expect == 0) break;
371 progress_in = True;
372 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
373 s->strm->next_in++;
374 s->strm->avail_in--;
375 s->strm->total_in_lo32++;
376 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
377 s->avail_in_expect--;
wdenk710e3502003-08-29 20:57:53 +0000378 }
379 }
380 return progress_in;
381}
382
383
384/*---------------------------------------------------*/
385static
386Bool copy_output_until_stop ( EState* s )
387{
388 Bool progress_out = False;
389
390 while (True) {
391
392 /*-- no output space? --*/
393 if (s->strm->avail_out == 0) break;
394
395 /*-- block done? --*/
396 if (s->state_out_pos >= s->numZ) break;
397
398 progress_out = True;
399 *(s->strm->next_out) = s->zbits[s->state_out_pos];
400 s->state_out_pos++;
401 s->strm->avail_out--;
402 s->strm->next_out++;
403 s->strm->total_out_lo32++;
404 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
405 }
406
407 return progress_out;
408}
409
410
411/*---------------------------------------------------*/
412static
413Bool handle_compress ( bz_stream* strm )
414{
415 Bool progress_in = False;
416 Bool progress_out = False;
417 EState* s = strm->state;
418
419 while (True) {
420
421 if (s->state == BZ_S_OUTPUT) {
wdenk9c53f402003-10-15 23:53:47 +0000422 progress_out |= copy_output_until_stop ( s );
423 if (s->state_out_pos < s->numZ) break;
424 if (s->mode == BZ_M_FINISHING &&
425 s->avail_in_expect == 0 &&
426 isempty_RL(s)) break;
427 prepare_new_block ( s );
428 s->state = BZ_S_INPUT;
429 if (s->mode == BZ_M_FLUSHING &&
430 s->avail_in_expect == 0 &&
431 isempty_RL(s)) break;
wdenk710e3502003-08-29 20:57:53 +0000432 }
433
434 if (s->state == BZ_S_INPUT) {
wdenk9c53f402003-10-15 23:53:47 +0000435 progress_in |= copy_input_until_stop ( s );
436 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
437 flush_RL ( s );
438 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
439 s->state = BZ_S_OUTPUT;
440 }
441 else
442 if (s->nblock >= s->nblockMAX) {
443 BZ2_compressBlock ( s, False );
444 s->state = BZ_S_OUTPUT;
445 }
446 else
447 if (s->strm->avail_in == 0) {
448 break;
449 }
wdenk710e3502003-08-29 20:57:53 +0000450 }
451
452 }
453
454 return progress_in || progress_out;
455}
456
457
458/*---------------------------------------------------*/
459int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
460{
461 Bool progress;
462 EState* s;
463 if (strm == NULL) return BZ_PARAM_ERROR;
464 s = strm->state;
465 if (s == NULL) return BZ_PARAM_ERROR;
466 if (s->strm != strm) return BZ_PARAM_ERROR;
467
468 preswitch:
469 switch (s->mode) {
470
471 case BZ_M_IDLE:
wdenk9c53f402003-10-15 23:53:47 +0000472 return BZ_SEQUENCE_ERROR;
wdenk710e3502003-08-29 20:57:53 +0000473
474 case BZ_M_RUNNING:
wdenk9c53f402003-10-15 23:53:47 +0000475 if (action == BZ_RUN) {
476 progress = handle_compress ( strm );
477 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
478 }
479 else
wdenk710e3502003-08-29 20:57:53 +0000480 if (action == BZ_FLUSH) {
wdenk9c53f402003-10-15 23:53:47 +0000481 s->avail_in_expect = strm->avail_in;
482 s->mode = BZ_M_FLUSHING;
483 goto preswitch;
484 }
485 else
486 if (action == BZ_FINISH) {
487 s->avail_in_expect = strm->avail_in;
488 s->mode = BZ_M_FINISHING;
489 goto preswitch;
490 }
491 else
492 return BZ_PARAM_ERROR;
wdenk710e3502003-08-29 20:57:53 +0000493
494 case BZ_M_FLUSHING:
wdenk9c53f402003-10-15 23:53:47 +0000495 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
496 if (s->avail_in_expect != s->strm->avail_in)
497 return BZ_SEQUENCE_ERROR;
498 progress = handle_compress ( strm );
499 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
500 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
501 s->mode = BZ_M_RUNNING;
502 return BZ_RUN_OK;
wdenk710e3502003-08-29 20:57:53 +0000503
504 case BZ_M_FINISHING:
wdenk9c53f402003-10-15 23:53:47 +0000505 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
506 if (s->avail_in_expect != s->strm->avail_in)
507 return BZ_SEQUENCE_ERROR;
508 progress = handle_compress ( strm );
509 if (!progress) return BZ_SEQUENCE_ERROR;
510 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
511 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
512 s->mode = BZ_M_IDLE;
513 return BZ_STREAM_END;
wdenk710e3502003-08-29 20:57:53 +0000514 }
515 return BZ_OK; /*--not reached--*/
516}
517
518
519/*---------------------------------------------------*/
520int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
521{
522 EState* s;
523 if (strm == NULL) return BZ_PARAM_ERROR;
524 s = strm->state;
525 if (s == NULL) return BZ_PARAM_ERROR;
526 if (s->strm != strm) return BZ_PARAM_ERROR;
527
528 if (s->arr1 != NULL) BZFREE(s->arr1);
529 if (s->arr2 != NULL) BZFREE(s->arr2);
530 if (s->ftab != NULL) BZFREE(s->ftab);
531 BZFREE(strm->state);
532
533 strm->state = NULL;
534
535 return BZ_OK;
536}
537#endif /* BZ_NO_COMPRESS */
538
539/*---------------------------------------------------*/
540/*--- Decompression stuff ---*/
541/*---------------------------------------------------*/
542
543/*---------------------------------------------------*/
544int BZ_API(BZ2_bzDecompressInit)
wdenk9c53f402003-10-15 23:53:47 +0000545 ( bz_stream* strm,
546 int verbosity,
547 int small )
wdenk710e3502003-08-29 20:57:53 +0000548{
549 DState* s;
550
551 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
552
553 if (strm == NULL) return BZ_PARAM_ERROR;
554 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
555 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
556
557 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
558 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
559
560 s = BZALLOC( sizeof(DState) );
561 if (s == NULL) return BZ_MEM_ERROR;
562 s->strm = strm;
563 strm->state = s;
564 s->state = BZ_X_MAGIC_1;
565 s->bsLive = 0;
566 s->bsBuff = 0;
567 s->calculatedCombinedCRC = 0;
568 strm->total_in_lo32 = 0;
569 strm->total_in_hi32 = 0;
570 strm->total_out_lo32 = 0;
571 strm->total_out_hi32 = 0;
572 s->smallDecompress = (Bool)small;
573 s->ll4 = NULL;
574 s->ll16 = NULL;
575 s->tt = NULL;
576 s->currBlockNo = 0;
577 s->verbosity = verbosity;
578
579 return BZ_OK;
580}
581
582
583/*---------------------------------------------------*/
584static
585void unRLE_obuf_to_output_FAST ( DState* s )
586{
587 UChar k1;
588
589 if (s->blockRandomised) {
590
591 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000592 /* try to finish existing run */
593 while (True) {
594 if (s->strm->avail_out == 0) return;
595 if (s->state_out_len == 0) break;
596 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
597 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
598 s->state_out_len--;
599 s->strm->next_out++;
600 s->strm->avail_out--;
601 s->strm->total_out_lo32++;
602 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
603 }
wdenk710e3502003-08-29 20:57:53 +0000604
wdenk9c53f402003-10-15 23:53:47 +0000605 /* can a new run be started? */
606 if (s->nblock_used == s->save_nblock+1) return;
wdenk710e3502003-08-29 20:57:53 +0000607
608
wdenk9c53f402003-10-15 23:53:47 +0000609 s->state_out_len = 1;
610 s->state_out_ch = s->k0;
611 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
612 k1 ^= BZ_RAND_MASK; s->nblock_used++;
613 if (s->nblock_used == s->save_nblock+1) continue;
614 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000615
wdenk9c53f402003-10-15 23:53:47 +0000616 s->state_out_len = 2;
617 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
618 k1 ^= BZ_RAND_MASK; s->nblock_used++;
619 if (s->nblock_used == s->save_nblock+1) continue;
620 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000621
wdenk9c53f402003-10-15 23:53:47 +0000622 s->state_out_len = 3;
623 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
624 k1 ^= BZ_RAND_MASK; s->nblock_used++;
625 if (s->nblock_used == s->save_nblock+1) continue;
626 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000627
wdenk9c53f402003-10-15 23:53:47 +0000628 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
629 k1 ^= BZ_RAND_MASK; s->nblock_used++;
630 s->state_out_len = ((Int32)k1) + 4;
631 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
632 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000633 }
634
635 } else {
636
637 /* restore */
638 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
639 UChar c_state_out_ch = s->state_out_ch;
640 Int32 c_state_out_len = s->state_out_len;
641 Int32 c_nblock_used = s->nblock_used;
642 Int32 c_k0 = s->k0;
643 UInt32* c_tt = s->tt;
644 UInt32 c_tPos = s->tPos;
645 char* cs_next_out = s->strm->next_out;
646 unsigned int cs_avail_out = s->strm->avail_out;
647 /* end restore */
648
649 UInt32 avail_out_INIT = cs_avail_out;
650 Int32 s_save_nblockPP = s->save_nblock+1;
651 unsigned int total_out_lo32_old;
652
653 while (True) {
654
wdenk9c53f402003-10-15 23:53:47 +0000655 /* try to finish existing run */
656 if (c_state_out_len > 0) {
657 while (True) {
658 if (cs_avail_out == 0) goto return_notr;
659 if (c_state_out_len == 1) break;
660 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
661 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
662 c_state_out_len--;
663 cs_next_out++;
664 cs_avail_out--;
665 }
666 s_state_out_len_eq_one:
667 {
668 if (cs_avail_out == 0) {
669 c_state_out_len = 1; goto return_notr;
670 };
671 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
672 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
673 cs_next_out++;
674 cs_avail_out--;
675 }
676 }
677 /* can a new run be started? */
678 if (c_nblock_used == s_save_nblockPP) {
679 c_state_out_len = 0; goto return_notr;
680 };
681 c_state_out_ch = c_k0;
682 BZ_GET_FAST_C(k1); c_nblock_used++;
683 if (k1 != c_k0) {
684 c_k0 = k1; goto s_state_out_len_eq_one;
685 };
686 if (c_nblock_used == s_save_nblockPP)
687 goto s_state_out_len_eq_one;
wdenk710e3502003-08-29 20:57:53 +0000688
wdenk9c53f402003-10-15 23:53:47 +0000689 c_state_out_len = 2;
690 BZ_GET_FAST_C(k1); c_nblock_used++;
691 if (c_nblock_used == s_save_nblockPP) continue;
692 if (k1 != c_k0) { c_k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000693
wdenk9c53f402003-10-15 23:53:47 +0000694 c_state_out_len = 3;
695 BZ_GET_FAST_C(k1); c_nblock_used++;
696 if (c_nblock_used == s_save_nblockPP) continue;
697 if (k1 != c_k0) { c_k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000698
wdenk9c53f402003-10-15 23:53:47 +0000699 BZ_GET_FAST_C(k1); c_nblock_used++;
700 c_state_out_len = ((Int32)k1) + 4;
701 BZ_GET_FAST_C(c_k0); c_nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000702 }
703
704 return_notr:
705 total_out_lo32_old = s->strm->total_out_lo32;
706 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
707 if (s->strm->total_out_lo32 < total_out_lo32_old)
wdenk9c53f402003-10-15 23:53:47 +0000708 s->strm->total_out_hi32++;
wdenk710e3502003-08-29 20:57:53 +0000709
710 /* save */
711 s->calculatedBlockCRC = c_calculatedBlockCRC;
712 s->state_out_ch = c_state_out_ch;
713 s->state_out_len = c_state_out_len;
714 s->nblock_used = c_nblock_used;
715 s->k0 = c_k0;
716 s->tt = c_tt;
717 s->tPos = c_tPos;
718 s->strm->next_out = cs_next_out;
719 s->strm->avail_out = cs_avail_out;
720 /* end save */
721 }
722}
723
724
wdenk710e3502003-08-29 20:57:53 +0000725/*---------------------------------------------------*/
726__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
727{
728 Int32 nb, na, mid;
729 nb = 0;
730 na = 256;
731 do {
732 mid = (nb + na) >> 1;
733 if (indx >= cftab[mid]) nb = mid; else na = mid;
734 }
735 while (na - nb != 1);
736 return nb;
737}
738
739
740/*---------------------------------------------------*/
741static
742void unRLE_obuf_to_output_SMALL ( DState* s )
743{
744 UChar k1;
745
746 if (s->blockRandomised) {
747
748 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000749 /* try to finish existing run */
750 while (True) {
751 if (s->strm->avail_out == 0) return;
752 if (s->state_out_len == 0) break;
753 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
754 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
755 s->state_out_len--;
756 s->strm->next_out++;
757 s->strm->avail_out--;
758 s->strm->total_out_lo32++;
759 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
760 }
wdenk710e3502003-08-29 20:57:53 +0000761
wdenk9c53f402003-10-15 23:53:47 +0000762 /* can a new run be started? */
763 if (s->nblock_used == s->save_nblock+1) return;
wdenk710e3502003-08-29 20:57:53 +0000764
765
wdenk9c53f402003-10-15 23:53:47 +0000766 s->state_out_len = 1;
767 s->state_out_ch = s->k0;
768 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
769 k1 ^= BZ_RAND_MASK; s->nblock_used++;
770 if (s->nblock_used == s->save_nblock+1) continue;
771 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000772
wdenk9c53f402003-10-15 23:53:47 +0000773 s->state_out_len = 2;
774 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
775 k1 ^= BZ_RAND_MASK; s->nblock_used++;
776 if (s->nblock_used == s->save_nblock+1) continue;
777 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000778
wdenk9c53f402003-10-15 23:53:47 +0000779 s->state_out_len = 3;
780 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
781 k1 ^= BZ_RAND_MASK; s->nblock_used++;
782 if (s->nblock_used == s->save_nblock+1) continue;
783 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000784
wdenk9c53f402003-10-15 23:53:47 +0000785 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
786 k1 ^= BZ_RAND_MASK; s->nblock_used++;
787 s->state_out_len = ((Int32)k1) + 4;
788 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
789 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000790 }
791
792 } else {
793
794 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000795 /* try to finish existing run */
796 while (True) {
797 if (s->strm->avail_out == 0) return;
798 if (s->state_out_len == 0) break;
799 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
800 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
801 s->state_out_len--;
802 s->strm->next_out++;
803 s->strm->avail_out--;
804 s->strm->total_out_lo32++;
805 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
806 }
wdenk710e3502003-08-29 20:57:53 +0000807
wdenk9c53f402003-10-15 23:53:47 +0000808 /* can a new run be started? */
809 if (s->nblock_used == s->save_nblock+1) return;
wdenk710e3502003-08-29 20:57:53 +0000810
wdenk9c53f402003-10-15 23:53:47 +0000811 s->state_out_len = 1;
812 s->state_out_ch = s->k0;
813 BZ_GET_SMALL(k1); s->nblock_used++;
814 if (s->nblock_used == s->save_nblock+1) continue;
815 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000816
wdenk9c53f402003-10-15 23:53:47 +0000817 s->state_out_len = 2;
818 BZ_GET_SMALL(k1); s->nblock_used++;
819 if (s->nblock_used == s->save_nblock+1) continue;
820 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000821
wdenk9c53f402003-10-15 23:53:47 +0000822 s->state_out_len = 3;
823 BZ_GET_SMALL(k1); s->nblock_used++;
824 if (s->nblock_used == s->save_nblock+1) continue;
825 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000826
wdenk9c53f402003-10-15 23:53:47 +0000827 BZ_GET_SMALL(k1); s->nblock_used++;
828 s->state_out_len = ((Int32)k1) + 4;
829 BZ_GET_SMALL(s->k0); s->nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000830 }
831
832 }
833}
834
835
836/*---------------------------------------------------*/
837int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
838{
839 DState* s;
840 if (strm == NULL) return BZ_PARAM_ERROR;
841 s = strm->state;
842 if (s == NULL) return BZ_PARAM_ERROR;
843 if (s->strm != strm) return BZ_PARAM_ERROR;
844
845 while (True) {
wdenk8f08c5b2004-10-11 22:43:02 +0000846#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
847 WATCHDOG_RESET();
848#endif
wdenk710e3502003-08-29 20:57:53 +0000849 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
850 if (s->state == BZ_X_OUTPUT) {
wdenk9c53f402003-10-15 23:53:47 +0000851 if (s->smallDecompress)
852 unRLE_obuf_to_output_SMALL ( s ); else
853 unRLE_obuf_to_output_FAST ( s );
854 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
855 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
856 if (s->verbosity >= 3)
857 VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
858 s->calculatedBlockCRC );
859 if (s->verbosity >= 2) VPrintf0 ( "]" );
860 if (s->calculatedBlockCRC != s->storedBlockCRC)
861 return BZ_DATA_ERROR;
862 s->calculatedCombinedCRC
863 = (s->calculatedCombinedCRC << 1) |
864 (s->calculatedCombinedCRC >> 31);
865 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
866 s->state = BZ_X_BLKHDR_1;
867 } else {
868 return BZ_OK;
869 }
wdenk710e3502003-08-29 20:57:53 +0000870 }
871 if (s->state >= BZ_X_MAGIC_1) {
wdenk9c53f402003-10-15 23:53:47 +0000872 Int32 r = BZ2_decompress ( s );
873 if (r == BZ_STREAM_END) {
874 if (s->verbosity >= 3)
875 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
876 s->storedCombinedCRC, s->calculatedCombinedCRC );
877 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
878 return BZ_DATA_ERROR;
879 return r;
880 }
881 if (s->state != BZ_X_OUTPUT) return r;
wdenk710e3502003-08-29 20:57:53 +0000882 }
883 }
884
885 AssertH ( 0, 6001 );
886
887 return 0; /*NOTREACHED*/
888}
889
890
891/*---------------------------------------------------*/
892int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
893{
894 DState* s;
895 if (strm == NULL) return BZ_PARAM_ERROR;
896 s = strm->state;
897 if (s == NULL) return BZ_PARAM_ERROR;
898 if (s->strm != strm) return BZ_PARAM_ERROR;
899
900 if (s->tt != NULL) BZFREE(s->tt);
901 if (s->ll16 != NULL) BZFREE(s->ll16);
902 if (s->ll4 != NULL) BZFREE(s->ll4);
903
904 BZFREE(strm->state);
905 strm->state = NULL;
906
907 return BZ_OK;
908}
909
910
911#ifndef BZ_NO_STDIO
912/*---------------------------------------------------*/
913/*--- File I/O stuff ---*/
914/*---------------------------------------------------*/
915
916#define BZ_SETERR(eee) \
917{ \
918 if (bzerror != NULL) *bzerror = eee; \
919 if (bzf != NULL) bzf->lastErr = eee; \
920}
921
922typedef
923 struct {
924 FILE* handle;
925 Char buf[BZ_MAX_UNUSED];
926 Int32 bufN;
927 Bool writing;
928 bz_stream strm;
929 Int32 lastErr;
930 Bool initialisedOk;
931 }
932 bzFile;
933
934
935/*---------------------------------------------*/
936static Bool myfeof ( FILE* f )
937{
938 Int32 c = fgetc ( f );
939 if (c == EOF) return True;
940 ungetc ( c, f );
941 return False;
942}
943
944
945/*---------------------------------------------------*/
946BZFILE* BZ_API(BZ2_bzWriteOpen)
wdenk9c53f402003-10-15 23:53:47 +0000947 ( int* bzerror,
948 FILE* f,
949 int blockSize100k,
950 int verbosity,
951 int workFactor )
wdenk710e3502003-08-29 20:57:53 +0000952{
953 Int32 ret;
954 bzFile* bzf = NULL;
955
956 BZ_SETERR(BZ_OK);
957
958 if (f == NULL ||
959 (blockSize100k < 1 || blockSize100k > 9) ||
960 (workFactor < 0 || workFactor > 250) ||
961 (verbosity < 0 || verbosity > 4))
962 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
963
964 if (ferror(f))
965 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
966
967 bzf = malloc ( sizeof(bzFile) );
968 if (bzf == NULL)
969 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
970
971 BZ_SETERR(BZ_OK);
972 bzf->initialisedOk = False;
973 bzf->bufN = 0;
974 bzf->handle = f;
975 bzf->writing = True;
976 bzf->strm.bzalloc = NULL;
977 bzf->strm.bzfree = NULL;
978 bzf->strm.opaque = NULL;
979
980 if (workFactor == 0) workFactor = 30;
981 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
wdenk9c53f402003-10-15 23:53:47 +0000982 verbosity, workFactor );
wdenk710e3502003-08-29 20:57:53 +0000983 if (ret != BZ_OK)
984 { BZ_SETERR(ret); free(bzf); return NULL; };
985
986 bzf->strm.avail_in = 0;
987 bzf->initialisedOk = True;
988 return bzf;
989}
990
991
wdenk710e3502003-08-29 20:57:53 +0000992/*---------------------------------------------------*/
993void BZ_API(BZ2_bzWrite)
wdenk9c53f402003-10-15 23:53:47 +0000994 ( int* bzerror,
995 BZFILE* b,
996 void* buf,
997 int len )
wdenk710e3502003-08-29 20:57:53 +0000998{
999 Int32 n, n2, ret;
1000 bzFile* bzf = (bzFile*)b;
1001
1002 BZ_SETERR(BZ_OK);
1003 if (bzf == NULL || buf == NULL || len < 0)
1004 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1005 if (!(bzf->writing))
1006 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1007 if (ferror(bzf->handle))
1008 { BZ_SETERR(BZ_IO_ERROR); return; };
1009
1010 if (len == 0)
1011 { BZ_SETERR(BZ_OK); return; };
1012
1013 bzf->strm.avail_in = len;
1014 bzf->strm.next_in = buf;
1015
1016 while (True) {
1017 bzf->strm.avail_out = BZ_MAX_UNUSED;
1018 bzf->strm.next_out = bzf->buf;
1019 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
1020 if (ret != BZ_RUN_OK)
wdenk9c53f402003-10-15 23:53:47 +00001021 { BZ_SETERR(ret); return; };
wdenk710e3502003-08-29 20:57:53 +00001022
1023 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
wdenk9c53f402003-10-15 23:53:47 +00001024 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1025 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1026 n, bzf->handle );
1027 if (n != n2 || ferror(bzf->handle))
1028 { BZ_SETERR(BZ_IO_ERROR); return; };
wdenk710e3502003-08-29 20:57:53 +00001029 }
1030
1031 if (bzf->strm.avail_in == 0)
wdenk9c53f402003-10-15 23:53:47 +00001032 { BZ_SETERR(BZ_OK); return; };
wdenk710e3502003-08-29 20:57:53 +00001033 }
1034}
1035
1036
1037/*---------------------------------------------------*/
1038void BZ_API(BZ2_bzWriteClose)
wdenk9c53f402003-10-15 23:53:47 +00001039 ( int* bzerror,
1040 BZFILE* b,
1041 int abandon,
1042 unsigned int* nbytes_in,
1043 unsigned int* nbytes_out )
wdenk710e3502003-08-29 20:57:53 +00001044{
1045 BZ2_bzWriteClose64 ( bzerror, b, abandon,
wdenk9c53f402003-10-15 23:53:47 +00001046 nbytes_in, NULL, nbytes_out, NULL );
wdenk710e3502003-08-29 20:57:53 +00001047}
1048
1049
1050void BZ_API(BZ2_bzWriteClose64)
wdenk9c53f402003-10-15 23:53:47 +00001051 ( int* bzerror,
1052 BZFILE* b,
1053 int abandon,
1054 unsigned int* nbytes_in_lo32,
1055 unsigned int* nbytes_in_hi32,
1056 unsigned int* nbytes_out_lo32,
1057 unsigned int* nbytes_out_hi32 )
wdenk710e3502003-08-29 20:57:53 +00001058{
1059 Int32 n, n2, ret;
1060 bzFile* bzf = (bzFile*)b;
1061
1062 if (bzf == NULL)
1063 { BZ_SETERR(BZ_OK); return; };
1064 if (!(bzf->writing))
1065 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1066 if (ferror(bzf->handle))
1067 { BZ_SETERR(BZ_IO_ERROR); return; };
1068
1069 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1070 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1071 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1072 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1073
1074 if ((!abandon) && bzf->lastErr == BZ_OK) {
1075 while (True) {
wdenk9c53f402003-10-15 23:53:47 +00001076 bzf->strm.avail_out = BZ_MAX_UNUSED;
1077 bzf->strm.next_out = bzf->buf;
1078 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1079 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1080 { BZ_SETERR(ret); return; };
wdenk710e3502003-08-29 20:57:53 +00001081
wdenk9c53f402003-10-15 23:53:47 +00001082 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1083 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1084 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1085 n, bzf->handle );
1086 if (n != n2 || ferror(bzf->handle))
1087 { BZ_SETERR(BZ_IO_ERROR); return; };
1088 }
wdenk710e3502003-08-29 20:57:53 +00001089
wdenk9c53f402003-10-15 23:53:47 +00001090 if (ret == BZ_STREAM_END) break;
wdenk710e3502003-08-29 20:57:53 +00001091 }
1092 }
1093
1094 if ( !abandon && !ferror ( bzf->handle ) ) {
1095 fflush ( bzf->handle );
1096 if (ferror(bzf->handle))
wdenk9c53f402003-10-15 23:53:47 +00001097 { BZ_SETERR(BZ_IO_ERROR); return; };
wdenk710e3502003-08-29 20:57:53 +00001098 }
1099
1100 if (nbytes_in_lo32 != NULL)
1101 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1102 if (nbytes_in_hi32 != NULL)
1103 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1104 if (nbytes_out_lo32 != NULL)
1105 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1106 if (nbytes_out_hi32 != NULL)
1107 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1108
1109 BZ_SETERR(BZ_OK);
1110 BZ2_bzCompressEnd ( &(bzf->strm) );
1111 free ( bzf );
1112}
1113
1114
1115/*---------------------------------------------------*/
1116BZFILE* BZ_API(BZ2_bzReadOpen)
wdenk9c53f402003-10-15 23:53:47 +00001117 ( int* bzerror,
1118 FILE* f,
1119 int verbosity,
1120 int small,
1121 void* unused,
1122 int nUnused )
wdenk710e3502003-08-29 20:57:53 +00001123{
1124 bzFile* bzf = NULL;
1125 int ret;
1126
1127 BZ_SETERR(BZ_OK);
1128
1129 if (f == NULL ||
1130 (small != 0 && small != 1) ||
1131 (verbosity < 0 || verbosity > 4) ||
1132 (unused == NULL && nUnused != 0) ||
1133 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1134 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1135
1136 if (ferror(f))
1137 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1138
1139 bzf = malloc ( sizeof(bzFile) );
1140 if (bzf == NULL)
1141 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1142
1143 BZ_SETERR(BZ_OK);
1144
1145 bzf->initialisedOk = False;
1146 bzf->handle = f;
1147 bzf->bufN = 0;
1148 bzf->writing = False;
1149 bzf->strm.bzalloc = NULL;
1150 bzf->strm.bzfree = NULL;
1151 bzf->strm.opaque = NULL;
1152
1153 while (nUnused > 0) {
1154 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1155 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1156 nUnused--;
1157 }
1158
1159 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1160 if (ret != BZ_OK)
1161 { BZ_SETERR(ret); free(bzf); return NULL; };
1162
1163 bzf->strm.avail_in = bzf->bufN;
1164 bzf->strm.next_in = bzf->buf;
1165
1166 bzf->initialisedOk = True;
1167 return bzf;
1168}
1169
1170
1171/*---------------------------------------------------*/
1172void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1173{
1174 bzFile* bzf = (bzFile*)b;
1175
1176 BZ_SETERR(BZ_OK);
1177 if (bzf == NULL)
1178 { BZ_SETERR(BZ_OK); return; };
1179
1180 if (bzf->writing)
1181 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1182
1183 if (bzf->initialisedOk)
1184 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1185 free ( bzf );
1186}
1187
1188
1189/*---------------------------------------------------*/
1190int BZ_API(BZ2_bzRead)
wdenk9c53f402003-10-15 23:53:47 +00001191 ( int* bzerror,
1192 BZFILE* b,
1193 void* buf,
1194 int len )
wdenk710e3502003-08-29 20:57:53 +00001195{
1196 Int32 n, ret;
1197 bzFile* bzf = (bzFile*)b;
1198
1199 BZ_SETERR(BZ_OK);
1200
1201 if (bzf == NULL || buf == NULL || len < 0)
1202 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1203
1204 if (bzf->writing)
1205 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1206
1207 if (len == 0)
1208 { BZ_SETERR(BZ_OK); return 0; };
1209
1210 bzf->strm.avail_out = len;
1211 bzf->strm.next_out = buf;
1212
1213 while (True) {
1214
1215 if (ferror(bzf->handle))
wdenk9c53f402003-10-15 23:53:47 +00001216 { BZ_SETERR(BZ_IO_ERROR); return 0; };
wdenk710e3502003-08-29 20:57:53 +00001217
1218 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
wdenk9c53f402003-10-15 23:53:47 +00001219 n = fread ( bzf->buf, sizeof(UChar),
1220 BZ_MAX_UNUSED, bzf->handle );
1221 if (ferror(bzf->handle))
1222 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1223 bzf->bufN = n;
1224 bzf->strm.avail_in = bzf->bufN;
1225 bzf->strm.next_in = bzf->buf;
wdenk710e3502003-08-29 20:57:53 +00001226 }
1227
1228 ret = BZ2_bzDecompress ( &(bzf->strm) );
1229
1230 if (ret != BZ_OK && ret != BZ_STREAM_END)
wdenk9c53f402003-10-15 23:53:47 +00001231 { BZ_SETERR(ret); return 0; };
wdenk710e3502003-08-29 20:57:53 +00001232
1233 if (ret == BZ_OK && myfeof(bzf->handle) &&
wdenk9c53f402003-10-15 23:53:47 +00001234 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1235 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
wdenk710e3502003-08-29 20:57:53 +00001236
1237 if (ret == BZ_STREAM_END)
wdenk9c53f402003-10-15 23:53:47 +00001238 { BZ_SETERR(BZ_STREAM_END);
1239 return len - bzf->strm.avail_out; };
wdenk710e3502003-08-29 20:57:53 +00001240 if (bzf->strm.avail_out == 0)
wdenk9c53f402003-10-15 23:53:47 +00001241 { BZ_SETERR(BZ_OK); return len; };
wdenk710e3502003-08-29 20:57:53 +00001242
1243 }
1244
1245 return 0; /*not reached*/
1246}
1247
1248
1249/*---------------------------------------------------*/
1250void BZ_API(BZ2_bzReadGetUnused)
wdenk9c53f402003-10-15 23:53:47 +00001251 ( int* bzerror,
1252 BZFILE* b,
1253 void** unused,
1254 int* nUnused )
wdenk710e3502003-08-29 20:57:53 +00001255{
1256 bzFile* bzf = (bzFile*)b;
1257 if (bzf == NULL)
1258 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1259 if (bzf->lastErr != BZ_STREAM_END)
1260 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1261 if (unused == NULL || nUnused == NULL)
1262 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1263
1264 BZ_SETERR(BZ_OK);
1265 *nUnused = bzf->strm.avail_in;
1266 *unused = bzf->strm.next_in;
1267}
1268#endif
1269
1270
1271/*---------------------------------------------------*/
1272/*--- Misc convenience stuff ---*/
1273/*---------------------------------------------------*/
1274#ifndef BZ_NO_COMPRESS
1275/*---------------------------------------------------*/
1276int BZ_API(BZ2_bzBuffToBuffCompress)
wdenk9c53f402003-10-15 23:53:47 +00001277 ( char* dest,
1278 unsigned int* destLen,
1279 char* source,
1280 unsigned int sourceLen,
1281 int blockSize100k,
1282 int verbosity,
1283 int workFactor )
wdenk710e3502003-08-29 20:57:53 +00001284{
1285 bz_stream strm;
1286 int ret;
1287
1288 if (dest == NULL || destLen == NULL ||
1289 source == NULL ||
1290 blockSize100k < 1 || blockSize100k > 9 ||
1291 verbosity < 0 || verbosity > 4 ||
1292 workFactor < 0 || workFactor > 250)
1293 return BZ_PARAM_ERROR;
1294
1295 if (workFactor == 0) workFactor = 30;
1296 strm.bzalloc = NULL;
1297 strm.bzfree = NULL;
1298 strm.opaque = NULL;
1299 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
wdenk9c53f402003-10-15 23:53:47 +00001300 verbosity, workFactor );
wdenk710e3502003-08-29 20:57:53 +00001301 if (ret != BZ_OK) return ret;
1302
1303 strm.next_in = source;
1304 strm.next_out = dest;
1305 strm.avail_in = sourceLen;
1306 strm.avail_out = *destLen;
1307
1308 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1309 if (ret == BZ_FINISH_OK) goto output_overflow;
1310 if (ret != BZ_STREAM_END) goto errhandler;
1311
1312 /* normal termination */
1313 *destLen -= strm.avail_out;
1314 BZ2_bzCompressEnd ( &strm );
1315 return BZ_OK;
1316
1317 output_overflow:
1318 BZ2_bzCompressEnd ( &strm );
1319 return BZ_OUTBUFF_FULL;
1320
1321 errhandler:
1322 BZ2_bzCompressEnd ( &strm );
1323 return ret;
1324}
1325#endif /* BZ_NO_COMPRESS */
1326
1327/*---------------------------------------------------*/
1328int BZ_API(BZ2_bzBuffToBuffDecompress)
wdenk9c53f402003-10-15 23:53:47 +00001329 ( char* dest,
1330 unsigned int* destLen,
1331 char* source,
1332 unsigned int sourceLen,
1333 int small,
1334 int verbosity )
wdenk710e3502003-08-29 20:57:53 +00001335{
1336 bz_stream strm;
1337 int ret;
1338
1339 if (destLen == NULL || source == NULL)
wdenk9c53f402003-10-15 23:53:47 +00001340 return BZ_PARAM_ERROR;
wdenk710e3502003-08-29 20:57:53 +00001341
1342 strm.bzalloc = NULL;
1343 strm.bzfree = NULL;
1344 strm.opaque = NULL;
1345 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1346 if (ret != BZ_OK) return ret;
1347
1348 strm.next_in = source;
1349 strm.next_out = dest;
1350 strm.avail_in = sourceLen;
1351 strm.avail_out = *destLen;
1352
1353 ret = BZ2_bzDecompress ( &strm );
Simon Glass487298b2014-12-02 13:17:38 -07001354 *destLen -= strm.avail_out;
wdenk710e3502003-08-29 20:57:53 +00001355 if (ret == BZ_OK) goto output_overflow_or_eof;
1356 if (ret != BZ_STREAM_END) goto errhandler;
1357
1358 /* normal termination */
wdenk710e3502003-08-29 20:57:53 +00001359 BZ2_bzDecompressEnd ( &strm );
1360 return BZ_OK;
1361
1362 output_overflow_or_eof:
1363 if (strm.avail_out > 0) {
1364 BZ2_bzDecompressEnd ( &strm );
1365 return BZ_UNEXPECTED_EOF;
1366 } else {
1367 BZ2_bzDecompressEnd ( &strm );
1368 return BZ_OUTBUFF_FULL;
1369 };
1370
1371 errhandler:
1372 BZ2_bzDecompressEnd ( &strm );
1373 return ret;
1374}
1375
1376
1377/*---------------------------------------------------*/
1378/*--
1379 Code contributed by Yoshioka Tsuneo
1380 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1381 to support better zlib compatibility.
1382 This code is not _officially_ part of libbzip2 (yet);
1383 I haven't tested it, documented it, or considered the
1384 threading-safeness of it.
1385 If this code breaks, please contact both Yoshioka and me.
1386--*/
1387/*---------------------------------------------------*/
1388
1389/*---------------------------------------------------*/
1390/*--
1391 return version like "0.9.0c".
1392--*/
1393const char * BZ_API(BZ2_bzlibVersion)(void)
1394{
1395 return BZ_VERSION;
1396}
1397
1398
1399#ifndef BZ_NO_STDIO
1400/*---------------------------------------------------*/
1401
1402#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1403# include <fcntl.h>
1404# include <io.h>
1405# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1406#else
1407# define SET_BINARY_MODE(file)
1408#endif
1409static
1410BZFILE * bzopen_or_bzdopen
wdenk9c53f402003-10-15 23:53:47 +00001411 ( const char *path, /* no use when bzdopen */
1412 int fd, /* no use when bzdopen */
1413 const char *mode,
1414 int open_mode) /* bzopen: 0, bzdopen:1 */
wdenk710e3502003-08-29 20:57:53 +00001415{
1416 int bzerr;
1417 char unused[BZ_MAX_UNUSED];
1418 int blockSize100k = 9;
1419 int writing = 0;
1420 char mode2[10] = "";
1421 FILE *fp = NULL;
1422 BZFILE *bzfp = NULL;
1423 int verbosity = 0;
1424 int workFactor = 30;
1425 int smallMode = 0;
1426 int nUnused = 0;
1427
1428 if (mode == NULL) return NULL;
1429 while (*mode) {
1430 switch (*mode) {
1431 case 'r':
wdenk9c53f402003-10-15 23:53:47 +00001432 writing = 0; break;
wdenk710e3502003-08-29 20:57:53 +00001433 case 'w':
wdenk9c53f402003-10-15 23:53:47 +00001434 writing = 1; break;
wdenk710e3502003-08-29 20:57:53 +00001435 case 's':
wdenk9c53f402003-10-15 23:53:47 +00001436 smallMode = 1; break;
wdenk710e3502003-08-29 20:57:53 +00001437 default:
wdenk9c53f402003-10-15 23:53:47 +00001438 if (isdigit((int)(*mode))) {
1439 blockSize100k = *mode-BZ_HDR_0;
1440 }
wdenk710e3502003-08-29 20:57:53 +00001441 }
1442 mode++;
1443 }
1444 strcat(mode2, writing ? "w" : "r" );
1445 strcat(mode2,"b"); /* binary mode */
1446
1447 if (open_mode==0) {
1448 if (path==NULL || strcmp(path,"")==0) {
wdenk9c53f402003-10-15 23:53:47 +00001449 fp = (writing ? stdout : stdin);
1450 SET_BINARY_MODE(fp);
wdenk710e3502003-08-29 20:57:53 +00001451 } else {
wdenk9c53f402003-10-15 23:53:47 +00001452 fp = fopen(path,mode2);
wdenk710e3502003-08-29 20:57:53 +00001453 }
1454 } else {
1455#ifdef BZ_STRICT_ANSI
1456 fp = NULL;
1457#else
1458 fp = fdopen(fd,mode2);
1459#endif
1460 }
1461 if (fp == NULL) return NULL;
1462
1463 if (writing) {
1464 /* Guard against total chaos and anarchy -- JRS */
1465 if (blockSize100k < 1) blockSize100k = 1;
1466 if (blockSize100k > 9) blockSize100k = 9;
1467 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
wdenk9c53f402003-10-15 23:53:47 +00001468 verbosity,workFactor);
wdenk710e3502003-08-29 20:57:53 +00001469 } else {
1470 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
wdenk9c53f402003-10-15 23:53:47 +00001471 unused,nUnused);
wdenk710e3502003-08-29 20:57:53 +00001472 }
1473 if (bzfp == NULL) {
1474 if (fp != stdin && fp != stdout) fclose(fp);
1475 return NULL;
1476 }
1477 return bzfp;
1478}
1479
1480
1481/*---------------------------------------------------*/
1482/*--
1483 open file for read or write.
1484 ex) bzopen("file","w9")
1485 case path="" or NULL => use stdin or stdout.
1486--*/
1487BZFILE * BZ_API(BZ2_bzopen)
wdenk9c53f402003-10-15 23:53:47 +00001488 ( const char *path,
1489 const char *mode )
wdenk710e3502003-08-29 20:57:53 +00001490{
1491 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1492}
1493
1494
1495/*---------------------------------------------------*/
1496BZFILE * BZ_API(BZ2_bzdopen)
wdenk9c53f402003-10-15 23:53:47 +00001497 ( int fd,
1498 const char *mode )
wdenk710e3502003-08-29 20:57:53 +00001499{
1500 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1501}
1502
1503
1504/*---------------------------------------------------*/
1505int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1506{
1507 int bzerr, nread;
1508 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1509 nread = BZ2_bzRead(&bzerr,b,buf,len);
1510 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1511 return nread;
1512 } else {
1513 return -1;
1514 }
1515}
1516
1517
1518/*---------------------------------------------------*/
1519int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1520{
1521 int bzerr;
1522
1523 BZ2_bzWrite(&bzerr,b,buf,len);
1524 if(bzerr == BZ_OK){
1525 return len;
1526 }else{
1527 return -1;
1528 }
1529}
1530
1531
1532/*---------------------------------------------------*/
1533int BZ_API(BZ2_bzflush) (BZFILE *b)
1534{
1535 /* do nothing now... */
1536 return 0;
1537}
1538
1539
1540/*---------------------------------------------------*/
1541void BZ_API(BZ2_bzclose) (BZFILE* b)
1542{
1543 int bzerr;
1544 FILE *fp = ((bzFile *)b)->handle;
1545
1546 if (b==NULL) {return;}
1547 if(((bzFile*)b)->writing){
1548 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1549 if(bzerr != BZ_OK){
wdenk9c53f402003-10-15 23:53:47 +00001550 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
wdenk710e3502003-08-29 20:57:53 +00001551 }
1552 }else{
1553 BZ2_bzReadClose(&bzerr,b);
1554 }
1555 if(fp!=stdin && fp!=stdout){
1556 fclose(fp);
1557 }
1558}
1559
1560
1561/*---------------------------------------------------*/
1562/*--
1563 return last error code
1564--*/
1565static char *bzerrorstrings[] = {
1566 "OK"
1567 ,"SEQUENCE_ERROR"
1568 ,"PARAM_ERROR"
1569 ,"MEM_ERROR"
1570 ,"DATA_ERROR"
1571 ,"DATA_ERROR_MAGIC"
1572 ,"IO_ERROR"
1573 ,"UNEXPECTED_EOF"
1574 ,"OUTBUFF_FULL"
1575 ,"CONFIG_ERROR"
1576 ,"???" /* for future */
1577 ,"???" /* for future */
1578 ,"???" /* for future */
1579 ,"???" /* for future */
1580 ,"???" /* for future */
1581 ,"???" /* for future */
1582};
1583
1584
1585const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1586{
1587 int err = ((bzFile *)b)->lastErr;
1588
1589 if(err>0) err = 0;
1590 *errnum = err;
1591 return bzerrorstrings[err*-1];
1592}
1593#endif
1594
Marian Balakowiczbe946ba2008-01-08 18:11:43 +01001595void bz_internal_error(int errcode)
1596{
1597 printf ("BZIP2 internal error %d\n", errcode);
1598}
wdenk710e3502003-08-29 20:57:53 +00001599
1600/*-------------------------------------------------------------*/
1601/*--- end bzlib.c ---*/
1602/*-------------------------------------------------------------*/