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