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