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