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