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