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