| /* 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_bzWriteOpen) |
| ( int* bzerror, |
| FILE* f, |
| int blockSize100k, |
| int verbosity, |
| int workFactor ) |
| { |
| Int32 ret; |
| bzFile* bzf = NULL; |
| |
| BZ_SETERR(BZ_OK); |
| |
| if (f == NULL || |
| (blockSize100k < 1 || blockSize100k > 9) || |
| (workFactor < 0 || workFactor > 250) || |
| (verbosity < 0 || verbosity > 4)) |
| { 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->bufN = 0; |
| bzf->handle = f; |
| bzf->writing = True; |
| bzf->strm.bzalloc = NULL; |
| bzf->strm.bzfree = NULL; |
| bzf->strm.opaque = NULL; |
| |
| if (workFactor == 0) workFactor = 30; |
| ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, |
| verbosity, workFactor ); |
| if (ret != BZ_OK) |
| { BZ_SETERR(ret); free(bzf); return NULL; }; |
| |
| bzf->strm.avail_in = 0; |
| bzf->initialisedOk = True; |
| return bzf; |
| } |
| |
| |
| |
| /*---------------------------------------------------*/ |
| void BZ_API(BZ2_bzWrite) |
| ( int* bzerror, |
| BZFILE* b, |
| void* buf, |
| int len ) |
| { |
| Int32 n, n2, ret; |
| bzFile* bzf = (bzFile*)b; |
| |
| BZ_SETERR(BZ_OK); |
| if (bzf == NULL || buf == NULL || len < 0) |
| { BZ_SETERR(BZ_PARAM_ERROR); return; }; |
| if (!(bzf->writing)) |
| { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; |
| if (ferror(bzf->handle)) |
| { BZ_SETERR(BZ_IO_ERROR); return; }; |
| |
| if (len == 0) |
| { BZ_SETERR(BZ_OK); return; }; |
| |
| bzf->strm.avail_in = len; |
| bzf->strm.next_in = buf; |
| |
| while (True) { |
| bzf->strm.avail_out = BZ_MAX_UNUSED; |
| bzf->strm.next_out = bzf->buf; |
| ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); |
| if (ret != BZ_RUN_OK) |
| { BZ_SETERR(ret); return; }; |
| |
| if (bzf->strm.avail_out < BZ_MAX_UNUSED) { |
| n = BZ_MAX_UNUSED - bzf->strm.avail_out; |
| n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), |
| n, bzf->handle ); |
| if (n != n2 || ferror(bzf->handle)) |
| { BZ_SETERR(BZ_IO_ERROR); return; }; |
| } |
| |
| if (bzf->strm.avail_in == 0) |
| { BZ_SETERR(BZ_OK); return; }; |
| } |
| } |
| |
| |
| /*---------------------------------------------------*/ |
| void BZ_API(BZ2_bzWriteClose) |
| ( int* bzerror, |
| BZFILE* b, |
| int abandon, |
| unsigned int* nbytes_in, |
| unsigned int* nbytes_out ) |
| { |
| BZ2_bzWriteClose64 ( bzerror, b, abandon, |
| nbytes_in, NULL, nbytes_out, NULL ); |
| } |
| |
| |
| 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 ) |
| { |
| Int32 n, n2, ret; |
| bzFile* bzf = (bzFile*)b; |
| |
| if (bzf == NULL) |
| { BZ_SETERR(BZ_OK); return; }; |
| if (!(bzf->writing)) |
| { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; |
| if (ferror(bzf->handle)) |
| { BZ_SETERR(BZ_IO_ERROR); return; }; |
| |
| if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; |
| if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; |
| if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; |
| if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; |
| |
| if ((!abandon) && bzf->lastErr == BZ_OK) { |
| while (True) { |
| bzf->strm.avail_out = BZ_MAX_UNUSED; |
| bzf->strm.next_out = bzf->buf; |
| ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); |
| if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) |
| { BZ_SETERR(ret); return; }; |
| |
| if (bzf->strm.avail_out < BZ_MAX_UNUSED) { |
| n = BZ_MAX_UNUSED - bzf->strm.avail_out; |
| n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), |
| n, bzf->handle ); |
| if (n != n2 || ferror(bzf->handle)) |
| { BZ_SETERR(BZ_IO_ERROR); return; }; |
| } |
| |
| if (ret == BZ_STREAM_END) break; |
| } |
| } |
| |
| if ( !abandon && !ferror ( bzf->handle ) ) { |
| fflush ( bzf->handle ); |
| if (ferror(bzf->handle)) |
| { BZ_SETERR(BZ_IO_ERROR); return; }; |
| } |
| |
| if (nbytes_in_lo32 != NULL) |
| *nbytes_in_lo32 = bzf->strm.total_in_lo32; |
| if (nbytes_in_hi32 != NULL) |
| *nbytes_in_hi32 = bzf->strm.total_in_hi32; |
| if (nbytes_out_lo32 != NULL) |
| *nbytes_out_lo32 = bzf->strm.total_out_lo32; |
| if (nbytes_out_hi32 != NULL) |
| *nbytes_out_hi32 = bzf->strm.total_out_hi32; |
| |
| BZ_SETERR(BZ_OK); |
| BZ2_bzCompressEnd ( &(bzf->strm) ); |
| free ( bzf ); |
| } |
| |