xref: /plan9/sys/src/cmd/bzip2/lib/bzzlib.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1*59cc4ca5SDavid du Colombier /*
2*59cc4ca5SDavid du Colombier  * THIS FILE IS NOT IDENTICAL TO THE ORIGINAL
3*59cc4ca5SDavid du Colombier  * FROM THE BZIP2 DISTRIBUTION.
4*59cc4ca5SDavid du Colombier  *
5*59cc4ca5SDavid du Colombier  * It has been modified, mainly to break the library
6*59cc4ca5SDavid du Colombier  * into smaller pieces.
7*59cc4ca5SDavid du Colombier  *
8*59cc4ca5SDavid du Colombier  * Russ Cox
9*59cc4ca5SDavid du Colombier  * rsc@plan9.bell-labs.com
10*59cc4ca5SDavid du Colombier  * July 2000
11*59cc4ca5SDavid du Colombier  */
12*59cc4ca5SDavid du Colombier 
13*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
14*59cc4ca5SDavid du Colombier /*--- Library top-level functions.                          ---*/
15*59cc4ca5SDavid du Colombier /*---                                               bzlib.c ---*/
16*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
17*59cc4ca5SDavid du Colombier 
18*59cc4ca5SDavid du Colombier /*--
19*59cc4ca5SDavid du Colombier   This file is a part of bzip2 and/or libbzip2, a program and
20*59cc4ca5SDavid du Colombier   library for lossless, block-sorting data compression.
21*59cc4ca5SDavid du Colombier 
22*59cc4ca5SDavid du Colombier   Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
23*59cc4ca5SDavid du Colombier 
24*59cc4ca5SDavid du Colombier   Redistribution and use in source and binary forms, with or without
25*59cc4ca5SDavid du Colombier   modification, are permitted provided that the following conditions
26*59cc4ca5SDavid du Colombier   are met:
27*59cc4ca5SDavid du Colombier 
28*59cc4ca5SDavid du Colombier   1. Redistributions of source code must retain the above copyright
29*59cc4ca5SDavid du Colombier      notice, this list of conditions and the following disclaimer.
30*59cc4ca5SDavid du Colombier 
31*59cc4ca5SDavid du Colombier   2. The origin of this software must not be misrepresented; you must
32*59cc4ca5SDavid du Colombier      not claim that you wrote the original software.  If you use this
33*59cc4ca5SDavid du Colombier      software in a product, an acknowledgment in the product
34*59cc4ca5SDavid du Colombier      documentation would be appreciated but is not required.
35*59cc4ca5SDavid du Colombier 
36*59cc4ca5SDavid du Colombier   3. Altered source versions must be plainly marked as such, and must
37*59cc4ca5SDavid du Colombier      not be misrepresented as being the original software.
38*59cc4ca5SDavid du Colombier 
39*59cc4ca5SDavid du Colombier   4. The name of the author may not be used to endorse or promote
40*59cc4ca5SDavid du Colombier      products derived from this software without specific prior written
41*59cc4ca5SDavid du Colombier      permission.
42*59cc4ca5SDavid du Colombier 
43*59cc4ca5SDavid du Colombier   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
44*59cc4ca5SDavid du Colombier   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45*59cc4ca5SDavid du Colombier   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46*59cc4ca5SDavid du Colombier   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
47*59cc4ca5SDavid du Colombier   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48*59cc4ca5SDavid du Colombier   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
49*59cc4ca5SDavid du Colombier   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50*59cc4ca5SDavid du Colombier   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51*59cc4ca5SDavid du Colombier   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
52*59cc4ca5SDavid du Colombier   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53*59cc4ca5SDavid du Colombier   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54*59cc4ca5SDavid du Colombier 
55*59cc4ca5SDavid du Colombier   Julian Seward, Cambridge, UK.
56*59cc4ca5SDavid du Colombier   jseward@acm.org
57*59cc4ca5SDavid du Colombier   bzip2/libbzip2 version 1.0 of 21 March 2000
58*59cc4ca5SDavid du Colombier 
59*59cc4ca5SDavid du Colombier   This program is based on (at least) the work of:
60*59cc4ca5SDavid du Colombier      Mike Burrows
61*59cc4ca5SDavid du Colombier      David Wheeler
62*59cc4ca5SDavid du Colombier      Peter Fenwick
63*59cc4ca5SDavid du Colombier      Alistair Moffat
64*59cc4ca5SDavid du Colombier      Radford Neal
65*59cc4ca5SDavid du Colombier      Ian H. Witten
66*59cc4ca5SDavid du Colombier      Robert Sedgewick
67*59cc4ca5SDavid du Colombier      Jon L. Bentley
68*59cc4ca5SDavid du Colombier 
69*59cc4ca5SDavid du Colombier   For more information on these sources, see the manual.
70*59cc4ca5SDavid du Colombier --*/
71*59cc4ca5SDavid du Colombier 
72*59cc4ca5SDavid du Colombier /*--
73*59cc4ca5SDavid du Colombier    CHANGES
74*59cc4ca5SDavid du Colombier    ~~~~~~~
75*59cc4ca5SDavid du Colombier    0.9.0 -- original version.
76*59cc4ca5SDavid du Colombier 
77*59cc4ca5SDavid du Colombier    0.9.0a/b -- no changes in this file.
78*59cc4ca5SDavid du Colombier 
79*59cc4ca5SDavid du Colombier    0.9.0c
80*59cc4ca5SDavid du Colombier       * made zero-length BZ_FLUSH work correctly in bzCompress().
81*59cc4ca5SDavid du Colombier       * fixed bzWrite/bzRead to ignore zero-length requests.
82*59cc4ca5SDavid du Colombier       * fixed bzread to correctly handle read requests after EOF.
83*59cc4ca5SDavid du Colombier       * wrong parameter order in call to bzDecompressInit in
84*59cc4ca5SDavid du Colombier         bzBuffToBuffDecompress.  Fixed.
85*59cc4ca5SDavid du Colombier --*/
86*59cc4ca5SDavid du Colombier 
87*59cc4ca5SDavid du Colombier #include "os.h"
88*59cc4ca5SDavid du Colombier #include "bzlib.h"
89*59cc4ca5SDavid du Colombier #include "bzlib_private.h"
90*59cc4ca5SDavid du Colombier #include "bzlib_stdio.h"
91*59cc4ca5SDavid du Colombier #include "bzlib_stdio_private.h"
92*59cc4ca5SDavid du Colombier 
93*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
94*59cc4ca5SDavid du Colombier /*--
95*59cc4ca5SDavid du Colombier    Code contributed by Yoshioka Tsuneo
96*59cc4ca5SDavid du Colombier    (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
97*59cc4ca5SDavid du Colombier    to support better zlib compatibility.
98*59cc4ca5SDavid du Colombier    This code is not _officially_ part of libbzip2 (yet);
99*59cc4ca5SDavid du Colombier    I haven't tested it, documented it, or considered the
100*59cc4ca5SDavid du Colombier    threading-safeness of it.
101*59cc4ca5SDavid du Colombier    If this code breaks, please contact both Yoshioka and me.
102*59cc4ca5SDavid du Colombier --*/
103*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
104*59cc4ca5SDavid du Colombier 
105*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
106*59cc4ca5SDavid du Colombier 
107*59cc4ca5SDavid du Colombier #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
108*59cc4ca5SDavid du Colombier #   include <fcntl.h>
109*59cc4ca5SDavid du Colombier #   include <io.h>
110*59cc4ca5SDavid du Colombier #   define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
111*59cc4ca5SDavid du Colombier #else
112*59cc4ca5SDavid du Colombier #   define SET_BINARY_MODE(file)
113*59cc4ca5SDavid du Colombier #endif
114*59cc4ca5SDavid du Colombier static
bzopen_or_bzdopen(const char * path,int fd,const char * mode,int open_mode)115*59cc4ca5SDavid du Colombier BZFILE * bzopen_or_bzdopen
116*59cc4ca5SDavid du Colombier                ( const char *path,   /* no use when bzdopen */
117*59cc4ca5SDavid du Colombier                  int fd,             /* no use when bzdopen */
118*59cc4ca5SDavid du Colombier                  const char *mode,
119*59cc4ca5SDavid du Colombier                  int open_mode)      /* bzopen: 0, bzdopen:1 */
120*59cc4ca5SDavid du Colombier {
121*59cc4ca5SDavid du Colombier    int    bzerr;
122*59cc4ca5SDavid du Colombier    char   unused[BZ_MAX_UNUSED];
123*59cc4ca5SDavid du Colombier    int    blockSize100k = 9;
124*59cc4ca5SDavid du Colombier    int    writing       = 0;
125*59cc4ca5SDavid du Colombier    char   mode2[10]     = "";
126*59cc4ca5SDavid du Colombier    FILE   *fp           = NULL;
127*59cc4ca5SDavid du Colombier    BZFILE *bzfp         = NULL;
128*59cc4ca5SDavid du Colombier    int    verbosity     = 0;
129*59cc4ca5SDavid du Colombier    int    workFactor    = 30;
130*59cc4ca5SDavid du Colombier    int    smallMode     = 0;
131*59cc4ca5SDavid du Colombier    int    nUnused       = 0;
132*59cc4ca5SDavid du Colombier 
133*59cc4ca5SDavid du Colombier    if (mode == NULL) return NULL;
134*59cc4ca5SDavid du Colombier    while (*mode) {
135*59cc4ca5SDavid du Colombier       switch (*mode) {
136*59cc4ca5SDavid du Colombier       case 'r':
137*59cc4ca5SDavid du Colombier          writing = 0; break;
138*59cc4ca5SDavid du Colombier       case 'w':
139*59cc4ca5SDavid du Colombier          writing = 1; break;
140*59cc4ca5SDavid du Colombier       case 's':
141*59cc4ca5SDavid du Colombier          smallMode = 1; break;
142*59cc4ca5SDavid du Colombier       default:
143*59cc4ca5SDavid du Colombier          if (isdigit((int)(*mode))) {
144*59cc4ca5SDavid du Colombier             blockSize100k = *mode-'0';
145*59cc4ca5SDavid du Colombier          }
146*59cc4ca5SDavid du Colombier       }
147*59cc4ca5SDavid du Colombier       mode++;
148*59cc4ca5SDavid du Colombier    }
149*59cc4ca5SDavid du Colombier    strcat(mode2, writing ? "w" : "r" );
150*59cc4ca5SDavid du Colombier    strcat(mode2,"b");   /* binary mode */
151*59cc4ca5SDavid du Colombier 
152*59cc4ca5SDavid du Colombier    if (open_mode==0) {
153*59cc4ca5SDavid du Colombier       if (path==NULL || strcmp(path,"")==0) {
154*59cc4ca5SDavid du Colombier         fp = (writing ? stdout : stdin);
155*59cc4ca5SDavid du Colombier         SET_BINARY_MODE(fp);
156*59cc4ca5SDavid du Colombier       } else {
157*59cc4ca5SDavid du Colombier         fp = fopen(path,mode2);
158*59cc4ca5SDavid du Colombier       }
159*59cc4ca5SDavid du Colombier    } else {
160*59cc4ca5SDavid du Colombier #ifdef BZ_STRICT_ANSI
161*59cc4ca5SDavid du Colombier       fp = NULL;
162*59cc4ca5SDavid du Colombier #else
163*59cc4ca5SDavid du Colombier       fp = fdopen(fd,mode2);
164*59cc4ca5SDavid du Colombier #endif
165*59cc4ca5SDavid du Colombier    }
166*59cc4ca5SDavid du Colombier    if (fp == NULL) return NULL;
167*59cc4ca5SDavid du Colombier 
168*59cc4ca5SDavid du Colombier    if (writing) {
169*59cc4ca5SDavid du Colombier       /* Guard against total chaos and anarchy -- JRS */
170*59cc4ca5SDavid du Colombier       if (blockSize100k < 1) blockSize100k = 1;
171*59cc4ca5SDavid du Colombier       if (blockSize100k > 9) blockSize100k = 9;
172*59cc4ca5SDavid du Colombier       bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k,
173*59cc4ca5SDavid du Colombier                              verbosity,workFactor);
174*59cc4ca5SDavid du Colombier    } else {
175*59cc4ca5SDavid du Colombier       bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode,
176*59cc4ca5SDavid du Colombier                             unused,nUnused);
177*59cc4ca5SDavid du Colombier    }
178*59cc4ca5SDavid du Colombier    if (bzfp == NULL) {
179*59cc4ca5SDavid du Colombier       if (fp != stdin && fp != stdout) fclose(fp);
180*59cc4ca5SDavid du Colombier       return NULL;
181*59cc4ca5SDavid du Colombier    }
182*59cc4ca5SDavid du Colombier    return bzfp;
183*59cc4ca5SDavid du Colombier }
184*59cc4ca5SDavid du Colombier 
185*59cc4ca5SDavid du Colombier 
186*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
187*59cc4ca5SDavid du Colombier /*--
188*59cc4ca5SDavid du Colombier    open file for read or write.
189*59cc4ca5SDavid du Colombier       ex) bzopen("file","w9")
190*59cc4ca5SDavid du Colombier       case path="" or NULL => use stdin or stdout.
191*59cc4ca5SDavid du Colombier --*/
BZ_API(BZ2_bzopen)192*59cc4ca5SDavid du Colombier BZFILE * BZ_API(BZ2_bzopen)
193*59cc4ca5SDavid du Colombier                ( const char *path,
194*59cc4ca5SDavid du Colombier                  const char *mode )
195*59cc4ca5SDavid du Colombier {
196*59cc4ca5SDavid du Colombier    return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0);
197*59cc4ca5SDavid du Colombier }
198*59cc4ca5SDavid du Colombier 
199*59cc4ca5SDavid du Colombier 
200*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzdopen)201*59cc4ca5SDavid du Colombier BZFILE * BZ_API(BZ2_bzdopen)
202*59cc4ca5SDavid du Colombier                ( int fd,
203*59cc4ca5SDavid du Colombier                  const char *mode )
204*59cc4ca5SDavid du Colombier {
205*59cc4ca5SDavid du Colombier    return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1);
206*59cc4ca5SDavid du Colombier }
207*59cc4ca5SDavid du Colombier 
208*59cc4ca5SDavid du Colombier 
209*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzread)210*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len )
211*59cc4ca5SDavid du Colombier {
212*59cc4ca5SDavid du Colombier    int bzerr, nread;
213*59cc4ca5SDavid du Colombier    if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0;
214*59cc4ca5SDavid du Colombier    nread = BZ2_bzRead(&bzerr,b,buf,len);
215*59cc4ca5SDavid du Colombier    if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
216*59cc4ca5SDavid du Colombier       return nread;
217*59cc4ca5SDavid du Colombier    } else {
218*59cc4ca5SDavid du Colombier       return -1;
219*59cc4ca5SDavid du Colombier    }
220*59cc4ca5SDavid du Colombier }
221*59cc4ca5SDavid du Colombier 
222*59cc4ca5SDavid du Colombier 
223*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzwrite)224*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len )
225*59cc4ca5SDavid du Colombier {
226*59cc4ca5SDavid du Colombier    int bzerr;
227*59cc4ca5SDavid du Colombier 
228*59cc4ca5SDavid du Colombier    BZ2_bzWrite(&bzerr,b,buf,len);
229*59cc4ca5SDavid du Colombier    if(bzerr == BZ_OK){
230*59cc4ca5SDavid du Colombier       return len;
231*59cc4ca5SDavid du Colombier    }else{
232*59cc4ca5SDavid du Colombier       return -1;
233*59cc4ca5SDavid du Colombier    }
234*59cc4ca5SDavid du Colombier }
235*59cc4ca5SDavid du Colombier 
236*59cc4ca5SDavid du Colombier 
237*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzflush)238*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzflush) (BZFILE *b)
239*59cc4ca5SDavid du Colombier {
240*59cc4ca5SDavid du Colombier    /* do nothing now... */
241*59cc4ca5SDavid du Colombier    return 0;
242*59cc4ca5SDavid du Colombier }
243*59cc4ca5SDavid du Colombier 
244*59cc4ca5SDavid du Colombier 
245*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzclose)246*59cc4ca5SDavid du Colombier void BZ_API(BZ2_bzclose) (BZFILE* b)
247*59cc4ca5SDavid du Colombier {
248*59cc4ca5SDavid du Colombier    int bzerr;
249*59cc4ca5SDavid du Colombier    FILE *fp = ((bzFile *)b)->handle;
250*59cc4ca5SDavid du Colombier 
251*59cc4ca5SDavid du Colombier    if (b==NULL) {return;}
252*59cc4ca5SDavid du Colombier    if(((bzFile*)b)->writing){
253*59cc4ca5SDavid du Colombier       BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL);
254*59cc4ca5SDavid du Colombier       if(bzerr != BZ_OK){
255*59cc4ca5SDavid du Colombier          BZ2_bzWriteClose(NULL,b,1,NULL,NULL);
256*59cc4ca5SDavid du Colombier       }
257*59cc4ca5SDavid du Colombier    }else{
258*59cc4ca5SDavid du Colombier       BZ2_bzReadClose(&bzerr,b);
259*59cc4ca5SDavid du Colombier    }
260*59cc4ca5SDavid du Colombier    if(fp!=stdin && fp!=stdout){
261*59cc4ca5SDavid du Colombier       fclose(fp);
262*59cc4ca5SDavid du Colombier    }
263*59cc4ca5SDavid du Colombier }
264*59cc4ca5SDavid du Colombier 
265*59cc4ca5SDavid du Colombier 
266*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
267*59cc4ca5SDavid du Colombier /*--
268*59cc4ca5SDavid du Colombier    return last error code
269*59cc4ca5SDavid du Colombier --*/
270*59cc4ca5SDavid du Colombier static char *bzerrorstrings[] = {
271*59cc4ca5SDavid du Colombier        "OK"
272*59cc4ca5SDavid du Colombier       ,"SEQUENCE_ERROR"
273*59cc4ca5SDavid du Colombier       ,"PARAM_ERROR"
274*59cc4ca5SDavid du Colombier       ,"MEM_ERROR"
275*59cc4ca5SDavid du Colombier       ,"DATA_ERROR"
276*59cc4ca5SDavid du Colombier       ,"DATA_ERROR_MAGIC"
277*59cc4ca5SDavid du Colombier       ,"IO_ERROR"
278*59cc4ca5SDavid du Colombier       ,"UNEXPECTED_EOF"
279*59cc4ca5SDavid du Colombier       ,"OUTBUFF_FULL"
280*59cc4ca5SDavid du Colombier       ,"CONFIG_ERROR"
281*59cc4ca5SDavid du Colombier       ,"???"   /* for future */
282*59cc4ca5SDavid du Colombier       ,"???"   /* for future */
283*59cc4ca5SDavid du Colombier       ,"???"   /* for future */
284*59cc4ca5SDavid du Colombier       ,"???"   /* for future */
285*59cc4ca5SDavid du Colombier       ,"???"   /* for future */
286*59cc4ca5SDavid du Colombier       ,"???"   /* for future */
287*59cc4ca5SDavid du Colombier };
288*59cc4ca5SDavid du Colombier 
289*59cc4ca5SDavid du Colombier 
BZ_API(BZ2_bzerror)290*59cc4ca5SDavid du Colombier const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum)
291*59cc4ca5SDavid du Colombier {
292*59cc4ca5SDavid du Colombier    int err = ((bzFile *)b)->lastErr;
293*59cc4ca5SDavid du Colombier 
294*59cc4ca5SDavid du Colombier    if(err>0) err = 0;
295*59cc4ca5SDavid du Colombier    *errnum = err;
296*59cc4ca5SDavid du Colombier    return bzerrorstrings[err*-1];
297*59cc4ca5SDavid du Colombier }
298