237 lines
6.9 KiB
C
237 lines
6.9 KiB
C
/* THIS FILE HAS BEEN MODIFIED -- rsc split bzlib.c into bzlib.c,
|
|
bzlibcompress.c, bzlibdecompress.c, bzlibread.c, bzlibwrite.c
|
|
*/
|
|
/*-------------------------------------------------------------*/
|
|
/*--- Library top-level functions. ---*/
|
|
/*--- bzlib.c ---*/
|
|
/*-------------------------------------------------------------*/
|
|
|
|
/*--
|
|
This file is a part of bzip2 and/or libbzip2, a program and
|
|
library for lossless, block-sorting data compression.
|
|
|
|
Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. The origin of this software must not be misrepresented; you must
|
|
not claim that you wrote the original software. If you use this
|
|
software in a product, an acknowledgment in the product
|
|
documentation would be appreciated but is not required.
|
|
|
|
3. Altered source versions must be plainly marked as such, and must
|
|
not be misrepresented as being the original software.
|
|
|
|
4. The name of the author may not be used to endorse or promote
|
|
products derived from this software without specific prior written
|
|
permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
Julian Seward, Cambridge, UK.
|
|
jseward@acm.org
|
|
bzip2/libbzip2 version 1.0 of 21 March 2000
|
|
|
|
This program is based on (at least) the work of:
|
|
Mike Burrows
|
|
David Wheeler
|
|
Peter Fenwick
|
|
Alistair Moffat
|
|
Radford Neal
|
|
Ian H. Witten
|
|
Robert Sedgewick
|
|
Jon L. Bentley
|
|
|
|
For more information on these sources, see the manual.
|
|
--*/
|
|
|
|
/*--
|
|
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 bzWrite/bzRead to ignore zero-length requests.
|
|
* fixed bzread to correctly handle read requests after EOF.
|
|
* wrong parameter order in call to bzDecompressInit in
|
|
bzBuffToBuffDecompress. Fixed.
|
|
--*/
|
|
|
|
#include "os.h"
|
|
#include "bzlib.h"
|
|
#include "bzlib_private.h"
|
|
#include "bzlib_stdio.h"
|
|
#include "bzlib_stdio_private.h"
|
|
|
|
/*---------------------------------------------------*/
|
|
BZFILE* BZ_API(BZ2_bzReadOpen)
|
|
( int* bzerror,
|
|
FILE* f,
|
|
int verbosity,
|
|
int small,
|
|
void* unused,
|
|
int nUnused )
|
|
{
|
|
bzFile* bzf = NULL;
|
|
int ret;
|
|
|
|
BZ_SETERR(BZ_OK);
|
|
|
|
if (f == NULL ||
|
|
(small != 0 && small != 1) ||
|
|
(verbosity < 0 || verbosity > 4) ||
|
|
(unused == NULL && nUnused != 0) ||
|
|
(unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
|
|
{ BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
|
|
|
|
if (ferror(f))
|
|
{ BZ_SETERR(BZ_IO_ERROR); return NULL; };
|
|
|
|
bzf = malloc ( sizeof(bzFile) );
|
|
if (bzf == NULL)
|
|
{ BZ_SETERR(BZ_MEM_ERROR); return NULL; };
|
|
|
|
BZ_SETERR(BZ_OK);
|
|
|
|
bzf->initialisedOk = False;
|
|
bzf->handle = f;
|
|
bzf->bufN = 0;
|
|
bzf->writing = False;
|
|
bzf->strm.bzalloc = NULL;
|
|
bzf->strm.bzfree = NULL;
|
|
bzf->strm.opaque = NULL;
|
|
|
|
while (nUnused > 0) {
|
|
bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
|
|
unused = ((void*)( 1 + ((UChar*)(unused)) ));
|
|
nUnused--;
|
|
}
|
|
|
|
ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
|
|
if (ret != BZ_OK)
|
|
{ BZ_SETERR(ret); free(bzf); return NULL; };
|
|
|
|
bzf->strm.avail_in = bzf->bufN;
|
|
bzf->strm.next_in = bzf->buf;
|
|
|
|
bzf->initialisedOk = True;
|
|
return bzf;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------*/
|
|
void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
|
|
{
|
|
bzFile* bzf = (bzFile*)b;
|
|
|
|
BZ_SETERR(BZ_OK);
|
|
if (bzf == NULL)
|
|
{ BZ_SETERR(BZ_OK); return; };
|
|
|
|
if (bzf->writing)
|
|
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
|
|
|
|
if (bzf->initialisedOk)
|
|
(void)BZ2_bzDecompressEnd ( &(bzf->strm) );
|
|
free ( bzf );
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------*/
|
|
int BZ_API(BZ2_bzRead)
|
|
( int* bzerror,
|
|
BZFILE* b,
|
|
void* buf,
|
|
int len )
|
|
{
|
|
Int32 n, ret;
|
|
bzFile* bzf = (bzFile*)b;
|
|
|
|
BZ_SETERR(BZ_OK);
|
|
|
|
if (bzf == NULL || buf == NULL || len < 0)
|
|
{ BZ_SETERR(BZ_PARAM_ERROR); return 0; };
|
|
|
|
if (bzf->writing)
|
|
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
|
|
|
|
if (len == 0)
|
|
{ BZ_SETERR(BZ_OK); return 0; };
|
|
|
|
bzf->strm.avail_out = len;
|
|
bzf->strm.next_out = buf;
|
|
|
|
while (True) {
|
|
|
|
if (ferror(bzf->handle))
|
|
{ BZ_SETERR(BZ_IO_ERROR); return 0; };
|
|
|
|
if (bzf->strm.avail_in == 0 && !bz_feof(bzf->handle)) {
|
|
n = fread ( bzf->buf, sizeof(UChar),
|
|
BZ_MAX_UNUSED, bzf->handle );
|
|
if (ferror(bzf->handle))
|
|
{ BZ_SETERR(BZ_IO_ERROR); return 0; };
|
|
bzf->bufN = n;
|
|
bzf->strm.avail_in = bzf->bufN;
|
|
bzf->strm.next_in = bzf->buf;
|
|
}
|
|
|
|
ret = BZ2_bzDecompress ( &(bzf->strm) );
|
|
|
|
if (ret != BZ_OK && ret != BZ_STREAM_END)
|
|
{ BZ_SETERR(ret); return 0; };
|
|
|
|
if (ret == BZ_OK && bz_feof(bzf->handle) &&
|
|
bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
|
|
{ BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
|
|
|
|
if (ret == BZ_STREAM_END)
|
|
{ BZ_SETERR(BZ_STREAM_END);
|
|
return len - bzf->strm.avail_out; };
|
|
if (bzf->strm.avail_out == 0)
|
|
{ BZ_SETERR(BZ_OK); return len; };
|
|
|
|
}
|
|
|
|
/* return 0; not reached*/
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------*/
|
|
void BZ_API(BZ2_bzReadGetUnused)
|
|
( int* bzerror,
|
|
BZFILE* b,
|
|
void** unused,
|
|
int* nUnused )
|
|
{
|
|
bzFile* bzf = (bzFile*)b;
|
|
if (bzf == NULL)
|
|
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
|
|
if (bzf->lastErr != BZ_STREAM_END)
|
|
{ BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
|
|
if (unused == NULL || nUnused == NULL)
|
|
{ BZ_SETERR(BZ_PARAM_ERROR); return; };
|
|
|
|
BZ_SETERR(BZ_OK);
|
|
*nUnused = bzf->strm.avail_in;
|
|
*unused = bzf->strm.next_in;
|
|
}
|