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