blob: 39a480e25f9abbdce7c9c1e67ccd4459a770c75d [file] [log] [blame]
Simon Glass9bc15642020-02-03 07:36:16 -07001#include <malloc.h>
wdenk8f08c5b2004-10-11 22:43:02 +00002#include <watchdog.h>
Tom Rinia877ce12023-12-14 13:16:58 -05003#include <stdio.h>
wdenk710e3502003-08-29 20:57:53 +00004
5/*
6 * This file is a modified version of bzlib.c from the bzip2-1.0.2
7 * distribution which can be found at http://sources.redhat.com/bzip2/
8 */
9
10/*-------------------------------------------------------------*/
11/*--- Library top-level functions. ---*/
12/*--- bzlib.c ---*/
13/*-------------------------------------------------------------*/
14
15/*--
16 This file is a part of bzip2 and/or libbzip2, a program and
17 library for lossless, block-sorting data compression.
18
19 Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
20
21 Redistribution and use in source and binary forms, with or without
22 modification, are permitted provided that the following conditions
23 are met:
24
25 1. Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
27
28 2. The origin of this software must not be misrepresented; you must
29 not claim that you wrote the original software. If you use this
30 software in a product, an acknowledgment in the product
31 documentation would be appreciated but is not required.
32
33 3. Altered source versions must be plainly marked as such, and must
34 not be misrepresented as being the original software.
35
36 4. The name of the author may not be used to endorse or promote
37 products derived from this software without specific prior written
38 permission.
39
40 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
41 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
42 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
44 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
46 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51
52 Julian Seward, Cambridge, UK.
53 jseward@acm.org
54 bzip2/libbzip2 version 1.0 of 21 March 2000
55
56 This program is based on (at least) the work of:
57 Mike Burrows
58 David Wheeler
59 Peter Fenwick
60 Alistair Moffat
61 Radford Neal
62 Ian H. Witten
63 Robert Sedgewick
64 Jon L. Bentley
65
66 For more information on these sources, see the manual.
67--*/
68
69/*--
70 CHANGES
71 ~~~~~~~
72 0.9.0 -- original version.
73
74 0.9.0a/b -- no changes in this file.
75
76 0.9.0c
77 * made zero-length BZ_FLUSH work correctly in bzCompress().
78 * fixed bzWrite/bzRead to ignore zero-length requests.
79 * fixed bzread to correctly handle read requests after EOF.
80 * wrong parameter order in call to bzDecompressInit in
wdenk9c53f402003-10-15 23:53:47 +000081 bzBuffToBuffDecompress. Fixed.
wdenk710e3502003-08-29 20:57:53 +000082--*/
83
84#include "bzlib_private.h"
85
86/*---------------------------------------------------*/
87/*--- Compression stuff ---*/
88/*---------------------------------------------------*/
89
wdenk710e3502003-08-29 20:57:53 +000090/*---------------------------------------------------*/
91#ifndef BZ_NO_STDIO
92void BZ2_bz__AssertH__fail ( int errcode )
93{
94 fprintf(stderr,
95 "\n\nbzip2/libbzip2: internal error number %d.\n"
96 "This is a bug in bzip2/libbzip2, %s.\n"
97 "Please report it to me at: jseward@acm.org. If this happened\n"
98 "when you were using some program which uses libbzip2 as a\n"
99 "component, you should also report this bug to the author(s)\n"
100 "of that program. Please make an effort to report this bug;\n"
101 "timely and accurate bug reports eventually lead to higher\n"
102 "quality software. Thanks. Julian Seward, 30 December 2001.\n\n",
103 errcode,
104 BZ2_bzlibVersion()
105 );
106
107 if (errcode == 1007) {
108 fprintf(stderr,
109 "\n*** A special note about internal error number 1007 ***\n"
110 "\n"
111 "Experience suggests that a common cause of i.e. 1007\n"
112 "is unreliable memory or other hardware. The 1007 assertion\n"
113 "just happens to cross-check the results of huge numbers of\n"
114 "memory reads/writes, and so acts (unintendedly) as a stress\n"
115 "test of your memory system.\n"
116 "\n"
117 "I suggest the following: try compressing the file again,\n"
118 "possibly monitoring progress in detail with the -vv flag.\n"
119 "\n"
120 "* If the error cannot be reproduced, and/or happens at different\n"
121 " points in compression, you may have a flaky memory system.\n"
122 " Try a memory-test program. I have used Memtest86\n"
123 " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
124 " Memtest86 tests memory much more thorougly than your BIOSs\n"
125 " power-on test, and may find failures that the BIOS doesn't.\n"
126 "\n"
127 "* If the error can be repeatably reproduced, this is a bug in\n"
128 " bzip2, and I would very much like to hear about it. Please\n"
129 " let me know, and, ideally, save a copy of the file causing the\n"
130 " problem -- without which I will be unable to investigate it.\n"
131 "\n"
132 );
133 }
134
135 exit(3);
136}
137#endif
138
wdenk710e3502003-08-29 20:57:53 +0000139/*---------------------------------------------------*/
140static
141int bz_config_ok ( void )
142{
143 if (sizeof(int) != 4) return 0;
144 if (sizeof(short) != 2) return 0;
145 if (sizeof(char) != 1) return 0;
146 return 1;
147}
148
wdenk710e3502003-08-29 20:57:53 +0000149/*---------------------------------------------------*/
150static
151void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
152{
153 void* v = malloc ( items * size );
154 return v;
155}
156
157static
158void default_bzfree ( void* opaque, void* addr )
159{
160 if (addr != NULL) free ( addr );
161}
162
163#ifndef BZ_NO_COMPRESS
164/*---------------------------------------------------*/
165static
166void prepare_new_block ( EState* s )
167{
168 Int32 i;
169 s->nblock = 0;
170 s->numZ = 0;
171 s->state_out_pos = 0;
172 BZ_INITIALISE_CRC ( s->blockCRC );
173 for (i = 0; i < 256; i++) s->inUse[i] = False;
174 s->blockNo++;
175}
176
wdenk710e3502003-08-29 20:57:53 +0000177/*---------------------------------------------------*/
178static
179void init_RL ( EState* s )
180{
181 s->state_in_ch = 256;
182 s->state_in_len = 0;
183}
184
wdenk710e3502003-08-29 20:57:53 +0000185static
186Bool isempty_RL ( EState* s )
187{
188 if (s->state_in_ch < 256 && s->state_in_len > 0)
189 return False; else
190 return True;
191}
192
193/*---------------------------------------------------*/
194int BZ_API(BZ2_bzCompressInit)
wdenk9c53f402003-10-15 23:53:47 +0000195 ( bz_stream* strm,
196 int blockSize100k,
197 int verbosity,
198 int workFactor )
wdenk710e3502003-08-29 20:57:53 +0000199{
200 Int32 n;
201 EState* s;
202
203 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
204
205 if (strm == NULL ||
206 blockSize100k < 1 || blockSize100k > 9 ||
207 workFactor < 0 || workFactor > 250)
208 return BZ_PARAM_ERROR;
209
210 if (workFactor == 0) workFactor = 30;
211 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
212 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
213
214 s = BZALLOC( sizeof(EState) );
215 if (s == NULL) return BZ_MEM_ERROR;
216 s->strm = strm;
217
218 s->arr1 = NULL;
219 s->arr2 = NULL;
220 s->ftab = NULL;
221
222 n = 100000 * blockSize100k;
223 s->arr1 = BZALLOC( n * sizeof(UInt32) );
224 s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
225 s->ftab = BZALLOC( 65537 * sizeof(UInt32) );
226
227 if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) {
228 if (s->arr1 != NULL) BZFREE(s->arr1);
229 if (s->arr2 != NULL) BZFREE(s->arr2);
230 if (s->ftab != NULL) BZFREE(s->ftab);
231 if (s != NULL) BZFREE(s);
232 return BZ_MEM_ERROR;
233 }
234
235 s->blockNo = 0;
236 s->state = BZ_S_INPUT;
237 s->mode = BZ_M_RUNNING;
238 s->combinedCRC = 0;
239 s->blockSize100k = blockSize100k;
240 s->nblockMAX = 100000 * blockSize100k - 19;
241 s->verbosity = verbosity;
242 s->workFactor = workFactor;
243
244 s->block = (UChar*)s->arr2;
245 s->mtfv = (UInt16*)s->arr1;
246 s->zbits = NULL;
247 s->ptr = (UInt32*)s->arr1;
248
249 strm->state = s;
250 strm->total_in_lo32 = 0;
251 strm->total_in_hi32 = 0;
252 strm->total_out_lo32 = 0;
253 strm->total_out_hi32 = 0;
254 init_RL ( s );
255 prepare_new_block ( s );
256 return BZ_OK;
257}
258
wdenk710e3502003-08-29 20:57:53 +0000259/*---------------------------------------------------*/
260static
261void add_pair_to_block ( EState* s )
262{
263 Int32 i;
264 UChar ch = (UChar)(s->state_in_ch);
265 for (i = 0; i < s->state_in_len; i++) {
266 BZ_UPDATE_CRC( s->blockCRC, ch );
267 }
268 s->inUse[s->state_in_ch] = True;
269 switch (s->state_in_len) {
270 case 1:
wdenk9c53f402003-10-15 23:53:47 +0000271 s->block[s->nblock] = (UChar)ch; s->nblock++;
272 break;
wdenk710e3502003-08-29 20:57:53 +0000273 case 2:
wdenk9c53f402003-10-15 23:53:47 +0000274 s->block[s->nblock] = (UChar)ch; s->nblock++;
275 s->block[s->nblock] = (UChar)ch; s->nblock++;
276 break;
wdenk710e3502003-08-29 20:57:53 +0000277 case 3:
wdenk9c53f402003-10-15 23:53:47 +0000278 s->block[s->nblock] = (UChar)ch; s->nblock++;
279 s->block[s->nblock] = (UChar)ch; s->nblock++;
280 s->block[s->nblock] = (UChar)ch; s->nblock++;
281 break;
wdenk710e3502003-08-29 20:57:53 +0000282 default:
wdenk9c53f402003-10-15 23:53:47 +0000283 s->inUse[s->state_in_len-4] = True;
284 s->block[s->nblock] = (UChar)ch; s->nblock++;
285 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 s->block[s->nblock] = ((UChar)(s->state_in_len-4));
289 s->nblock++;
290 break;
wdenk710e3502003-08-29 20:57:53 +0000291 }
292}
293
wdenk710e3502003-08-29 20:57:53 +0000294/*---------------------------------------------------*/
295static
296void flush_RL ( EState* s )
297{
298 if (s->state_in_ch < 256) add_pair_to_block ( s );
299 init_RL ( s );
300}
301
wdenk710e3502003-08-29 20:57:53 +0000302/*---------------------------------------------------*/
303#define ADD_CHAR_TO_BLOCK(zs,zchh0) \
304{ \
305 UInt32 zchh = (UInt32)(zchh0); \
306 /*-- fast track the common case --*/ \
307 if (zchh != zs->state_in_ch && \
308 zs->state_in_len == 1) { \
309 UChar ch = (UChar)(zs->state_in_ch); \
310 BZ_UPDATE_CRC( zs->blockCRC, ch ); \
311 zs->inUse[zs->state_in_ch] = True; \
312 zs->block[zs->nblock] = (UChar)ch; \
313 zs->nblock++; \
314 zs->state_in_ch = zchh; \
315 } \
316 else \
317 /*-- general, uncommon cases --*/ \
318 if (zchh != zs->state_in_ch || \
319 zs->state_in_len == 255) { \
320 if (zs->state_in_ch < 256) \
wdenk9c53f402003-10-15 23:53:47 +0000321 add_pair_to_block ( zs ); \
wdenk710e3502003-08-29 20:57:53 +0000322 zs->state_in_ch = zchh; \
323 zs->state_in_len = 1; \
324 } else { \
325 zs->state_in_len++; \
326 } \
327}
328
wdenk710e3502003-08-29 20:57:53 +0000329/*---------------------------------------------------*/
330static
331Bool copy_input_until_stop ( EState* s )
332{
333 Bool progress_in = False;
334
335 if (s->mode == BZ_M_RUNNING) {
336
337 /*-- fast track the common case --*/
338 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000339 /*-- block full? --*/
340 if (s->nblock >= s->nblockMAX) break;
341 /*-- no input? --*/
342 if (s->strm->avail_in == 0) break;
343 progress_in = True;
344 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
345 s->strm->next_in++;
346 s->strm->avail_in--;
347 s->strm->total_in_lo32++;
348 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
wdenk710e3502003-08-29 20:57:53 +0000349 }
350
351 } else {
352
353 /*-- general, uncommon case --*/
354 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000355 /*-- block full? --*/
356 if (s->nblock >= s->nblockMAX) break;
357 /*-- no input? --*/
358 if (s->strm->avail_in == 0) break;
359 /*-- flush/finish end? --*/
360 if (s->avail_in_expect == 0) break;
361 progress_in = True;
362 ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) );
363 s->strm->next_in++;
364 s->strm->avail_in--;
365 s->strm->total_in_lo32++;
366 if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++;
367 s->avail_in_expect--;
wdenk710e3502003-08-29 20:57:53 +0000368 }
369 }
370 return progress_in;
371}
372
wdenk710e3502003-08-29 20:57:53 +0000373/*---------------------------------------------------*/
374static
375Bool copy_output_until_stop ( EState* s )
376{
377 Bool progress_out = False;
378
379 while (True) {
380
381 /*-- no output space? --*/
382 if (s->strm->avail_out == 0) break;
383
384 /*-- block done? --*/
385 if (s->state_out_pos >= s->numZ) break;
386
387 progress_out = True;
388 *(s->strm->next_out) = s->zbits[s->state_out_pos];
389 s->state_out_pos++;
390 s->strm->avail_out--;
391 s->strm->next_out++;
392 s->strm->total_out_lo32++;
393 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
394 }
395
396 return progress_out;
397}
398
wdenk710e3502003-08-29 20:57:53 +0000399/*---------------------------------------------------*/
400static
401Bool handle_compress ( bz_stream* strm )
402{
403 Bool progress_in = False;
404 Bool progress_out = False;
405 EState* s = strm->state;
406
407 while (True) {
408
409 if (s->state == BZ_S_OUTPUT) {
wdenk9c53f402003-10-15 23:53:47 +0000410 progress_out |= copy_output_until_stop ( s );
411 if (s->state_out_pos < s->numZ) break;
412 if (s->mode == BZ_M_FINISHING &&
413 s->avail_in_expect == 0 &&
414 isempty_RL(s)) break;
415 prepare_new_block ( s );
416 s->state = BZ_S_INPUT;
417 if (s->mode == BZ_M_FLUSHING &&
418 s->avail_in_expect == 0 &&
419 isempty_RL(s)) break;
wdenk710e3502003-08-29 20:57:53 +0000420 }
421
422 if (s->state == BZ_S_INPUT) {
wdenk9c53f402003-10-15 23:53:47 +0000423 progress_in |= copy_input_until_stop ( s );
424 if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
425 flush_RL ( s );
426 BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) );
427 s->state = BZ_S_OUTPUT;
428 }
429 else
430 if (s->nblock >= s->nblockMAX) {
431 BZ2_compressBlock ( s, False );
432 s->state = BZ_S_OUTPUT;
433 }
434 else
435 if (s->strm->avail_in == 0) {
436 break;
437 }
wdenk710e3502003-08-29 20:57:53 +0000438 }
439
440 }
441
442 return progress_in || progress_out;
443}
444
wdenk710e3502003-08-29 20:57:53 +0000445/*---------------------------------------------------*/
446int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
447{
448 Bool progress;
449 EState* s;
450 if (strm == NULL) return BZ_PARAM_ERROR;
451 s = strm->state;
452 if (s == NULL) return BZ_PARAM_ERROR;
453 if (s->strm != strm) return BZ_PARAM_ERROR;
454
455 preswitch:
456 switch (s->mode) {
457
458 case BZ_M_IDLE:
wdenk9c53f402003-10-15 23:53:47 +0000459 return BZ_SEQUENCE_ERROR;
wdenk710e3502003-08-29 20:57:53 +0000460
461 case BZ_M_RUNNING:
wdenk9c53f402003-10-15 23:53:47 +0000462 if (action == BZ_RUN) {
463 progress = handle_compress ( strm );
464 return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
465 }
466 else
wdenk710e3502003-08-29 20:57:53 +0000467 if (action == BZ_FLUSH) {
wdenk9c53f402003-10-15 23:53:47 +0000468 s->avail_in_expect = strm->avail_in;
469 s->mode = BZ_M_FLUSHING;
470 goto preswitch;
471 }
472 else
473 if (action == BZ_FINISH) {
474 s->avail_in_expect = strm->avail_in;
475 s->mode = BZ_M_FINISHING;
476 goto preswitch;
477 }
478 else
479 return BZ_PARAM_ERROR;
wdenk710e3502003-08-29 20:57:53 +0000480
481 case BZ_M_FLUSHING:
wdenk9c53f402003-10-15 23:53:47 +0000482 if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR;
483 if (s->avail_in_expect != s->strm->avail_in)
484 return BZ_SEQUENCE_ERROR;
485 progress = handle_compress ( strm );
486 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
487 s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
488 s->mode = BZ_M_RUNNING;
489 return BZ_RUN_OK;
wdenk710e3502003-08-29 20:57:53 +0000490
491 case BZ_M_FINISHING:
wdenk9c53f402003-10-15 23:53:47 +0000492 if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR;
493 if (s->avail_in_expect != s->strm->avail_in)
494 return BZ_SEQUENCE_ERROR;
495 progress = handle_compress ( strm );
496 if (!progress) return BZ_SEQUENCE_ERROR;
497 if (s->avail_in_expect > 0 || !isempty_RL(s) ||
498 s->state_out_pos < s->numZ) return BZ_FINISH_OK;
499 s->mode = BZ_M_IDLE;
500 return BZ_STREAM_END;
wdenk710e3502003-08-29 20:57:53 +0000501 }
502 return BZ_OK; /*--not reached--*/
503}
504
wdenk710e3502003-08-29 20:57:53 +0000505/*---------------------------------------------------*/
506int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm )
507{
508 EState* s;
509 if (strm == NULL) return BZ_PARAM_ERROR;
510 s = strm->state;
511 if (s == NULL) return BZ_PARAM_ERROR;
512 if (s->strm != strm) return BZ_PARAM_ERROR;
513
514 if (s->arr1 != NULL) BZFREE(s->arr1);
515 if (s->arr2 != NULL) BZFREE(s->arr2);
516 if (s->ftab != NULL) BZFREE(s->ftab);
517 BZFREE(strm->state);
518
519 strm->state = NULL;
520
521 return BZ_OK;
522}
523#endif /* BZ_NO_COMPRESS */
524
525/*---------------------------------------------------*/
526/*--- Decompression stuff ---*/
527/*---------------------------------------------------*/
528
529/*---------------------------------------------------*/
530int BZ_API(BZ2_bzDecompressInit)
wdenk9c53f402003-10-15 23:53:47 +0000531 ( bz_stream* strm,
532 int verbosity,
533 int small )
wdenk710e3502003-08-29 20:57:53 +0000534{
535 DState* s;
536
537 if (!bz_config_ok()) return BZ_CONFIG_ERROR;
538
539 if (strm == NULL) return BZ_PARAM_ERROR;
540 if (small != 0 && small != 1) return BZ_PARAM_ERROR;
541 if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
542
543 if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
544 if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
545
546 s = BZALLOC( sizeof(DState) );
547 if (s == NULL) return BZ_MEM_ERROR;
548 s->strm = strm;
549 strm->state = s;
550 s->state = BZ_X_MAGIC_1;
551 s->bsLive = 0;
552 s->bsBuff = 0;
553 s->calculatedCombinedCRC = 0;
554 strm->total_in_lo32 = 0;
555 strm->total_in_hi32 = 0;
556 strm->total_out_lo32 = 0;
557 strm->total_out_hi32 = 0;
558 s->smallDecompress = (Bool)small;
559 s->ll4 = NULL;
560 s->ll16 = NULL;
561 s->tt = NULL;
562 s->currBlockNo = 0;
563 s->verbosity = verbosity;
564
565 return BZ_OK;
566}
567
wdenk710e3502003-08-29 20:57:53 +0000568/*---------------------------------------------------*/
569static
570void unRLE_obuf_to_output_FAST ( DState* s )
571{
572 UChar k1;
573
574 if (s->blockRandomised) {
575
576 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000577 /* try to finish existing run */
578 while (True) {
579 if (s->strm->avail_out == 0) return;
580 if (s->state_out_len == 0) break;
581 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
582 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
583 s->state_out_len--;
584 s->strm->next_out++;
585 s->strm->avail_out--;
586 s->strm->total_out_lo32++;
587 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
588 }
wdenk710e3502003-08-29 20:57:53 +0000589
wdenk9c53f402003-10-15 23:53:47 +0000590 /* can a new run be started? */
591 if (s->nblock_used == s->save_nblock+1) return;
wdenk710e3502003-08-29 20:57:53 +0000592
wdenk9c53f402003-10-15 23:53:47 +0000593 s->state_out_len = 1;
594 s->state_out_ch = s->k0;
595 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
596 k1 ^= BZ_RAND_MASK; s->nblock_used++;
597 if (s->nblock_used == s->save_nblock+1) continue;
598 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000599
wdenk9c53f402003-10-15 23:53:47 +0000600 s->state_out_len = 2;
601 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
602 k1 ^= BZ_RAND_MASK; s->nblock_used++;
603 if (s->nblock_used == s->save_nblock+1) continue;
604 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000605
wdenk9c53f402003-10-15 23:53:47 +0000606 s->state_out_len = 3;
607 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
608 k1 ^= BZ_RAND_MASK; s->nblock_used++;
609 if (s->nblock_used == s->save_nblock+1) continue;
610 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000611
wdenk9c53f402003-10-15 23:53:47 +0000612 BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;
613 k1 ^= BZ_RAND_MASK; s->nblock_used++;
614 s->state_out_len = ((Int32)k1) + 4;
615 BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;
616 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000617 }
618
619 } else {
620
621 /* restore */
622 UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
623 UChar c_state_out_ch = s->state_out_ch;
624 Int32 c_state_out_len = s->state_out_len;
625 Int32 c_nblock_used = s->nblock_used;
626 Int32 c_k0 = s->k0;
627 UInt32* c_tt = s->tt;
628 UInt32 c_tPos = s->tPos;
629 char* cs_next_out = s->strm->next_out;
630 unsigned int cs_avail_out = s->strm->avail_out;
631 /* end restore */
632
633 UInt32 avail_out_INIT = cs_avail_out;
634 Int32 s_save_nblockPP = s->save_nblock+1;
635 unsigned int total_out_lo32_old;
636
637 while (True) {
638
wdenk9c53f402003-10-15 23:53:47 +0000639 /* try to finish existing run */
640 if (c_state_out_len > 0) {
641 while (True) {
642 if (cs_avail_out == 0) goto return_notr;
643 if (c_state_out_len == 1) break;
644 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
645 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
646 c_state_out_len--;
647 cs_next_out++;
648 cs_avail_out--;
649 }
650 s_state_out_len_eq_one:
651 {
652 if (cs_avail_out == 0) {
653 c_state_out_len = 1; goto return_notr;
654 };
655 *( (UChar*)(cs_next_out) ) = c_state_out_ch;
656 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch );
657 cs_next_out++;
658 cs_avail_out--;
659 }
660 }
661 /* can a new run be started? */
662 if (c_nblock_used == s_save_nblockPP) {
663 c_state_out_len = 0; goto return_notr;
664 };
665 c_state_out_ch = c_k0;
666 BZ_GET_FAST_C(k1); c_nblock_used++;
667 if (k1 != c_k0) {
668 c_k0 = k1; goto s_state_out_len_eq_one;
669 };
670 if (c_nblock_used == s_save_nblockPP)
671 goto s_state_out_len_eq_one;
wdenk710e3502003-08-29 20:57:53 +0000672
wdenk9c53f402003-10-15 23:53:47 +0000673 c_state_out_len = 2;
674 BZ_GET_FAST_C(k1); c_nblock_used++;
675 if (c_nblock_used == s_save_nblockPP) continue;
676 if (k1 != c_k0) { c_k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000677
wdenk9c53f402003-10-15 23:53:47 +0000678 c_state_out_len = 3;
679 BZ_GET_FAST_C(k1); c_nblock_used++;
680 if (c_nblock_used == s_save_nblockPP) continue;
681 if (k1 != c_k0) { c_k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000682
wdenk9c53f402003-10-15 23:53:47 +0000683 BZ_GET_FAST_C(k1); c_nblock_used++;
684 c_state_out_len = ((Int32)k1) + 4;
685 BZ_GET_FAST_C(c_k0); c_nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000686 }
687
688 return_notr:
689 total_out_lo32_old = s->strm->total_out_lo32;
690 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
691 if (s->strm->total_out_lo32 < total_out_lo32_old)
wdenk9c53f402003-10-15 23:53:47 +0000692 s->strm->total_out_hi32++;
wdenk710e3502003-08-29 20:57:53 +0000693
694 /* save */
695 s->calculatedBlockCRC = c_calculatedBlockCRC;
696 s->state_out_ch = c_state_out_ch;
697 s->state_out_len = c_state_out_len;
698 s->nblock_used = c_nblock_used;
699 s->k0 = c_k0;
700 s->tt = c_tt;
701 s->tPos = c_tPos;
702 s->strm->next_out = cs_next_out;
703 s->strm->avail_out = cs_avail_out;
704 /* end save */
705 }
706}
707
wdenk710e3502003-08-29 20:57:53 +0000708/*---------------------------------------------------*/
709__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
710{
711 Int32 nb, na, mid;
712 nb = 0;
713 na = 256;
714 do {
715 mid = (nb + na) >> 1;
716 if (indx >= cftab[mid]) nb = mid; else na = mid;
717 }
718 while (na - nb != 1);
719 return nb;
720}
721
wdenk710e3502003-08-29 20:57:53 +0000722/*---------------------------------------------------*/
723static
724void unRLE_obuf_to_output_SMALL ( DState* s )
725{
726 UChar k1;
727
728 if (s->blockRandomised) {
729
730 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000731 /* try to finish existing run */
732 while (True) {
733 if (s->strm->avail_out == 0) return;
734 if (s->state_out_len == 0) break;
735 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
736 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
737 s->state_out_len--;
738 s->strm->next_out++;
739 s->strm->avail_out--;
740 s->strm->total_out_lo32++;
741 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
742 }
wdenk710e3502003-08-29 20:57:53 +0000743
wdenk9c53f402003-10-15 23:53:47 +0000744 /* can a new run be started? */
745 if (s->nblock_used == s->save_nblock+1) return;
wdenk710e3502003-08-29 20:57:53 +0000746
wdenk9c53f402003-10-15 23:53:47 +0000747 s->state_out_len = 1;
748 s->state_out_ch = s->k0;
749 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
750 k1 ^= BZ_RAND_MASK; s->nblock_used++;
751 if (s->nblock_used == s->save_nblock+1) continue;
752 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000753
wdenk9c53f402003-10-15 23:53:47 +0000754 s->state_out_len = 2;
755 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
756 k1 ^= BZ_RAND_MASK; s->nblock_used++;
757 if (s->nblock_used == s->save_nblock+1) continue;
758 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000759
wdenk9c53f402003-10-15 23:53:47 +0000760 s->state_out_len = 3;
761 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
762 k1 ^= BZ_RAND_MASK; s->nblock_used++;
763 if (s->nblock_used == s->save_nblock+1) continue;
764 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000765
wdenk9c53f402003-10-15 23:53:47 +0000766 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;
767 k1 ^= BZ_RAND_MASK; s->nblock_used++;
768 s->state_out_len = ((Int32)k1) + 4;
769 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;
770 s->k0 ^= BZ_RAND_MASK; s->nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000771 }
772
773 } else {
774
775 while (True) {
wdenk9c53f402003-10-15 23:53:47 +0000776 /* try to finish existing run */
777 while (True) {
778 if (s->strm->avail_out == 0) return;
779 if (s->state_out_len == 0) break;
780 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch;
781 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch );
782 s->state_out_len--;
783 s->strm->next_out++;
784 s->strm->avail_out--;
785 s->strm->total_out_lo32++;
786 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
787 }
wdenk710e3502003-08-29 20:57:53 +0000788
wdenk9c53f402003-10-15 23:53:47 +0000789 /* can a new run be started? */
790 if (s->nblock_used == s->save_nblock+1) return;
wdenk710e3502003-08-29 20:57:53 +0000791
wdenk9c53f402003-10-15 23:53:47 +0000792 s->state_out_len = 1;
793 s->state_out_ch = s->k0;
794 BZ_GET_SMALL(k1); s->nblock_used++;
795 if (s->nblock_used == s->save_nblock+1) continue;
796 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000797
wdenk9c53f402003-10-15 23:53:47 +0000798 s->state_out_len = 2;
799 BZ_GET_SMALL(k1); s->nblock_used++;
800 if (s->nblock_used == s->save_nblock+1) continue;
801 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000802
wdenk9c53f402003-10-15 23:53:47 +0000803 s->state_out_len = 3;
804 BZ_GET_SMALL(k1); s->nblock_used++;
805 if (s->nblock_used == s->save_nblock+1) continue;
806 if (k1 != s->k0) { s->k0 = k1; continue; };
wdenk710e3502003-08-29 20:57:53 +0000807
wdenk9c53f402003-10-15 23:53:47 +0000808 BZ_GET_SMALL(k1); s->nblock_used++;
809 s->state_out_len = ((Int32)k1) + 4;
810 BZ_GET_SMALL(s->k0); s->nblock_used++;
wdenk710e3502003-08-29 20:57:53 +0000811 }
812
813 }
814}
815
wdenk710e3502003-08-29 20:57:53 +0000816/*---------------------------------------------------*/
817int BZ_API(BZ2_bzDecompress) ( bz_stream *strm )
818{
819 DState* s;
820 if (strm == NULL) return BZ_PARAM_ERROR;
821 s = strm->state;
822 if (s == NULL) return BZ_PARAM_ERROR;
823 if (s->strm != strm) return BZ_PARAM_ERROR;
824
825 while (True) {
wdenk8f08c5b2004-10-11 22:43:02 +0000826#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
Stefan Roese80877fa2022-09-02 14:10:46 +0200827 schedule();
wdenk8f08c5b2004-10-11 22:43:02 +0000828#endif
wdenk710e3502003-08-29 20:57:53 +0000829 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
830 if (s->state == BZ_X_OUTPUT) {
wdenk9c53f402003-10-15 23:53:47 +0000831 if (s->smallDecompress)
832 unRLE_obuf_to_output_SMALL ( s ); else
833 unRLE_obuf_to_output_FAST ( s );
834 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) {
835 BZ_FINALISE_CRC ( s->calculatedBlockCRC );
836 if (s->verbosity >= 3)
837 VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC,
838 s->calculatedBlockCRC );
839 if (s->verbosity >= 2) VPrintf0 ( "]" );
840 if (s->calculatedBlockCRC != s->storedBlockCRC)
841 return BZ_DATA_ERROR;
842 s->calculatedCombinedCRC
843 = (s->calculatedCombinedCRC << 1) |
844 (s->calculatedCombinedCRC >> 31);
845 s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
846 s->state = BZ_X_BLKHDR_1;
847 } else {
848 return BZ_OK;
849 }
wdenk710e3502003-08-29 20:57:53 +0000850 }
851 if (s->state >= BZ_X_MAGIC_1) {
wdenk9c53f402003-10-15 23:53:47 +0000852 Int32 r = BZ2_decompress ( s );
853 if (r == BZ_STREAM_END) {
854 if (s->verbosity >= 3)
855 VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x",
856 s->storedCombinedCRC, s->calculatedCombinedCRC );
857 if (s->calculatedCombinedCRC != s->storedCombinedCRC)
858 return BZ_DATA_ERROR;
859 return r;
860 }
861 if (s->state != BZ_X_OUTPUT) return r;
wdenk710e3502003-08-29 20:57:53 +0000862 }
863 }
864
865 AssertH ( 0, 6001 );
866
867 return 0; /*NOTREACHED*/
868}
869
wdenk710e3502003-08-29 20:57:53 +0000870/*---------------------------------------------------*/
871int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm )
872{
873 DState* s;
874 if (strm == NULL) return BZ_PARAM_ERROR;
875 s = strm->state;
876 if (s == NULL) return BZ_PARAM_ERROR;
877 if (s->strm != strm) return BZ_PARAM_ERROR;
878
879 if (s->tt != NULL) BZFREE(s->tt);
880 if (s->ll16 != NULL) BZFREE(s->ll16);
881 if (s->ll4 != NULL) BZFREE(s->ll4);
882
883 BZFREE(strm->state);
884 strm->state = NULL;
885
886 return BZ_OK;
887}
888
wdenk710e3502003-08-29 20:57:53 +0000889#ifndef BZ_NO_STDIO
890/*---------------------------------------------------*/
891/*--- File I/O stuff ---*/
892/*---------------------------------------------------*/
893
894#define BZ_SETERR(eee) \
895{ \
896 if (bzerror != NULL) *bzerror = eee; \
897 if (bzf != NULL) bzf->lastErr = eee; \
898}
899
900typedef
901 struct {
902 FILE* handle;
903 Char buf[BZ_MAX_UNUSED];
904 Int32 bufN;
905 Bool writing;
906 bz_stream strm;
907 Int32 lastErr;
908 Bool initialisedOk;
909 }
910 bzFile;
911
wdenk710e3502003-08-29 20:57:53 +0000912/*---------------------------------------------*/
913static 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
wdenk710e3502003-08-29 20:57:53 +0000921/*---------------------------------------------------*/
922BZFILE* BZ_API(BZ2_bzWriteOpen)
wdenk9c53f402003-10-15 23:53:47 +0000923 ( int* bzerror,
924 FILE* f,
925 int blockSize100k,
926 int verbosity,
927 int workFactor )
wdenk710e3502003-08-29 20:57:53 +0000928{
929 Int32 ret;
930 bzFile* bzf = NULL;
931
932 BZ_SETERR(BZ_OK);
933
934 if (f == NULL ||
935 (blockSize100k < 1 || blockSize100k > 9) ||
936 (workFactor < 0 || workFactor > 250) ||
937 (verbosity < 0 || verbosity > 4))
938 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
939
940 if (ferror(f))
941 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
942
943 bzf = malloc ( sizeof(bzFile) );
944 if (bzf == NULL)
945 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
946
947 BZ_SETERR(BZ_OK);
948 bzf->initialisedOk = False;
949 bzf->bufN = 0;
950 bzf->handle = f;
951 bzf->writing = True;
952 bzf->strm.bzalloc = NULL;
953 bzf->strm.bzfree = NULL;
954 bzf->strm.opaque = NULL;
955
956 if (workFactor == 0) workFactor = 30;
957 ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k,
wdenk9c53f402003-10-15 23:53:47 +0000958 verbosity, workFactor );
wdenk710e3502003-08-29 20:57:53 +0000959 if (ret != BZ_OK)
960 { BZ_SETERR(ret); free(bzf); return NULL; };
961
962 bzf->strm.avail_in = 0;
963 bzf->initialisedOk = True;
964 return bzf;
965}
966
wdenk710e3502003-08-29 20:57:53 +0000967/*---------------------------------------------------*/
968void BZ_API(BZ2_bzWrite)
wdenk9c53f402003-10-15 23:53:47 +0000969 ( int* bzerror,
970 BZFILE* b,
971 void* buf,
972 int len )
wdenk710e3502003-08-29 20:57:53 +0000973{
974 Int32 n, n2, ret;
975 bzFile* bzf = (bzFile*)b;
976
977 BZ_SETERR(BZ_OK);
978 if (bzf == NULL || buf == NULL || len < 0)
979 { BZ_SETERR(BZ_PARAM_ERROR); return; };
980 if (!(bzf->writing))
981 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
982 if (ferror(bzf->handle))
983 { BZ_SETERR(BZ_IO_ERROR); return; };
984
985 if (len == 0)
986 { BZ_SETERR(BZ_OK); return; };
987
988 bzf->strm.avail_in = len;
989 bzf->strm.next_in = buf;
990
991 while (True) {
992 bzf->strm.avail_out = BZ_MAX_UNUSED;
993 bzf->strm.next_out = bzf->buf;
994 ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN );
995 if (ret != BZ_RUN_OK)
wdenk9c53f402003-10-15 23:53:47 +0000996 { BZ_SETERR(ret); return; };
wdenk710e3502003-08-29 20:57:53 +0000997
998 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
wdenk9c53f402003-10-15 23:53:47 +0000999 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1000 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1001 n, bzf->handle );
1002 if (n != n2 || ferror(bzf->handle))
1003 { BZ_SETERR(BZ_IO_ERROR); return; };
wdenk710e3502003-08-29 20:57:53 +00001004 }
1005
1006 if (bzf->strm.avail_in == 0)
wdenk9c53f402003-10-15 23:53:47 +00001007 { BZ_SETERR(BZ_OK); return; };
wdenk710e3502003-08-29 20:57:53 +00001008 }
1009}
1010
wdenk710e3502003-08-29 20:57:53 +00001011/*---------------------------------------------------*/
1012void BZ_API(BZ2_bzWriteClose)
wdenk9c53f402003-10-15 23:53:47 +00001013 ( int* bzerror,
1014 BZFILE* b,
1015 int abandon,
1016 unsigned int* nbytes_in,
1017 unsigned int* nbytes_out )
wdenk710e3502003-08-29 20:57:53 +00001018{
1019 BZ2_bzWriteClose64 ( bzerror, b, abandon,
wdenk9c53f402003-10-15 23:53:47 +00001020 nbytes_in, NULL, nbytes_out, NULL );
wdenk710e3502003-08-29 20:57:53 +00001021}
1022
wdenk710e3502003-08-29 20:57:53 +00001023void BZ_API(BZ2_bzWriteClose64)
wdenk9c53f402003-10-15 23:53:47 +00001024 ( int* bzerror,
1025 BZFILE* b,
1026 int abandon,
1027 unsigned int* nbytes_in_lo32,
1028 unsigned int* nbytes_in_hi32,
1029 unsigned int* nbytes_out_lo32,
1030 unsigned int* nbytes_out_hi32 )
wdenk710e3502003-08-29 20:57:53 +00001031{
1032 Int32 n, n2, ret;
1033 bzFile* bzf = (bzFile*)b;
1034
1035 if (bzf == NULL)
1036 { BZ_SETERR(BZ_OK); return; };
1037 if (!(bzf->writing))
1038 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1039 if (ferror(bzf->handle))
1040 { BZ_SETERR(BZ_IO_ERROR); return; };
1041
1042 if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0;
1043 if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0;
1044 if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0;
1045 if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0;
1046
1047 if ((!abandon) && bzf->lastErr == BZ_OK) {
1048 while (True) {
wdenk9c53f402003-10-15 23:53:47 +00001049 bzf->strm.avail_out = BZ_MAX_UNUSED;
1050 bzf->strm.next_out = bzf->buf;
1051 ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH );
1052 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
1053 { BZ_SETERR(ret); return; };
wdenk710e3502003-08-29 20:57:53 +00001054
wdenk9c53f402003-10-15 23:53:47 +00001055 if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1056 n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1057 n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar),
1058 n, bzf->handle );
1059 if (n != n2 || ferror(bzf->handle))
1060 { BZ_SETERR(BZ_IO_ERROR); return; };
1061 }
wdenk710e3502003-08-29 20:57:53 +00001062
wdenk9c53f402003-10-15 23:53:47 +00001063 if (ret == BZ_STREAM_END) break;
wdenk710e3502003-08-29 20:57:53 +00001064 }
1065 }
1066
1067 if ( !abandon && !ferror ( bzf->handle ) ) {
1068 fflush ( bzf->handle );
1069 if (ferror(bzf->handle))
wdenk9c53f402003-10-15 23:53:47 +00001070 { BZ_SETERR(BZ_IO_ERROR); return; };
wdenk710e3502003-08-29 20:57:53 +00001071 }
1072
1073 if (nbytes_in_lo32 != NULL)
1074 *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1075 if (nbytes_in_hi32 != NULL)
1076 *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1077 if (nbytes_out_lo32 != NULL)
1078 *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1079 if (nbytes_out_hi32 != NULL)
1080 *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1081
1082 BZ_SETERR(BZ_OK);
1083 BZ2_bzCompressEnd ( &(bzf->strm) );
1084 free ( bzf );
1085}
1086
wdenk710e3502003-08-29 20:57:53 +00001087/*---------------------------------------------------*/
1088BZFILE* BZ_API(BZ2_bzReadOpen)
wdenk9c53f402003-10-15 23:53:47 +00001089 ( int* bzerror,
1090 FILE* f,
1091 int verbosity,
1092 int small,
1093 void* unused,
1094 int nUnused )
wdenk710e3502003-08-29 20:57:53 +00001095{
1096 bzFile* bzf = NULL;
1097 int ret;
1098
1099 BZ_SETERR(BZ_OK);
1100
1101 if (f == NULL ||
1102 (small != 0 && small != 1) ||
1103 (verbosity < 0 || verbosity > 4) ||
1104 (unused == NULL && nUnused != 0) ||
1105 (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
1106 { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
1107
1108 if (ferror(f))
1109 { BZ_SETERR(BZ_IO_ERROR); return NULL; };
1110
1111 bzf = malloc ( sizeof(bzFile) );
1112 if (bzf == NULL)
1113 { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
1114
1115 BZ_SETERR(BZ_OK);
1116
1117 bzf->initialisedOk = False;
1118 bzf->handle = f;
1119 bzf->bufN = 0;
1120 bzf->writing = False;
1121 bzf->strm.bzalloc = NULL;
1122 bzf->strm.bzfree = NULL;
1123 bzf->strm.opaque = NULL;
1124
1125 while (nUnused > 0) {
1126 bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
1127 unused = ((void*)( 1 + ((UChar*)(unused)) ));
1128 nUnused--;
1129 }
1130
1131 ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
1132 if (ret != BZ_OK)
1133 { BZ_SETERR(ret); free(bzf); return NULL; };
1134
1135 bzf->strm.avail_in = bzf->bufN;
1136 bzf->strm.next_in = bzf->buf;
1137
1138 bzf->initialisedOk = True;
1139 return bzf;
1140}
1141
wdenk710e3502003-08-29 20:57:53 +00001142/*---------------------------------------------------*/
1143void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
1144{
1145 bzFile* bzf = (bzFile*)b;
1146
1147 BZ_SETERR(BZ_OK);
1148 if (bzf == NULL)
1149 { BZ_SETERR(BZ_OK); return; };
1150
1151 if (bzf->writing)
1152 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1153
1154 if (bzf->initialisedOk)
1155 (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
1156 free ( bzf );
1157}
1158
wdenk710e3502003-08-29 20:57:53 +00001159/*---------------------------------------------------*/
1160int BZ_API(BZ2_bzRead)
wdenk9c53f402003-10-15 23:53:47 +00001161 ( int* bzerror,
1162 BZFILE* b,
1163 void* buf,
1164 int len )
wdenk710e3502003-08-29 20:57:53 +00001165{
1166 Int32 n, ret;
1167 bzFile* bzf = (bzFile*)b;
1168
1169 BZ_SETERR(BZ_OK);
1170
1171 if (bzf == NULL || buf == NULL || len < 0)
1172 { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
1173
1174 if (bzf->writing)
1175 { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
1176
1177 if (len == 0)
1178 { BZ_SETERR(BZ_OK); return 0; };
1179
1180 bzf->strm.avail_out = len;
1181 bzf->strm.next_out = buf;
1182
1183 while (True) {
1184
1185 if (ferror(bzf->handle))
wdenk9c53f402003-10-15 23:53:47 +00001186 { BZ_SETERR(BZ_IO_ERROR); return 0; };
wdenk710e3502003-08-29 20:57:53 +00001187
1188 if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
wdenk9c53f402003-10-15 23:53:47 +00001189 n = fread ( bzf->buf, sizeof(UChar),
1190 BZ_MAX_UNUSED, bzf->handle );
1191 if (ferror(bzf->handle))
1192 { BZ_SETERR(BZ_IO_ERROR); return 0; };
1193 bzf->bufN = n;
1194 bzf->strm.avail_in = bzf->bufN;
1195 bzf->strm.next_in = bzf->buf;
wdenk710e3502003-08-29 20:57:53 +00001196 }
1197
1198 ret = BZ2_bzDecompress ( &(bzf->strm) );
1199
1200 if (ret != BZ_OK && ret != BZ_STREAM_END)
wdenk9c53f402003-10-15 23:53:47 +00001201 { BZ_SETERR(ret); return 0; };
wdenk710e3502003-08-29 20:57:53 +00001202
1203 if (ret == BZ_OK && myfeof(bzf->handle) &&
wdenk9c53f402003-10-15 23:53:47 +00001204 bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
1205 { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
wdenk710e3502003-08-29 20:57:53 +00001206
1207 if (ret == BZ_STREAM_END)
wdenk9c53f402003-10-15 23:53:47 +00001208 { BZ_SETERR(BZ_STREAM_END);
1209 return len - bzf->strm.avail_out; };
wdenk710e3502003-08-29 20:57:53 +00001210 if (bzf->strm.avail_out == 0)
wdenk9c53f402003-10-15 23:53:47 +00001211 { BZ_SETERR(BZ_OK); return len; };
wdenk710e3502003-08-29 20:57:53 +00001212
1213 }
1214
1215 return 0; /*not reached*/
1216}
1217
wdenk710e3502003-08-29 20:57:53 +00001218/*---------------------------------------------------*/
1219void BZ_API(BZ2_bzReadGetUnused)
wdenk9c53f402003-10-15 23:53:47 +00001220 ( int* bzerror,
1221 BZFILE* b,
1222 void** unused,
1223 int* nUnused )
wdenk710e3502003-08-29 20:57:53 +00001224{
1225 bzFile* bzf = (bzFile*)b;
1226 if (bzf == NULL)
1227 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1228 if (bzf->lastErr != BZ_STREAM_END)
1229 { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
1230 if (unused == NULL || nUnused == NULL)
1231 { BZ_SETERR(BZ_PARAM_ERROR); return; };
1232
1233 BZ_SETERR(BZ_OK);
1234 *nUnused = bzf->strm.avail_in;
1235 *unused = bzf->strm.next_in;
1236}
1237#endif
1238
wdenk710e3502003-08-29 20:57:53 +00001239/*---------------------------------------------------*/
1240/*--- Misc convenience stuff ---*/
1241/*---------------------------------------------------*/
1242#ifndef BZ_NO_COMPRESS
1243/*---------------------------------------------------*/
1244int BZ_API(BZ2_bzBuffToBuffCompress)
wdenk9c53f402003-10-15 23:53:47 +00001245 ( char* dest,
1246 unsigned int* destLen,
1247 char* source,
1248 unsigned int sourceLen,
1249 int blockSize100k,
1250 int verbosity,
1251 int workFactor )
wdenk710e3502003-08-29 20:57:53 +00001252{
1253 bz_stream strm;
1254 int ret;
1255
1256 if (dest == NULL || destLen == NULL ||
1257 source == NULL ||
1258 blockSize100k < 1 || blockSize100k > 9 ||
1259 verbosity < 0 || verbosity > 4 ||
1260 workFactor < 0 || workFactor > 250)
1261 return BZ_PARAM_ERROR;
1262
1263 if (workFactor == 0) workFactor = 30;
1264 strm.bzalloc = NULL;
1265 strm.bzfree = NULL;
1266 strm.opaque = NULL;
1267 ret = BZ2_bzCompressInit ( &strm, blockSize100k,
wdenk9c53f402003-10-15 23:53:47 +00001268 verbosity, workFactor );
wdenk710e3502003-08-29 20:57:53 +00001269 if (ret != BZ_OK) return ret;
1270
1271 strm.next_in = source;
1272 strm.next_out = dest;
1273 strm.avail_in = sourceLen;
1274 strm.avail_out = *destLen;
1275
1276 ret = BZ2_bzCompress ( &strm, BZ_FINISH );
1277 if (ret == BZ_FINISH_OK) goto output_overflow;
1278 if (ret != BZ_STREAM_END) goto errhandler;
1279
1280 /* normal termination */
1281 *destLen -= strm.avail_out;
1282 BZ2_bzCompressEnd ( &strm );
1283 return BZ_OK;
1284
1285 output_overflow:
1286 BZ2_bzCompressEnd ( &strm );
1287 return BZ_OUTBUFF_FULL;
1288
1289 errhandler:
1290 BZ2_bzCompressEnd ( &strm );
1291 return ret;
1292}
1293#endif /* BZ_NO_COMPRESS */
1294
1295/*---------------------------------------------------*/
1296int BZ_API(BZ2_bzBuffToBuffDecompress)
wdenk9c53f402003-10-15 23:53:47 +00001297 ( char* dest,
1298 unsigned int* destLen,
1299 char* source,
1300 unsigned int sourceLen,
1301 int small,
1302 int verbosity )
wdenk710e3502003-08-29 20:57:53 +00001303{
1304 bz_stream strm;
1305 int ret;
1306
1307 if (destLen == NULL || source == NULL)
wdenk9c53f402003-10-15 23:53:47 +00001308 return BZ_PARAM_ERROR;
wdenk710e3502003-08-29 20:57:53 +00001309
1310 strm.bzalloc = NULL;
1311 strm.bzfree = NULL;
1312 strm.opaque = NULL;
1313 ret = BZ2_bzDecompressInit ( &strm, verbosity, small );
1314 if (ret != BZ_OK) return ret;
1315
1316 strm.next_in = source;
1317 strm.next_out = dest;
1318 strm.avail_in = sourceLen;
1319 strm.avail_out = *destLen;
1320
1321 ret = BZ2_bzDecompress ( &strm );
Simon Glass487298b2014-12-02 13:17:38 -07001322 *destLen -= strm.avail_out;
wdenk710e3502003-08-29 20:57:53 +00001323 if (ret == BZ_OK) goto output_overflow_or_eof;
1324 if (ret != BZ_STREAM_END) goto errhandler;
1325
1326 /* normal termination */
wdenk710e3502003-08-29 20:57:53 +00001327 BZ2_bzDecompressEnd ( &strm );
1328 return BZ_OK;
1329
1330 output_overflow_or_eof:
1331 if (strm.avail_out > 0) {
1332 BZ2_bzDecompressEnd ( &strm );
1333 return BZ_UNEXPECTED_EOF;
1334 } else {
1335 BZ2_bzDecompressEnd ( &strm );
1336 return BZ_OUTBUFF_FULL;
1337 };
1338
1339 errhandler:
1340 BZ2_bzDecompressEnd ( &strm );
1341 return ret;
1342}
1343
wdenk710e3502003-08-29 20:57:53 +00001344/*---------------------------------------------------*/
1345/*--
1346 Code contributed by Yoshioka Tsuneo
1347 (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
1348 to support better zlib compatibility.
1349 This code is not _officially_ part of libbzip2 (yet);
1350 I haven't tested it, documented it, or considered the
1351 threading-safeness of it.
1352 If this code breaks, please contact both Yoshioka and me.
1353--*/
1354/*---------------------------------------------------*/
1355
1356/*---------------------------------------------------*/
1357/*--
1358 return version like "0.9.0c".
1359--*/
1360const char * BZ_API(BZ2_bzlibVersion)(void)
1361{
1362 return BZ_VERSION;
1363}
1364
wdenk710e3502003-08-29 20:57:53 +00001365#ifndef BZ_NO_STDIO
1366/*---------------------------------------------------*/
1367
1368#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1369# include <fcntl.h>
1370# include <io.h>
1371# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
1372#else
1373# define SET_BINARY_MODE(file)
1374#endif
1375static
1376BZFILE * bzopen_or_bzdopen
wdenk9c53f402003-10-15 23:53:47 +00001377 ( const char *path, /* no use when bzdopen */
1378 int fd, /* no use when bzdopen */
1379 const char *mode,
1380 int open_mode) /* bzopen: 0, bzdopen:1 */
wdenk710e3502003-08-29 20:57:53 +00001381{
1382 int bzerr;
1383 char unused[BZ_MAX_UNUSED];
1384 int blockSize100k = 9;
1385 int writing = 0;
1386 char mode2[10] = "";
1387 FILE *fp = NULL;
1388 BZFILE *bzfp = NULL;
1389 int verbosity = 0;
1390 int workFactor = 30;
1391 int smallMode = 0;
1392 int nUnused = 0;
1393
1394 if (mode == NULL) return NULL;
1395 while (*mode) {
1396 switch (*mode) {
1397 case 'r':
wdenk9c53f402003-10-15 23:53:47 +00001398 writing = 0; break;
wdenk710e3502003-08-29 20:57:53 +00001399 case 'w':
wdenk9c53f402003-10-15 23:53:47 +00001400 writing = 1; break;
wdenk710e3502003-08-29 20:57:53 +00001401 case 's':
wdenk9c53f402003-10-15 23:53:47 +00001402 smallMode = 1; break;
wdenk710e3502003-08-29 20:57:53 +00001403 default:
wdenk9c53f402003-10-15 23:53:47 +00001404 if (isdigit((int)(*mode))) {
1405 blockSize100k = *mode-BZ_HDR_0;
1406 }
wdenk710e3502003-08-29 20:57:53 +00001407 }
1408 mode++;
1409 }
1410 strcat(mode2, writing ? "w" : "r" );
1411 strcat(mode2,"b"); /* binary mode */
1412
1413 if (open_mode==0) {
1414 if (path==NULL || strcmp(path,"")==0) {
wdenk9c53f402003-10-15 23:53:47 +00001415 fp = (writing ? stdout : stdin);
1416 SET_BINARY_MODE(fp);
wdenk710e3502003-08-29 20:57:53 +00001417 } else {
wdenk9c53f402003-10-15 23:53:47 +00001418 fp = fopen(path,mode2);
wdenk710e3502003-08-29 20:57:53 +00001419 }
1420 } else {
1421#ifdef BZ_STRICT_ANSI
1422 fp = NULL;
1423#else
1424 fp = fdopen(fd,mode2);
1425#endif
1426 }
1427 if (fp == NULL) return NULL;
1428
1429 if (writing) {
1430 /* Guard against total chaos and anarchy -- JRS */
1431 if (blockSize100k < 1) blockSize100k = 1;
1432 if (blockSize100k > 9) blockSize100k = 9;
1433 bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
wdenk9c53f402003-10-15 23:53:47 +00001434 verbosity,workFactor);
wdenk710e3502003-08-29 20:57:53 +00001435 } else {
1436 bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
wdenk9c53f402003-10-15 23:53:47 +00001437 unused,nUnused);
wdenk710e3502003-08-29 20:57:53 +00001438 }
1439 if (bzfp == NULL) {
1440 if (fp != stdin && fp != stdout) fclose(fp);
1441 return NULL;
1442 }
1443 return bzfp;
1444}
1445
wdenk710e3502003-08-29 20:57:53 +00001446/*---------------------------------------------------*/
1447/*--
1448 open file for read or write.
1449 ex) bzopen("file","w9")
1450 case path="" or NULL => use stdin or stdout.
1451--*/
1452BZFILE * BZ_API(BZ2_bzopen)
wdenk9c53f402003-10-15 23:53:47 +00001453 ( const char *path,
1454 const char *mode )
wdenk710e3502003-08-29 20:57:53 +00001455{
1456 return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
1457}
1458
wdenk710e3502003-08-29 20:57:53 +00001459/*---------------------------------------------------*/
1460BZFILE * BZ_API(BZ2_bzdopen)
wdenk9c53f402003-10-15 23:53:47 +00001461 ( int fd,
1462 const char *mode )
wdenk710e3502003-08-29 20:57:53 +00001463{
1464 return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
1465}
1466
wdenk710e3502003-08-29 20:57:53 +00001467/*---------------------------------------------------*/
1468int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
1469{
1470 int bzerr, nread;
1471 if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
1472 nread = BZ2_bzRead(&bzerr,b,buf,len);
1473 if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1474 return nread;
1475 } else {
1476 return -1;
1477 }
1478}
1479
wdenk710e3502003-08-29 20:57:53 +00001480/*---------------------------------------------------*/
1481int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
1482{
1483 int bzerr;
1484
1485 BZ2_bzWrite(&bzerr,b,buf,len);
1486 if(bzerr == BZ_OK){
1487 return len;
1488 }else{
1489 return -1;
1490 }
1491}
1492
wdenk710e3502003-08-29 20:57:53 +00001493/*---------------------------------------------------*/
1494int BZ_API(BZ2_bzflush) (BZFILE *b)
1495{
1496 /* do nothing now... */
1497 return 0;
1498}
1499
wdenk710e3502003-08-29 20:57:53 +00001500/*---------------------------------------------------*/
1501void BZ_API(BZ2_bzclose) (BZFILE* b)
1502{
1503 int bzerr;
1504 FILE *fp = ((bzFile *)b)->handle;
1505
1506 if (b==NULL) {return;}
1507 if(((bzFile*)b)->writing){
1508 BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
1509 if(bzerr != BZ_OK){
wdenk9c53f402003-10-15 23:53:47 +00001510 BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
wdenk710e3502003-08-29 20:57:53 +00001511 }
1512 }else{
1513 BZ2_bzReadClose(&bzerr,b);
1514 }
1515 if(fp!=stdin && fp!=stdout){
1516 fclose(fp);
1517 }
1518}
1519
wdenk710e3502003-08-29 20:57:53 +00001520/*---------------------------------------------------*/
1521/*--
1522 return last error code
1523--*/
1524static char *bzerrorstrings[] = {
1525 "OK"
1526 ,"SEQUENCE_ERROR"
1527 ,"PARAM_ERROR"
1528 ,"MEM_ERROR"
1529 ,"DATA_ERROR"
1530 ,"DATA_ERROR_MAGIC"
1531 ,"IO_ERROR"
1532 ,"UNEXPECTED_EOF"
1533 ,"OUTBUFF_FULL"
1534 ,"CONFIG_ERROR"
1535 ,"???" /* for future */
1536 ,"???" /* for future */
1537 ,"???" /* for future */
1538 ,"???" /* for future */
1539 ,"???" /* for future */
1540 ,"???" /* for future */
1541};
1542
wdenk710e3502003-08-29 20:57:53 +00001543const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
1544{
1545 int err = ((bzFile *)b)->lastErr;
1546
1547 if(err>0) err = 0;
1548 *errnum = err;
1549 return bzerrorstrings[err*-1];
1550}
1551#endif
1552
Marian Balakowiczbe946ba2008-01-08 18:11:43 +01001553void bz_internal_error(int errcode)
1554{
1555 printf ("BZIP2 internal error %d\n", errcode);
1556}
wdenk710e3502003-08-29 20:57:53 +00001557
1558/*-------------------------------------------------------------*/
1559/*--- end bzlib.c ---*/
1560/*-------------------------------------------------------------*/