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