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