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