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