1 2 /*-------------------------------------------------------------*/ 3 /*--- Library top-level functions. ---*/ 4 /*--- bzlib.c ---*/ 5 /*-------------------------------------------------------------*/ 6 7 /* ------------------------------------------------------------------ 8 This file is part of bzip2/libbzip2, a program and library for 9 lossless, block-sorting data compression. 10 11 bzip2/libbzip2 version 1.0.4 of 20 December 2006 12 Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org> 13 14 Please read the WARNING, DISCLAIMER and PATENTS sections in the 15 README file. 16 17 This program is released under the terms of the license contained 18 in the file LICENSE. 19 ------------------------------------------------------------------ */ 20 21 /* CHANGES 22 0.9.0 -- original version. 23 0.9.0a/b -- no changes in this file. 24 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). 25 fixed bzWrite/bzRead to ignore zero-length requests. 26 fixed bzread to correctly handle read requests after EOF. 27 wrong parameter order in call to bzDecompressInit in 28 bzBuffToBuffDecompress. Fixed. 29 */ 30 31 #include <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 me at: jseward@bzip.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. Julian Seward, 15 February 2005.\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 /* end restore */ 609 610 UInt32 avail_out_INIT = cs_avail_out; 611 Int32 s_save_nblockPP = s->save_nblock+1; 612 unsigned int total_out_lo32_old; 613 614 while (True) { 615 616 /* try to finish existing run */ 617 if (c_state_out_len > 0) { 618 while (True) { 619 if (cs_avail_out == 0) goto return_notr; 620 if (c_state_out_len == 1) break; 621 *( (UChar*)(cs_next_out) ) = c_state_out_ch; 622 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 623 c_state_out_len--; 624 cs_next_out++; 625 cs_avail_out--; 626 } 627 s_state_out_len_eq_one: 628 { 629 if (cs_avail_out == 0) { 630 c_state_out_len = 1; goto return_notr; 631 }; 632 *( (UChar*)(cs_next_out) ) = c_state_out_ch; 633 BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); 634 cs_next_out++; 635 cs_avail_out--; 636 } 637 } 638 /* Only caused by corrupt data stream? */ 639 if (c_nblock_used > s_save_nblockPP) 640 return True; 641 642 /* can a new run be started? */ 643 if (c_nblock_used == s_save_nblockPP) { 644 c_state_out_len = 0; goto return_notr; 645 }; 646 c_state_out_ch = c_k0; 647 BZ_GET_FAST_C(k1); c_nblock_used++; 648 if (k1 != c_k0) { 649 c_k0 = k1; goto s_state_out_len_eq_one; 650 }; 651 if (c_nblock_used == s_save_nblockPP) 652 goto s_state_out_len_eq_one; 653 654 c_state_out_len = 2; 655 BZ_GET_FAST_C(k1); c_nblock_used++; 656 if (c_nblock_used == s_save_nblockPP) continue; 657 if (k1 != c_k0) { c_k0 = k1; continue; }; 658 659 c_state_out_len = 3; 660 BZ_GET_FAST_C(k1); c_nblock_used++; 661 if (c_nblock_used == s_save_nblockPP) continue; 662 if (k1 != c_k0) { c_k0 = k1; continue; }; 663 664 BZ_GET_FAST_C(k1); c_nblock_used++; 665 c_state_out_len = ((Int32)k1) + 4; 666 BZ_GET_FAST_C(c_k0); c_nblock_used++; 667 } 668 669 return_notr: 670 total_out_lo32_old = s->strm->total_out_lo32; 671 s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); 672 if (s->strm->total_out_lo32 < total_out_lo32_old) 673 s->strm->total_out_hi32++; 674 675 /* save */ 676 s->calculatedBlockCRC = c_calculatedBlockCRC; 677 s->state_out_ch = c_state_out_ch; 678 s->state_out_len = c_state_out_len; 679 s->nblock_used = c_nblock_used; 680 s->k0 = c_k0; 681 s->tt = c_tt; 682 s->tPos = c_tPos; 683 s->strm->next_out = cs_next_out; 684 s->strm->avail_out = cs_avail_out; 685 /* end save */ 686 } 687 return False; 688 } 689 690 691 692 /*---------------------------------------------------*/ 693 __inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) 694 { 695 Int32 nb, na, mid; 696 nb = 0; 697 na = 256; 698 do { 699 mid = (nb + na) >> 1; 700 if (indx >= cftab[mid]) nb = mid; else na = mid; 701 } 702 while (na - nb != 1); 703 return nb; 704 } 705 706 707 /*---------------------------------------------------*/ 708 /* Return True iff data corruption is discovered. 709 Returns False if there is no problem. 710 */ 711 static 712 Bool unRLE_obuf_to_output_SMALL ( DState* s ) 713 { 714 UChar k1; 715 716 if (s->blockRandomised) { 717 718 while (True) { 719 /* try to finish existing run */ 720 while (True) { 721 if (s->strm->avail_out == 0) return False; 722 if (s->state_out_len == 0) break; 723 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 724 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 725 s->state_out_len--; 726 s->strm->next_out++; 727 s->strm->avail_out--; 728 s->strm->total_out_lo32++; 729 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 730 } 731 732 /* can a new run be started? */ 733 if (s->nblock_used == s->save_nblock+1) return False; 734 735 /* Only caused by corrupt data stream? */ 736 if (s->nblock_used > s->save_nblock+1) 737 return True; 738 739 s->state_out_len = 1; 740 s->state_out_ch = s->k0; 741 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 742 k1 ^= BZ_RAND_MASK; s->nblock_used++; 743 if (s->nblock_used == s->save_nblock+1) continue; 744 if (k1 != s->k0) { s->k0 = k1; continue; }; 745 746 s->state_out_len = 2; 747 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 748 k1 ^= BZ_RAND_MASK; s->nblock_used++; 749 if (s->nblock_used == s->save_nblock+1) continue; 750 if (k1 != s->k0) { s->k0 = k1; continue; }; 751 752 s->state_out_len = 3; 753 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 754 k1 ^= BZ_RAND_MASK; s->nblock_used++; 755 if (s->nblock_used == s->save_nblock+1) continue; 756 if (k1 != s->k0) { s->k0 = k1; continue; }; 757 758 BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; 759 k1 ^= BZ_RAND_MASK; s->nblock_used++; 760 s->state_out_len = ((Int32)k1) + 4; 761 BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; 762 s->k0 ^= BZ_RAND_MASK; s->nblock_used++; 763 } 764 765 } else { 766 767 while (True) { 768 /* try to finish existing run */ 769 while (True) { 770 if (s->strm->avail_out == 0) return False; 771 if (s->state_out_len == 0) break; 772 *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; 773 BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); 774 s->state_out_len--; 775 s->strm->next_out++; 776 s->strm->avail_out--; 777 s->strm->total_out_lo32++; 778 if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; 779 } 780 781 /* can a new run be started? */ 782 if (s->nblock_used == s->save_nblock+1) return False; 783 784 /* Only caused by corrupt data stream? */ 785 if (s->nblock_used > s->save_nblock+1) 786 return True; 787 788 s->state_out_len = 1; 789 s->state_out_ch = s->k0; 790 BZ_GET_SMALL(k1); s->nblock_used++; 791 if (s->nblock_used == s->save_nblock+1) continue; 792 if (k1 != s->k0) { s->k0 = k1; continue; }; 793 794 s->state_out_len = 2; 795 BZ_GET_SMALL(k1); s->nblock_used++; 796 if (s->nblock_used == s->save_nblock+1) continue; 797 if (k1 != s->k0) { s->k0 = k1; continue; }; 798 799 s->state_out_len = 3; 800 BZ_GET_SMALL(k1); s->nblock_used++; 801 if (s->nblock_used == s->save_nblock+1) continue; 802 if (k1 != s->k0) { s->k0 = k1; continue; }; 803 804 BZ_GET_SMALL(k1); s->nblock_used++; 805 s->state_out_len = ((Int32)k1) + 4; 806 BZ_GET_SMALL(s->k0); s->nblock_used++; 807 } 808 809 } 810 } 811 812 813 /*---------------------------------------------------*/ 814 int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) 815 { 816 Bool corrupt; 817 DState* s; 818 if (strm == NULL) return BZ_PARAM_ERROR; 819 s = strm->state; 820 if (s == NULL) return BZ_PARAM_ERROR; 821 if (s->strm != strm) return BZ_PARAM_ERROR; 822 823 while (True) { 824 if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; 825 if (s->state == BZ_X_OUTPUT) { 826 if (s->smallDecompress) 827 corrupt = unRLE_obuf_to_output_SMALL ( s ); else 828 corrupt = unRLE_obuf_to_output_FAST ( s ); 829 if (corrupt) return BZ_DATA_ERROR; 830 if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { 831 BZ_FINALISE_CRC ( s->calculatedBlockCRC ); 832 if (s->verbosity >= 3) 833 VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, 834 s->calculatedBlockCRC ); 835 if (s->verbosity >= 2) VPrintf0 ( "]" ); 836 if (s->calculatedBlockCRC != s->storedBlockCRC) 837 return BZ_DATA_ERROR; 838 s->calculatedCombinedCRC 839 = (s->calculatedCombinedCRC << 1) | 840 (s->calculatedCombinedCRC >> 31); 841 s->calculatedCombinedCRC ^= s->calculatedBlockCRC; 842 s->state = BZ_X_BLKHDR_1; 843 } else { 844 return BZ_OK; 845 } 846 } 847 if (s->state >= BZ_X_MAGIC_1) { 848 Int32 r = BZ2_decompress ( s ); 849 if (r == BZ_STREAM_END) { 850 if (s->verbosity >= 3) 851 VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", 852 s->storedCombinedCRC, s->calculatedCombinedCRC ); 853 if (s->calculatedCombinedCRC != s->storedCombinedCRC) 854 return BZ_DATA_ERROR; 855 return r; 856 } 857 if (s->state != BZ_X_OUTPUT) return r; 858 } 859 } 860 861 AssertH ( 0, 6001 ); 862 863 return 0; /*NOTREACHED*/ 864 } 865 866 867 /*---------------------------------------------------*/ 868 int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) 869 { 870 DState* s; 871 if (strm == NULL) return BZ_PARAM_ERROR; 872 s = strm->state; 873 if (s == NULL) return BZ_PARAM_ERROR; 874 if (s->strm != strm) return BZ_PARAM_ERROR; 875 876 if (s->tt != NULL) BZFREE(s->tt); 877 if (s->ll16 != NULL) BZFREE(s->ll16); 878 if (s->ll4 != NULL) BZFREE(s->ll4); 879 880 BZFREE(strm->state); 881 strm->state = NULL; 882 883 return BZ_OK; 884 } 885 886 #ifndef BZ_NO_COMPRESS 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 899 typedef 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 /*---------------------------------------------*/ 913 static 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 /*---------------------------------------------------*/ 923 BZFILE* 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 = 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 /*---------------------------------------------------*/ 971 void 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 = 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 /*---------------------------------------------------*/ 1016 void 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 1028 void 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 /*---------------------------------------------------*/ 1094 BZFILE* 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 = 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 /*---------------------------------------------------*/ 1150 void 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 /*---------------------------------------------------*/ 1168 int 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 = 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 /*---------------------------------------------------*/ 1228 void 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 /*---------------------------------------------------*/ 1254 int 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 /*---------------------------------------------------*/ 1306 int 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 --*/ 1373 const 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 1389 static 1390 BZFILE * 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((int)(*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 --*/ 1467 BZFILE * 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 /*---------------------------------------------------*/ 1476 BZFILE * 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 /*---------------------------------------------------*/ 1485 int 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 /*---------------------------------------------------*/ 1499 int 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 /*---------------------------------------------------*/ 1513 int BZ_API(BZ2_bzflush) (BZFILE *b) 1514 { 1515 /* do nothing now... */ 1516 return 0; 1517 } 1518 1519 1520 /*---------------------------------------------------*/ 1521 void 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 --*/ 1546 static 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 1566 const 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 #endif /* BZ_NO_COMPRESS */ 1577 1578 /*-------------------------------------------------------------*/ 1579 /*--- end bzlib.c ---*/ 1580 /*-------------------------------------------------------------*/ 1581