xref: /plan9/sys/src/cmd/bzip2/lib/bzread.c (revision b85a83648eec38fe82b6f00adfd7828ceec5ee8d)
1*59cc4ca5SDavid du Colombier /* THIS FILE HAS BEEN MODIFIED -- rsc split bzlib.c into bzlib.c,
2*59cc4ca5SDavid du Colombier 		bzlibcompress.c, bzlibdecompress.c, bzlibread.c, bzlibwrite.c
3*59cc4ca5SDavid du Colombier  */
4*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
5*59cc4ca5SDavid du Colombier /*--- Library top-level functions.                          ---*/
6*59cc4ca5SDavid du Colombier /*---                                               bzlib.c ---*/
7*59cc4ca5SDavid du Colombier /*-------------------------------------------------------------*/
8*59cc4ca5SDavid du Colombier 
9*59cc4ca5SDavid du Colombier /*--
10*59cc4ca5SDavid du Colombier   This file is a part of bzip2 and/or libbzip2, a program and
11*59cc4ca5SDavid du Colombier   library for lossless, block-sorting data compression.
12*59cc4ca5SDavid du Colombier 
13*59cc4ca5SDavid du Colombier   Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
14*59cc4ca5SDavid du Colombier 
15*59cc4ca5SDavid du Colombier   Redistribution and use in source and binary forms, with or without
16*59cc4ca5SDavid du Colombier   modification, are permitted provided that the following conditions
17*59cc4ca5SDavid du Colombier   are met:
18*59cc4ca5SDavid du Colombier 
19*59cc4ca5SDavid du Colombier   1. Redistributions of source code must retain the above copyright
20*59cc4ca5SDavid du Colombier      notice, this list of conditions and the following disclaimer.
21*59cc4ca5SDavid du Colombier 
22*59cc4ca5SDavid du Colombier   2. The origin of this software must not be misrepresented; you must
23*59cc4ca5SDavid du Colombier      not claim that you wrote the original software.  If you use this
24*59cc4ca5SDavid du Colombier      software in a product, an acknowledgment in the product
25*59cc4ca5SDavid du Colombier      documentation would be appreciated but is not required.
26*59cc4ca5SDavid du Colombier 
27*59cc4ca5SDavid du Colombier   3. Altered source versions must be plainly marked as such, and must
28*59cc4ca5SDavid du Colombier      not be misrepresented as being the original software.
29*59cc4ca5SDavid du Colombier 
30*59cc4ca5SDavid du Colombier   4. The name of the author may not be used to endorse or promote
31*59cc4ca5SDavid du Colombier      products derived from this software without specific prior written
32*59cc4ca5SDavid du Colombier      permission.
33*59cc4ca5SDavid du Colombier 
34*59cc4ca5SDavid du Colombier   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
35*59cc4ca5SDavid du Colombier   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36*59cc4ca5SDavid du Colombier   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37*59cc4ca5SDavid du Colombier   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
38*59cc4ca5SDavid du Colombier   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39*59cc4ca5SDavid du Colombier   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40*59cc4ca5SDavid du Colombier   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41*59cc4ca5SDavid du Colombier   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42*59cc4ca5SDavid du Colombier   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43*59cc4ca5SDavid du Colombier   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44*59cc4ca5SDavid du Colombier   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*59cc4ca5SDavid du Colombier 
46*59cc4ca5SDavid du Colombier   Julian Seward, Cambridge, UK.
47*59cc4ca5SDavid du Colombier   jseward@acm.org
48*59cc4ca5SDavid du Colombier   bzip2/libbzip2 version 1.0 of 21 March 2000
49*59cc4ca5SDavid du Colombier 
50*59cc4ca5SDavid du Colombier   This program is based on (at least) the work of:
51*59cc4ca5SDavid du Colombier      Mike Burrows
52*59cc4ca5SDavid du Colombier      David Wheeler
53*59cc4ca5SDavid du Colombier      Peter Fenwick
54*59cc4ca5SDavid du Colombier      Alistair Moffat
55*59cc4ca5SDavid du Colombier      Radford Neal
56*59cc4ca5SDavid du Colombier      Ian H. Witten
57*59cc4ca5SDavid du Colombier      Robert Sedgewick
58*59cc4ca5SDavid du Colombier      Jon L. Bentley
59*59cc4ca5SDavid du Colombier 
60*59cc4ca5SDavid du Colombier   For more information on these sources, see the manual.
61*59cc4ca5SDavid du Colombier --*/
62*59cc4ca5SDavid du Colombier 
63*59cc4ca5SDavid du Colombier /*--
64*59cc4ca5SDavid du Colombier    CHANGES
65*59cc4ca5SDavid du Colombier    ~~~~~~~
66*59cc4ca5SDavid du Colombier    0.9.0 -- original version.
67*59cc4ca5SDavid du Colombier 
68*59cc4ca5SDavid du Colombier    0.9.0a/b -- no changes in this file.
69*59cc4ca5SDavid du Colombier 
70*59cc4ca5SDavid du Colombier    0.9.0c
71*59cc4ca5SDavid du Colombier       * made zero-length BZ_FLUSH work correctly in bzCompress().
72*59cc4ca5SDavid du Colombier       * fixed bzWrite/bzRead to ignore zero-length requests.
73*59cc4ca5SDavid du Colombier       * fixed bzread to correctly handle read requests after EOF.
74*59cc4ca5SDavid du Colombier       * wrong parameter order in call to bzDecompressInit in
75*59cc4ca5SDavid du Colombier         bzBuffToBuffDecompress.  Fixed.
76*59cc4ca5SDavid du Colombier --*/
77*59cc4ca5SDavid du Colombier 
78*59cc4ca5SDavid du Colombier #include "os.h"
79*59cc4ca5SDavid du Colombier #include "bzlib.h"
80*59cc4ca5SDavid du Colombier #include "bzlib_private.h"
81*59cc4ca5SDavid du Colombier #include "bzlib_stdio.h"
82*59cc4ca5SDavid du Colombier #include "bzlib_stdio_private.h"
83*59cc4ca5SDavid du Colombier 
84*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzReadOpen)85*59cc4ca5SDavid du Colombier BZFILE* BZ_API(BZ2_bzReadOpen)
86*59cc4ca5SDavid du Colombier                    ( int*  bzerror,
87*59cc4ca5SDavid du Colombier                      FILE* f,
88*59cc4ca5SDavid du Colombier                      int   verbosity,
89*59cc4ca5SDavid du Colombier                      int   small,
90*59cc4ca5SDavid du Colombier                      void* unused,
91*59cc4ca5SDavid du Colombier                      int   nUnused )
92*59cc4ca5SDavid du Colombier {
93*59cc4ca5SDavid du Colombier    bzFile* bzf = NULL;
94*59cc4ca5SDavid du Colombier    int     ret;
95*59cc4ca5SDavid du Colombier 
96*59cc4ca5SDavid du Colombier    BZ_SETERR(BZ_OK);
97*59cc4ca5SDavid du Colombier 
98*59cc4ca5SDavid du Colombier    if (f == NULL ||
99*59cc4ca5SDavid du Colombier        (small != 0 && small != 1) ||
100*59cc4ca5SDavid du Colombier        (verbosity < 0 || verbosity > 4) ||
101*59cc4ca5SDavid du Colombier        (unused == NULL && nUnused != 0) ||
102*59cc4ca5SDavid du Colombier        (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
103*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
104*59cc4ca5SDavid du Colombier 
105*59cc4ca5SDavid du Colombier    if (ferror(f))
106*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_IO_ERROR); return NULL; };
107*59cc4ca5SDavid du Colombier 
108*59cc4ca5SDavid du Colombier    bzf = malloc ( sizeof(bzFile) );
109*59cc4ca5SDavid du Colombier    if (bzf == NULL)
110*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_MEM_ERROR); return NULL; };
111*59cc4ca5SDavid du Colombier 
112*59cc4ca5SDavid du Colombier    BZ_SETERR(BZ_OK);
113*59cc4ca5SDavid du Colombier 
114*59cc4ca5SDavid du Colombier    bzf->initialisedOk = False;
115*59cc4ca5SDavid du Colombier    bzf->handle        = f;
116*59cc4ca5SDavid du Colombier    bzf->bufN          = 0;
117*59cc4ca5SDavid du Colombier    bzf->writing       = False;
118*59cc4ca5SDavid du Colombier    bzf->strm.bzalloc  = NULL;
119*59cc4ca5SDavid du Colombier    bzf->strm.bzfree   = NULL;
120*59cc4ca5SDavid du Colombier    bzf->strm.opaque   = NULL;
121*59cc4ca5SDavid du Colombier 
122*59cc4ca5SDavid du Colombier    while (nUnused > 0) {
123*59cc4ca5SDavid du Colombier       bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++;
124*59cc4ca5SDavid du Colombier       unused = ((void*)( 1 + ((UChar*)(unused))  ));
125*59cc4ca5SDavid du Colombier       nUnused--;
126*59cc4ca5SDavid du Colombier    }
127*59cc4ca5SDavid du Colombier 
128*59cc4ca5SDavid du Colombier    ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small );
129*59cc4ca5SDavid du Colombier    if (ret != BZ_OK)
130*59cc4ca5SDavid du Colombier       { BZ_SETERR(ret); free(bzf); return NULL; };
131*59cc4ca5SDavid du Colombier 
132*59cc4ca5SDavid du Colombier    bzf->strm.avail_in = bzf->bufN;
133*59cc4ca5SDavid du Colombier    bzf->strm.next_in  = bzf->buf;
134*59cc4ca5SDavid du Colombier 
135*59cc4ca5SDavid du Colombier    bzf->initialisedOk = True;
136*59cc4ca5SDavid du Colombier    return bzf;
137*59cc4ca5SDavid du Colombier }
138*59cc4ca5SDavid du Colombier 
139*59cc4ca5SDavid du Colombier 
140*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzReadClose)141*59cc4ca5SDavid du Colombier void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b )
142*59cc4ca5SDavid du Colombier {
143*59cc4ca5SDavid du Colombier    bzFile* bzf = (bzFile*)b;
144*59cc4ca5SDavid du Colombier 
145*59cc4ca5SDavid du Colombier    BZ_SETERR(BZ_OK);
146*59cc4ca5SDavid du Colombier    if (bzf == NULL)
147*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_OK); return; };
148*59cc4ca5SDavid du Colombier 
149*59cc4ca5SDavid du Colombier    if (bzf->writing)
150*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
151*59cc4ca5SDavid du Colombier 
152*59cc4ca5SDavid du Colombier    if (bzf->initialisedOk)
153*59cc4ca5SDavid du Colombier       (void)BZ2_bzDecompressEnd ( &(bzf->strm) );
154*59cc4ca5SDavid du Colombier    free ( bzf );
155*59cc4ca5SDavid du Colombier }
156*59cc4ca5SDavid du Colombier 
157*59cc4ca5SDavid du Colombier 
158*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzRead)159*59cc4ca5SDavid du Colombier int BZ_API(BZ2_bzRead)
160*59cc4ca5SDavid du Colombier            ( int*    bzerror,
161*59cc4ca5SDavid du Colombier              BZFILE* b,
162*59cc4ca5SDavid du Colombier              void*   buf,
163*59cc4ca5SDavid du Colombier              int     len )
164*59cc4ca5SDavid du Colombier {
165*59cc4ca5SDavid du Colombier    Int32   n, ret;
166*59cc4ca5SDavid du Colombier    bzFile* bzf = (bzFile*)b;
167*59cc4ca5SDavid du Colombier 
168*59cc4ca5SDavid du Colombier    BZ_SETERR(BZ_OK);
169*59cc4ca5SDavid du Colombier 
170*59cc4ca5SDavid du Colombier    if (bzf == NULL || buf == NULL || len < 0)
171*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_PARAM_ERROR); return 0; };
172*59cc4ca5SDavid du Colombier 
173*59cc4ca5SDavid du Colombier    if (bzf->writing)
174*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; };
175*59cc4ca5SDavid du Colombier 
176*59cc4ca5SDavid du Colombier    if (len == 0)
177*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_OK); return 0; };
178*59cc4ca5SDavid du Colombier 
179*59cc4ca5SDavid du Colombier    bzf->strm.avail_out = len;
180*59cc4ca5SDavid du Colombier    bzf->strm.next_out = buf;
181*59cc4ca5SDavid du Colombier 
182*59cc4ca5SDavid du Colombier    while (True) {
183*59cc4ca5SDavid du Colombier 
184*59cc4ca5SDavid du Colombier       if (ferror(bzf->handle))
185*59cc4ca5SDavid du Colombier          { BZ_SETERR(BZ_IO_ERROR); return 0; };
186*59cc4ca5SDavid du Colombier 
187*59cc4ca5SDavid du Colombier       if (bzf->strm.avail_in == 0 && !bz_feof(bzf->handle)) {
188*59cc4ca5SDavid du Colombier          n = fread ( bzf->buf, sizeof(UChar),
189*59cc4ca5SDavid du Colombier                      BZ_MAX_UNUSED, bzf->handle );
190*59cc4ca5SDavid du Colombier          if (ferror(bzf->handle))
191*59cc4ca5SDavid du Colombier             { BZ_SETERR(BZ_IO_ERROR); return 0; };
192*59cc4ca5SDavid du Colombier          bzf->bufN = n;
193*59cc4ca5SDavid du Colombier          bzf->strm.avail_in = bzf->bufN;
194*59cc4ca5SDavid du Colombier          bzf->strm.next_in = bzf->buf;
195*59cc4ca5SDavid du Colombier       }
196*59cc4ca5SDavid du Colombier 
197*59cc4ca5SDavid du Colombier       ret = BZ2_bzDecompress ( &(bzf->strm) );
198*59cc4ca5SDavid du Colombier 
199*59cc4ca5SDavid du Colombier       if (ret != BZ_OK && ret != BZ_STREAM_END)
200*59cc4ca5SDavid du Colombier          { BZ_SETERR(ret); return 0; };
201*59cc4ca5SDavid du Colombier 
202*59cc4ca5SDavid du Colombier       if (ret == BZ_OK && bz_feof(bzf->handle) &&
203*59cc4ca5SDavid du Colombier           bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0)
204*59cc4ca5SDavid du Colombier          { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; };
205*59cc4ca5SDavid du Colombier 
206*59cc4ca5SDavid du Colombier       if (ret == BZ_STREAM_END)
207*59cc4ca5SDavid du Colombier          { BZ_SETERR(BZ_STREAM_END);
208*59cc4ca5SDavid du Colombier            return len - bzf->strm.avail_out; };
209*59cc4ca5SDavid du Colombier       if (bzf->strm.avail_out == 0)
210*59cc4ca5SDavid du Colombier          { BZ_SETERR(BZ_OK); return len; };
211*59cc4ca5SDavid du Colombier 
212*59cc4ca5SDavid du Colombier    }
213*59cc4ca5SDavid du Colombier 
214*59cc4ca5SDavid du Colombier }
215*59cc4ca5SDavid du Colombier 
216*59cc4ca5SDavid du Colombier 
217*59cc4ca5SDavid du Colombier /*---------------------------------------------------*/
BZ_API(BZ2_bzReadGetUnused)218*59cc4ca5SDavid du Colombier void BZ_API(BZ2_bzReadGetUnused)
219*59cc4ca5SDavid du Colombier                      ( int*    bzerror,
220*59cc4ca5SDavid du Colombier                        BZFILE* b,
221*59cc4ca5SDavid du Colombier                        void**  unused,
222*59cc4ca5SDavid du Colombier                        int*    nUnused )
223*59cc4ca5SDavid du Colombier {
224*59cc4ca5SDavid du Colombier    bzFile* bzf = (bzFile*)b;
225*59cc4ca5SDavid du Colombier    if (bzf == NULL)
226*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_PARAM_ERROR); return; };
227*59cc4ca5SDavid du Colombier    if (bzf->lastErr != BZ_STREAM_END)
228*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_SEQUENCE_ERROR); return; };
229*59cc4ca5SDavid du Colombier    if (unused == NULL || nUnused == NULL)
230*59cc4ca5SDavid du Colombier       { BZ_SETERR(BZ_PARAM_ERROR); return; };
231*59cc4ca5SDavid du Colombier 
232*59cc4ca5SDavid du Colombier    BZ_SETERR(BZ_OK);
233*59cc4ca5SDavid du Colombier    *nUnused = bzf->strm.avail_in;
234*59cc4ca5SDavid du Colombier    *unused = bzf->strm.next_in;
235*59cc4ca5SDavid du Colombier }
236