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