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