| /* 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; |
| } |