bzlib.c revision fce880d1411ac6f72a4f06d50af95f9912093f9f
/*-------------------------------------------------------------*/
/*--- Library top-level functions. ---*/
/*--- bzlib.c ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
lossless, block-sorting data compression.
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
/* CHANGES
0.9.0 -- original version.
0.9.0a/b -- no changes in this file.
0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress().
fixed bzread to correctly handle read requests after EOF.
wrong parameter order in call to bzDecompressInit in
bzBuffToBuffDecompress. Fixed.
*/
#include "bzlib_private.h"
#ifndef BZ_NO_COMPRESS
/*---------------------------------------------------*/
/*--- Compression stuff ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
#ifndef BZ_NO_STDIO
void BZ2_bz__AssertH__fail ( int errcode )
{
"Please report it to me at: jseward@bzip.org. If this happened\n"
"when you were using some program which uses libbzip2 as a\n"
"component, you should also report this bug to the author(s)\n"
"of that program. Please make an effort to report this bug;\n"
"timely and accurate bug reports eventually lead to higher\n"
"quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
);
if (errcode == 1007) {
"\n*** A special note about internal error number 1007 ***\n"
"\n"
"Experience suggests that a common cause of i.e. 1007\n"
"is unreliable memory or other hardware. The 1007 assertion\n"
"just happens to cross-check the results of huge numbers of\n"
"test of your memory system.\n"
"\n"
"I suggest the following: try compressing the file again,\n"
"possibly monitoring progress in detail with the -vv flag.\n"
"\n"
" points in compression, you may have a flaky memory system.\n"
" Try a memory-test program. I have used Memtest86\n"
" (www.memtest86.com). At the time of writing it is free (GPLd).\n"
" Memtest86 tests memory much more thorougly than your BIOSs\n"
" power-on test, and may find failures that the BIOS doesn't.\n"
"\n"
"* If the error can be repeatably reproduced, this is a bug in\n"
" bzip2, and I would very much like to hear about it. Please\n"
" let me know, and, ideally, save a copy of the file causing the\n"
" problem -- without which I will be unable to investigate it.\n"
"\n"
);
}
exit(3);
}
#endif
#endif /* BZ_NO_COMPRESS */
/*---------------------------------------------------*/
static
int bz_config_ok ( void )
{
if (sizeof(int) != 4) return 0;
if (sizeof(short) != 2) return 0;
if (sizeof(char) != 1) return 0;
return 1;
}
/*
* Added for Solaris kernel
*/
#define BZES \
BZE(BZ_FLUSH_OK) \
BZE(BZ_FINISH_OK) \
BZE(BZ_STREAM_END) \
BZE(BZ_MEM_ERROR) \
BZE(BZ_DATA_ERROR) \
BZE(BZ_IO_ERROR) \
int error_code
)
{
switch (error_code)
{
#define BZE(x) case x: return (#x);
}
return ("BZ_UNKNOWN_ERROR");
}
#ifndef BZ_LOADER
#include <sys/sysmacros.h>
#endif
#ifdef _KERNEL
void
bz_internal_error(int errcode)
{
}
/*---------------------------------------------------*/
typedef struct {
char *buf;
} bzap;
static
{
if (p != NULL) {
return (pp);
}
return (NULL);
}
static
{
}
}
#else
/*---------------------------------------------------*/
static
{
return v;
}
static
{
}
#endif /* _KERNEL */
/*---------------------------------------------------*/
#ifndef BZ_NO_COMPRESS
static
void prepare_new_block ( EState* s )
{
Int32 i;
s->nblock = 0;
s->numZ = 0;
s->state_out_pos = 0;
BZ_INITIALISE_CRC ( s->blockCRC );
s->blockNo++;
}
/*---------------------------------------------------*/
static
{
s->state_in_ch = 256;
s->state_in_len = 0;
}
static
{
return False; else
return True;
}
/*---------------------------------------------------*/
int BZ_API(BZ2_bzCompressInit)
int blockSize100k,
int verbosity,
int workFactor )
{
Int32 n;
EState* s;
if (!bz_config_ok()) return BZ_CONFIG_ERROR;
return BZ_PARAM_ERROR;
if (s == NULL) return BZ_MEM_ERROR;
n = 100000 * blockSize100k;
return BZ_MEM_ERROR;
}
s->blockNo = 0;
s->state = BZ_S_INPUT;
s->mode = BZ_M_RUNNING;
s->combinedCRC = 0;
s->blockSize100k = blockSize100k;
s->workFactor = workFactor;
strm->total_in_lo32 = 0;
strm->total_in_hi32 = 0;
strm->total_out_lo32 = 0;
strm->total_out_hi32 = 0;
init_RL ( s );
prepare_new_block ( s );
return BZ_OK;
}
/*---------------------------------------------------*/
/*
* returns the BZALLOC size needed for bzCompressInit
*/
int BZ_API(BZ2_bzCompressInitSize) (
int blockSize100k)
{
Int32 n, t;
n = 100000 * blockSize100k;
t = 0;
t += ( sizeof(EState) );
t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
t += ( n * sizeof(UInt32) );
t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
t += ( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) );
t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
t += ( 65537 * sizeof(UInt32) );
t = P2ROUNDUP(t, BZ2_BZALLOC_ALIGN);
return (t);
}
/*---------------------------------------------------*/
/*
*/
{
if (!bz_config_ok()) return BZ_CONFIG_ERROR;
if (s == NULL) return BZ_MEM_ERROR;
s->blockNo = 0;
s->state = BZ_S_INPUT;
s->mode = BZ_M_RUNNING;
s->combinedCRC = 0;
strm->total_in_lo32 = 0;
strm->total_in_hi32 = 0;
strm->total_out_lo32 = 0;
strm->total_out_hi32 = 0;
init_RL ( s );
prepare_new_block ( s );
return BZ_OK;
}
/*---------------------------------------------------*/
static
void add_pair_to_block ( EState* s )
{
Int32 i;
for (i = 0; i < s->state_in_len; i++) {
}
switch (s->state_in_len) {
case 1:
break;
case 2:
break;
case 3:
break;
default:
s->nblock++;
break;
}
}
/*---------------------------------------------------*/
static
{
init_RL ( s );
}
/*---------------------------------------------------*/
{ \
/*-- fast track the common case --*/ \
} \
else \
/*-- general, uncommon cases --*/ \
add_pair_to_block ( zs ); \
} else { \
zs->state_in_len++; \
} \
}
/*---------------------------------------------------*/
static
{
if (s->mode == BZ_M_RUNNING) {
/*-- fast track the common case --*/
while (True) {
/*-- block full? --*/
/*-- no input? --*/
progress_in = True;
s->strm->total_in_lo32++;
}
} else {
/*-- general, uncommon case --*/
while (True) {
/*-- block full? --*/
/*-- no input? --*/
if (s->avail_in_expect == 0) break;
progress_in = True;
s->strm->total_in_lo32++;
s->avail_in_expect--;
}
}
return progress_in;
}
/*---------------------------------------------------*/
static
{
while (True) {
/*-- no output space? --*/
/*-- block done? --*/
if (s->state_out_pos >= s->numZ) break;
progress_out = True;
s->state_out_pos++;
s->strm->total_out_lo32++;
}
return progress_out;
}
/*---------------------------------------------------*/
static
{
while (True) {
if (s->state == BZ_S_OUTPUT) {
progress_out |= copy_output_until_stop ( s );
if (s->state_out_pos < s->numZ) break;
if (s->mode == BZ_M_FINISHING &&
s->avail_in_expect == 0 &&
isempty_RL(s)) break;
prepare_new_block ( s );
s->state = BZ_S_INPUT;
if (s->mode == BZ_M_FLUSHING &&
s->avail_in_expect == 0 &&
isempty_RL(s)) break;
}
if (s->state == BZ_S_INPUT) {
progress_in |= copy_input_until_stop ( s );
flush_RL ( s );
s->state = BZ_S_OUTPUT;
}
else
BZ2_compressBlock ( s, False );
s->state = BZ_S_OUTPUT;
}
else
break;
}
}
}
return progress_in || progress_out;
}
/*---------------------------------------------------*/
{
EState* s;
if (s == NULL) return BZ_PARAM_ERROR;
switch (s->mode) {
case BZ_M_IDLE:
return BZ_SEQUENCE_ERROR;
case BZ_M_RUNNING:
}
else
s->mode = BZ_M_FLUSHING;
goto preswitch;
}
else
s->mode = BZ_M_FINISHING;
goto preswitch;
}
else
return BZ_PARAM_ERROR;
case BZ_M_FLUSHING:
return BZ_SEQUENCE_ERROR;
if (s->avail_in_expect > 0 || !isempty_RL(s) ||
s->mode = BZ_M_RUNNING;
return BZ_RUN_OK;
case BZ_M_FINISHING:
return BZ_SEQUENCE_ERROR;
if (!progress) return BZ_SEQUENCE_ERROR;
if (s->avail_in_expect > 0 || !isempty_RL(s) ||
return BZ_STREAM_END;
}
return BZ_OK; /*--not reached--*/
}
/*---------------------------------------------------*/
{
EState* s;
if (s == NULL) return BZ_PARAM_ERROR;
return BZ_OK;
}
#endif /* BZ_NO_COMPRESS */
/*---------------------------------------------------*/
/*--- Decompression stuff ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
int verbosity,
int small )
{
DState* s;
if (!bz_config_ok()) return BZ_CONFIG_ERROR;
if (s == NULL) return BZ_MEM_ERROR;
s->state = BZ_X_MAGIC_1;
s->bsLive = 0;
s->bsBuff = 0;
s->calculatedCombinedCRC = 0;
strm->total_in_lo32 = 0;
strm->total_in_hi32 = 0;
strm->total_out_lo32 = 0;
strm->total_out_hi32 = 0;
s->currBlockNo = 0;
return BZ_OK;
}
/*---------------------------------------------------*/
/*
*/
{
if (!bz_config_ok()) return BZ_CONFIG_ERROR;
s->state = BZ_X_MAGIC_1;
s->bsLive = 0;
s->bsBuff = 0;
s->calculatedCombinedCRC = 0;
strm->total_in_lo32 = 0;
strm->total_in_hi32 = 0;
strm->total_out_lo32 = 0;
strm->total_out_hi32 = 0;
s->currBlockNo = 0;
return BZ_OK;
}
/*---------------------------------------------------*/
/* Return True iff data corruption is discovered.
Returns False if there is no problem.
*/
static
{
if (s->blockRandomised) {
while (True) {
/* try to finish existing run */
while (True) {
if (s->state_out_len == 0) break;
s->state_out_len--;
s->strm->total_out_lo32++;
}
/* can a new run be started? */
/* Only caused by corrupt data stream? */
return True;
s->state_out_len = 1;
s->state_out_ch = s->k0;
s->state_out_len = 2;
s->state_out_len = 3;
}
} else {
/* restore */
/* end restore */
unsigned int total_out_lo32_old;
while (True) {
/* try to finish existing run */
if (c_state_out_len > 0) {
while (True) {
if (cs_avail_out == 0) goto return_notr;
if (c_state_out_len == 1) break;
cs_next_out++;
cs_avail_out--;
}
{
if (cs_avail_out == 0) {
};
cs_next_out++;
cs_avail_out--;
}
}
/* Only caused by corrupt data stream? */
if (c_nblock_used > s_save_nblockPP)
return True;
/* can a new run be started? */
if (c_nblock_used == s_save_nblockPP) {
c_state_out_len = 0; goto return_notr;
};
};
if (c_nblock_used == s_save_nblockPP)
goto s_state_out_len_eq_one;
c_state_out_len = 2;
if (c_nblock_used == s_save_nblockPP) continue;
c_state_out_len = 3;
if (c_nblock_used == s_save_nblockPP) continue;
}
s->strm->total_out_hi32++;
/* save */
s->state_out_ch = c_state_out_ch;
s->state_out_len = c_state_out_len;
s->nblock_used = c_nblock_used;
/* end save */
}
return False;
}
/*---------------------------------------------------*/
{
nb = 0;
na = 256;
do {
}
return nb;
}
/*---------------------------------------------------*/
/* Return True iff data corruption is discovered.
Returns False if there is no problem.
*/
static
{
if (s->blockRandomised) {
while (True) {
/* try to finish existing run */
while (True) {
if (s->state_out_len == 0) break;
s->state_out_len--;
s->strm->total_out_lo32++;
}
/* can a new run be started? */
/* Only caused by corrupt data stream? */
return True;
s->state_out_len = 1;
s->state_out_ch = s->k0;
s->state_out_len = 2;
s->state_out_len = 3;
}
} else {
while (True) {
/* try to finish existing run */
while (True) {
if (s->state_out_len == 0) break;
s->state_out_len--;
s->strm->total_out_lo32++;
}
/* can a new run be started? */
/* Only caused by corrupt data stream? */
return True;
s->state_out_len = 1;
s->state_out_ch = s->k0;
s->state_out_len = 2;
s->state_out_len = 3;
}
}
}
/*---------------------------------------------------*/
{
DState* s;
if (s == NULL) return BZ_PARAM_ERROR;
while (True) {
if (s->state == BZ_X_OUTPUT) {
if (s->smallDecompress)
corrupt = unRLE_obuf_to_output_SMALL ( s ); else
corrupt = unRLE_obuf_to_output_FAST ( s );
if (corrupt) return BZ_DATA_ERROR;
BZ_FINALISE_CRC ( s->calculatedBlockCRC );
if (s->verbosity >= 3)
s->calculatedBlockCRC );
if (s->calculatedBlockCRC != s->storedBlockCRC)
return BZ_DATA_ERROR;
= (s->calculatedCombinedCRC << 1) |
(s->calculatedCombinedCRC >> 31);
s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
s->state = BZ_X_BLKHDR_1;
} else {
return BZ_OK;
}
}
if (s->state >= BZ_X_MAGIC_1) {
Int32 r = BZ2_decompress ( s );
if (r == BZ_STREAM_END) {
if (s->verbosity >= 3)
VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
s->storedCombinedCRC, s->calculatedCombinedCRC );
if (s->calculatedCombinedCRC != s->storedCombinedCRC)
return BZ_DATA_ERROR;
return r;
}
if (s->state != BZ_X_OUTPUT) return r;
}
}
#if 0
AssertH ( 0, 6001 );
return 0; /*NOTREACHED*/
#endif
}
/*---------------------------------------------------*/
{
DState* s;
if (s == NULL) return BZ_PARAM_ERROR;
return BZ_OK;
}
#ifndef BZ_NO_COMPRESS
#ifndef BZ_NO_STDIO
/*---------------------------------------------------*/
/*--- File I/O stuff ---*/
/*---------------------------------------------------*/
{ \
}
typedef
struct {
}
/*---------------------------------------------*/
{
ungetc ( c, f );
return False;
}
/*---------------------------------------------------*/
( int* bzerror,
FILE* f,
int blockSize100k,
int verbosity,
int workFactor )
{
if (f == NULL ||
if (ferror(f))
verbosity, workFactor );
return bzf;
}
/*---------------------------------------------------*/
void BZ_API(BZ2_bzWrite)
( int* bzerror,
BZFILE* b,
void* buf,
int len )
{
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
{ BZ_SETERR(BZ_IO_ERROR); return; };
if (len == 0)
while (True) {
{ BZ_SETERR(BZ_IO_ERROR); return; };
}
}
}
/*---------------------------------------------------*/
void BZ_API(BZ2_bzWriteClose)
( int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in,
unsigned int* nbytes_out )
{
}
void BZ_API(BZ2_bzWriteClose64)
( int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in_lo32,
unsigned int* nbytes_in_hi32,
unsigned int* nbytes_out_lo32,
unsigned int* nbytes_out_hi32 )
{
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
{ BZ_SETERR(BZ_IO_ERROR); return; };
while (True) {
{ BZ_SETERR(BZ_IO_ERROR); return; };
}
if (ret == BZ_STREAM_END) break;
}
}
{ BZ_SETERR(BZ_IO_ERROR); return; };
}
if (nbytes_in_lo32 != NULL)
if (nbytes_in_hi32 != NULL)
if (nbytes_out_lo32 != NULL)
if (nbytes_out_hi32 != NULL)
}
/*---------------------------------------------------*/
( int* bzerror,
FILE* f,
int verbosity,
int small,
void* unused,
int nUnused )
{
int ret;
if (f == NULL ||
if (ferror(f))
while (nUnused > 0) {
nUnused--;
}
return bzf;
}
/*---------------------------------------------------*/
{
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
if (bzf->initialisedOk)
}
/*---------------------------------------------------*/
int BZ_API(BZ2_bzRead)
( int* bzerror,
BZFILE* b,
void* buf,
int len )
{
{ BZ_SETERR(BZ_PARAM_ERROR); return 0; };
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
if (len == 0)
while (True) {
{ BZ_SETERR(BZ_IO_ERROR); return 0; };
{ BZ_SETERR(BZ_IO_ERROR); return 0; };
}
{ BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
if (ret == BZ_STREAM_END)
}
return 0; /*not reached*/
}
/*---------------------------------------------------*/
void BZ_API(BZ2_bzReadGetUnused)
( int* bzerror,
BZFILE* b,
void** unused,
int* nUnused )
{
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
}
#endif
/*---------------------------------------------------*/
/*--- Misc convenience stuff ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
( char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int blockSize100k,
int verbosity,
int workFactor )
{
int ret;
return BZ_PARAM_ERROR;
verbosity, workFactor );
/* normal termination */
(void) BZ2_bzCompressEnd ( &strm );
return BZ_OK;
(void) BZ2_bzCompressEnd ( &strm );
return BZ_OUTBUFF_FULL;
(void) BZ2_bzCompressEnd ( &strm );
return ret;
}
/*---------------------------------------------------*/
( char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int small,
int verbosity )
{
int ret;
return BZ_PARAM_ERROR;
/* normal termination */
(void) BZ2_bzDecompressEnd ( &strm );
return BZ_OK;
(void) BZ2_bzDecompressEnd ( &strm );
return BZ_UNEXPECTED_EOF;
} else {
(void) BZ2_bzDecompressEnd ( &strm );
return BZ_OUTBUFF_FULL;
}
(void) BZ2_bzDecompressEnd ( &strm );
return ret;
}
/*---------------------------------------------------*/
/*--
Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
to support better zlib compatibility.
This code is not _officially_ part of libbzip2 (yet);
I haven't tested it, documented it, or considered the
threading-safeness of it.
If this code breaks, please contact both Yoshioka and me.
--*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
/*--
return version like "0.9.5d, 4-Sept-1999".
--*/
const char * BZ_API(BZ2_bzlibVersion)(void)
{
return BZ_VERSION;
}
#ifndef BZ_NO_STDIO
/*---------------------------------------------------*/
# include <fcntl.h>
# include <io.h>
#else
# define SET_BINARY_MODE(file)
#endif
static
( const char *path, /* no use when bzdopen */
int fd, /* no use when bzdopen */
const char *mode,
int open_mode) /* bzopen: 0, bzdopen:1 */
{
int bzerr;
char unused[BZ_MAX_UNUSED];
int blockSize100k = 9;
int writing = 0;
int verbosity = 0;
int workFactor = 30;
int smallMode = 0;
int nUnused = 0;
while (*mode) {
switch (*mode) {
case 'r':
writing = 0; break;
case 'w':
writing = 1; break;
case 's':
smallMode = 1; break;
default:
}
}
mode++;
}
if (open_mode==0) {
} else {
}
} else {
#ifdef BZ_STRICT_ANSI
#else
#endif
}
if (writing) {
/* Guard against total chaos and anarchy -- JRS */
} else {
}
return NULL;
}
return bzfp;
}
/*---------------------------------------------------*/
/*--
open file for read or write.
ex) bzopen("file","w9")
case path="" or NULL => use stdin or stdout.
--*/
( const char *path,
const char *mode )
{
}
/*---------------------------------------------------*/
( int fd,
const char *mode )
{
}
/*---------------------------------------------------*/
{
return nread;
} else {
return -1;
}
}
/*---------------------------------------------------*/
{
int bzerr;
return len;
}else{
return -1;
}
}
/*---------------------------------------------------*/
{
/* do nothing now... */
return 0;
}
/*---------------------------------------------------*/
{
int bzerr;
if (b==NULL) {return;}
}
}else{
BZ2_bzReadClose(&bzerr,b);
}
}
}
/*---------------------------------------------------*/
/*--
return last error code
--*/
static const char *bzerrorstrings[] = {
"OK"
,"SEQUENCE_ERROR"
,"PARAM_ERROR"
,"MEM_ERROR"
,"DATA_ERROR"
,"DATA_ERROR_MAGIC"
,"IO_ERROR"
,"UNEXPECTED_EOF"
,"OUTBUFF_FULL"
,"CONFIG_ERROR"
,"???" /* for future */
,"???" /* for future */
,"???" /* for future */
,"???" /* for future */
,"???" /* for future */
,"???" /* for future */
};
{
}
#endif
#endif /* BZ_NO_COMPRESS */
/*-------------------------------------------------------------*/
/*--- end bzlib.c ---*/
/*-------------------------------------------------------------*/