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