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