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