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