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