1fe927c51SPeter Avalos /* gzread.c -- zlib functions for reading gzip files
2*e041647aSSascha Wildner * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
3fe927c51SPeter Avalos * For conditions of distribution and use, see copyright notice in zlib.h
4fe927c51SPeter Avalos */
5fe927c51SPeter Avalos
6fe927c51SPeter Avalos #include "gzguts.h"
7fe927c51SPeter Avalos
8fe927c51SPeter Avalos /* Local functions */
9fe927c51SPeter Avalos local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
10fe927c51SPeter Avalos local int gz_avail OF((gz_statep));
11712f98b7SJohn Marino local int gz_look OF((gz_statep));
12fe927c51SPeter Avalos local int gz_decomp OF((gz_statep));
13712f98b7SJohn Marino local int gz_fetch OF((gz_statep));
14fe927c51SPeter Avalos local int gz_skip OF((gz_statep, z_off64_t));
15*e041647aSSascha Wildner local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
16fe927c51SPeter Avalos
17fe927c51SPeter Avalos /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
18fe927c51SPeter Avalos state->fd, and update state->eof, state->err, and state->msg as appropriate.
19fe927c51SPeter Avalos This function needs to loop on read(), since read() is not guaranteed to
20fe927c51SPeter Avalos read the number of bytes requested, depending on the type of descriptor. */
gz_load(state,buf,len,have)21fe927c51SPeter Avalos local int gz_load(state, buf, len, have)
22fe927c51SPeter Avalos gz_statep state;
23fe927c51SPeter Avalos unsigned char *buf;
24fe927c51SPeter Avalos unsigned len;
25fe927c51SPeter Avalos unsigned *have;
26fe927c51SPeter Avalos {
27fe927c51SPeter Avalos int ret;
28*e041647aSSascha Wildner unsigned get, max = ((unsigned)-1 >> 2) + 1;
29fe927c51SPeter Avalos
30fe927c51SPeter Avalos *have = 0;
31fe927c51SPeter Avalos do {
32*e041647aSSascha Wildner get = len - *have;
33*e041647aSSascha Wildner if (get > max)
34*e041647aSSascha Wildner get = max;
35*e041647aSSascha Wildner ret = read(state->fd, buf + *have, get);
36fe927c51SPeter Avalos if (ret <= 0)
37fe927c51SPeter Avalos break;
38*e041647aSSascha Wildner *have += (unsigned)ret;
39fe927c51SPeter Avalos } while (*have < len);
40fe927c51SPeter Avalos if (ret < 0) {
41fe927c51SPeter Avalos gz_error(state, Z_ERRNO, zstrerror());
42fe927c51SPeter Avalos return -1;
43fe927c51SPeter Avalos }
44fe927c51SPeter Avalos if (ret == 0)
45fe927c51SPeter Avalos state->eof = 1;
46fe927c51SPeter Avalos return 0;
47fe927c51SPeter Avalos }
48fe927c51SPeter Avalos
49fe927c51SPeter Avalos /* Load up input buffer and set eof flag if last data loaded -- return -1 on
50fe927c51SPeter Avalos error, 0 otherwise. Note that the eof flag is set when the end of the input
51fe927c51SPeter Avalos file is reached, even though there may be unused data in the buffer. Once
52fe927c51SPeter Avalos that data has been used, no more attempts will be made to read the file.
53712f98b7SJohn Marino If strm->avail_in != 0, then the current data is moved to the beginning of
54712f98b7SJohn Marino the input buffer, and then the remainder of the buffer is loaded with the
55712f98b7SJohn Marino available data from the input file. */
gz_avail(state)56fe927c51SPeter Avalos local int gz_avail(state)
57fe927c51SPeter Avalos gz_statep state;
58fe927c51SPeter Avalos {
59712f98b7SJohn Marino unsigned got;
60fe927c51SPeter Avalos z_streamp strm = &(state->strm);
61fe927c51SPeter Avalos
62712f98b7SJohn Marino if (state->err != Z_OK && state->err != Z_BUF_ERROR)
63fe927c51SPeter Avalos return -1;
64fe927c51SPeter Avalos if (state->eof == 0) {
65712f98b7SJohn Marino if (strm->avail_in) { /* copy what's there to the start */
6653ddf67cSJohn Marino unsigned char *p = state->in;
6753ddf67cSJohn Marino unsigned const char *q = strm->next_in;
68712f98b7SJohn Marino unsigned n = strm->avail_in;
69712f98b7SJohn Marino do {
70712f98b7SJohn Marino *p++ = *q++;
71712f98b7SJohn Marino } while (--n);
72712f98b7SJohn Marino }
73712f98b7SJohn Marino if (gz_load(state, state->in + strm->avail_in,
74712f98b7SJohn Marino state->size - strm->avail_in, &got) == -1)
75fe927c51SPeter Avalos return -1;
76712f98b7SJohn Marino strm->avail_in += got;
77fe927c51SPeter Avalos strm->next_in = state->in;
78fe927c51SPeter Avalos }
79fe927c51SPeter Avalos return 0;
80fe927c51SPeter Avalos }
81fe927c51SPeter Avalos
82712f98b7SJohn Marino /* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
83fe927c51SPeter Avalos If this is the first time in, allocate required memory. state->how will be
84fe927c51SPeter Avalos left unchanged if there is no more input data available, will be set to COPY
85fe927c51SPeter Avalos if there is no gzip header and direct copying will be performed, or it will
86712f98b7SJohn Marino be set to GZIP for decompression. If direct copying, then leftover input
87712f98b7SJohn Marino data from the input buffer will be copied to the output buffer. In that
88712f98b7SJohn Marino case, all further file reads will be directly to either the output buffer or
89712f98b7SJohn Marino a user buffer. If decompressing, the inflate state will be initialized.
90712f98b7SJohn Marino gz_look() will return 0 on success or -1 on failure. */
gz_look(state)91712f98b7SJohn Marino local int gz_look(state)
92fe927c51SPeter Avalos gz_statep state;
93fe927c51SPeter Avalos {
94fe927c51SPeter Avalos z_streamp strm = &(state->strm);
95fe927c51SPeter Avalos
96fe927c51SPeter Avalos /* allocate read buffers and inflate memory */
97fe927c51SPeter Avalos if (state->size == 0) {
98fe927c51SPeter Avalos /* allocate buffers */
9953ddf67cSJohn Marino state->in = (unsigned char *)malloc(state->want);
10053ddf67cSJohn Marino state->out = (unsigned char *)malloc(state->want << 1);
101fe927c51SPeter Avalos if (state->in == NULL || state->out == NULL) {
102fe927c51SPeter Avalos free(state->out);
103fe927c51SPeter Avalos free(state->in);
104fe927c51SPeter Avalos gz_error(state, Z_MEM_ERROR, "out of memory");
105fe927c51SPeter Avalos return -1;
106fe927c51SPeter Avalos }
107fe927c51SPeter Avalos state->size = state->want;
108fe927c51SPeter Avalos
109fe927c51SPeter Avalos /* allocate inflate memory */
110fe927c51SPeter Avalos state->strm.zalloc = Z_NULL;
111fe927c51SPeter Avalos state->strm.zfree = Z_NULL;
112fe927c51SPeter Avalos state->strm.opaque = Z_NULL;
113fe927c51SPeter Avalos state->strm.avail_in = 0;
114fe927c51SPeter Avalos state->strm.next_in = Z_NULL;
115712f98b7SJohn Marino if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
116fe927c51SPeter Avalos free(state->out);
117fe927c51SPeter Avalos free(state->in);
118fe927c51SPeter Avalos state->size = 0;
119fe927c51SPeter Avalos gz_error(state, Z_MEM_ERROR, "out of memory");
120fe927c51SPeter Avalos return -1;
121fe927c51SPeter Avalos }
122fe927c51SPeter Avalos }
123fe927c51SPeter Avalos
124712f98b7SJohn Marino /* get at least the magic bytes in the input buffer */
125712f98b7SJohn Marino if (strm->avail_in < 2) {
126fe927c51SPeter Avalos if (gz_avail(state) == -1)
127fe927c51SPeter Avalos return -1;
128fe927c51SPeter Avalos if (strm->avail_in == 0)
129fe927c51SPeter Avalos return 0;
130fe927c51SPeter Avalos }
131fe927c51SPeter Avalos
132712f98b7SJohn Marino /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
133712f98b7SJohn Marino a logical dilemma here when considering the case of a partially written
134712f98b7SJohn Marino gzip file, to wit, if a single 31 byte is written, then we cannot tell
135712f98b7SJohn Marino whether this is a single-byte file, or just a partially written gzip
136712f98b7SJohn Marino file -- for here we assume that if a gzip file is being written, then
137712f98b7SJohn Marino the header will be written in a single operation, so that reading a
138712f98b7SJohn Marino single byte is sufficient indication that it is not a gzip file) */
139712f98b7SJohn Marino if (strm->avail_in > 1 &&
140712f98b7SJohn Marino strm->next_in[0] == 31 && strm->next_in[1] == 139) {
141fe927c51SPeter Avalos inflateReset(strm);
142fe927c51SPeter Avalos state->how = GZIP;
143fe927c51SPeter Avalos state->direct = 0;
144fe927c51SPeter Avalos return 0;
145fe927c51SPeter Avalos }
146712f98b7SJohn Marino
147712f98b7SJohn Marino /* no gzip header -- if we were decoding gzip before, then this is trailing
148712f98b7SJohn Marino garbage. Ignore the trailing garbage and finish. */
149712f98b7SJohn Marino if (state->direct == 0) {
150712f98b7SJohn Marino strm->avail_in = 0;
151712f98b7SJohn Marino state->eof = 1;
152712f98b7SJohn Marino state->x.have = 0;
153712f98b7SJohn Marino return 0;
154fe927c51SPeter Avalos }
155fe927c51SPeter Avalos
156712f98b7SJohn Marino /* doing raw i/o, copy any leftover input to output -- this assumes that
157712f98b7SJohn Marino the output buffer is larger than the input buffer, which also assures
158712f98b7SJohn Marino space for gzungetc() */
159712f98b7SJohn Marino state->x.next = state->out;
160fe927c51SPeter Avalos if (strm->avail_in) {
161712f98b7SJohn Marino memcpy(state->x.next, strm->next_in, strm->avail_in);
162712f98b7SJohn Marino state->x.have = strm->avail_in;
163fe927c51SPeter Avalos strm->avail_in = 0;
164fe927c51SPeter Avalos }
165fe927c51SPeter Avalos state->how = COPY;
166fe927c51SPeter Avalos state->direct = 1;
167fe927c51SPeter Avalos return 0;
168fe927c51SPeter Avalos }
169fe927c51SPeter Avalos
170fe927c51SPeter Avalos /* Decompress from input to the provided next_out and avail_out in the state.
171712f98b7SJohn Marino On return, state->x.have and state->x.next point to the just decompressed
172712f98b7SJohn Marino data. If the gzip stream completes, state->how is reset to LOOK to look for
173712f98b7SJohn Marino the next gzip stream or raw data, once state->x.have is depleted. Returns 0
174712f98b7SJohn Marino on success, -1 on failure. */
gz_decomp(state)175fe927c51SPeter Avalos local int gz_decomp(state)
176fe927c51SPeter Avalos gz_statep state;
177fe927c51SPeter Avalos {
178712f98b7SJohn Marino int ret = Z_OK;
179fe927c51SPeter Avalos unsigned had;
180fe927c51SPeter Avalos z_streamp strm = &(state->strm);
181fe927c51SPeter Avalos
182fe927c51SPeter Avalos /* fill output buffer up to end of deflate stream */
183fe927c51SPeter Avalos had = strm->avail_out;
184fe927c51SPeter Avalos do {
185fe927c51SPeter Avalos /* get more input for inflate() */
186fe927c51SPeter Avalos if (strm->avail_in == 0 && gz_avail(state) == -1)
187fe927c51SPeter Avalos return -1;
188fe927c51SPeter Avalos if (strm->avail_in == 0) {
189712f98b7SJohn Marino gz_error(state, Z_BUF_ERROR, "unexpected end of file");
190712f98b7SJohn Marino break;
191fe927c51SPeter Avalos }
192fe927c51SPeter Avalos
193fe927c51SPeter Avalos /* decompress and handle errors */
194fe927c51SPeter Avalos ret = inflate(strm, Z_NO_FLUSH);
195fe927c51SPeter Avalos if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
196fe927c51SPeter Avalos gz_error(state, Z_STREAM_ERROR,
197fe927c51SPeter Avalos "internal error: inflate stream corrupt");
198fe927c51SPeter Avalos return -1;
199fe927c51SPeter Avalos }
200fe927c51SPeter Avalos if (ret == Z_MEM_ERROR) {
201fe927c51SPeter Avalos gz_error(state, Z_MEM_ERROR, "out of memory");
202fe927c51SPeter Avalos return -1;
203fe927c51SPeter Avalos }
204fe927c51SPeter Avalos if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
205fe927c51SPeter Avalos gz_error(state, Z_DATA_ERROR,
206fe927c51SPeter Avalos strm->msg == NULL ? "compressed data error" : strm->msg);
207fe927c51SPeter Avalos return -1;
208fe927c51SPeter Avalos }
209fe927c51SPeter Avalos } while (strm->avail_out && ret != Z_STREAM_END);
210fe927c51SPeter Avalos
211712f98b7SJohn Marino /* update available output */
212712f98b7SJohn Marino state->x.have = had - strm->avail_out;
213712f98b7SJohn Marino state->x.next = strm->next_out - state->x.have;
214fe927c51SPeter Avalos
215712f98b7SJohn Marino /* if the gzip stream completed successfully, look for another */
216712f98b7SJohn Marino if (ret == Z_STREAM_END)
217712f98b7SJohn Marino state->how = LOOK;
218fe927c51SPeter Avalos
219fe927c51SPeter Avalos /* good decompression */
220fe927c51SPeter Avalos return 0;
221fe927c51SPeter Avalos }
222fe927c51SPeter Avalos
223712f98b7SJohn Marino /* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
224fe927c51SPeter Avalos Data is either copied from the input file or decompressed from the input
225fe927c51SPeter Avalos file depending on state->how. If state->how is LOOK, then a gzip header is
226712f98b7SJohn Marino looked for to determine whether to copy or decompress. Returns -1 on error,
227712f98b7SJohn Marino otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
228712f98b7SJohn Marino end of the input file has been reached and all data has been processed. */
gz_fetch(state)229712f98b7SJohn Marino local int gz_fetch(state)
230fe927c51SPeter Avalos gz_statep state;
231fe927c51SPeter Avalos {
232fe927c51SPeter Avalos z_streamp strm = &(state->strm);
233fe927c51SPeter Avalos
234712f98b7SJohn Marino do {
235712f98b7SJohn Marino switch(state->how) {
236712f98b7SJohn Marino case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
237712f98b7SJohn Marino if (gz_look(state) == -1)
238fe927c51SPeter Avalos return -1;
239712f98b7SJohn Marino if (state->how == LOOK)
240fe927c51SPeter Avalos return 0;
241712f98b7SJohn Marino break;
242712f98b7SJohn Marino case COPY: /* -> COPY */
243712f98b7SJohn Marino if (gz_load(state, state->out, state->size << 1, &(state->x.have))
244712f98b7SJohn Marino == -1)
245fe927c51SPeter Avalos return -1;
246712f98b7SJohn Marino state->x.next = state->out;
247712f98b7SJohn Marino return 0;
248712f98b7SJohn Marino case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
249fe927c51SPeter Avalos strm->avail_out = state->size << 1;
250fe927c51SPeter Avalos strm->next_out = state->out;
251fe927c51SPeter Avalos if (gz_decomp(state) == -1)
252fe927c51SPeter Avalos return -1;
253fe927c51SPeter Avalos }
254712f98b7SJohn Marino } while (state->x.have == 0 && (!state->eof || strm->avail_in));
255fe927c51SPeter Avalos return 0;
256fe927c51SPeter Avalos }
257fe927c51SPeter Avalos
258fe927c51SPeter Avalos /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
gz_skip(state,len)259fe927c51SPeter Avalos local int gz_skip(state, len)
260fe927c51SPeter Avalos gz_statep state;
261fe927c51SPeter Avalos z_off64_t len;
262fe927c51SPeter Avalos {
263fe927c51SPeter Avalos unsigned n;
264fe927c51SPeter Avalos
265fe927c51SPeter Avalos /* skip over len bytes or reach end-of-file, whichever comes first */
266fe927c51SPeter Avalos while (len)
267fe927c51SPeter Avalos /* skip over whatever is in output buffer */
268712f98b7SJohn Marino if (state->x.have) {
269712f98b7SJohn Marino n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
270712f98b7SJohn Marino (unsigned)len : state->x.have;
271712f98b7SJohn Marino state->x.have -= n;
272712f98b7SJohn Marino state->x.next += n;
273712f98b7SJohn Marino state->x.pos += n;
274fe927c51SPeter Avalos len -= n;
275fe927c51SPeter Avalos }
276fe927c51SPeter Avalos
277fe927c51SPeter Avalos /* output buffer empty -- return if we're at the end of the input */
278fe927c51SPeter Avalos else if (state->eof && state->strm.avail_in == 0)
279fe927c51SPeter Avalos break;
280fe927c51SPeter Avalos
281fe927c51SPeter Avalos /* need more data to skip -- load up output buffer */
282fe927c51SPeter Avalos else {
283fe927c51SPeter Avalos /* get more output, looking for header if required */
284712f98b7SJohn Marino if (gz_fetch(state) == -1)
285fe927c51SPeter Avalos return -1;
286fe927c51SPeter Avalos }
287fe927c51SPeter Avalos return 0;
288fe927c51SPeter Avalos }
289fe927c51SPeter Avalos
290*e041647aSSascha Wildner /* Read len bytes into buf from file, or less than len up to the end of the
291*e041647aSSascha Wildner input. Return the number of bytes read. If zero is returned, either the
292*e041647aSSascha Wildner end of file was reached, or there was an error. state->err must be
293*e041647aSSascha Wildner consulted in that case to determine which. */
gz_read(state,buf,len)294*e041647aSSascha Wildner local z_size_t gz_read(state, buf, len)
295fe927c51SPeter Avalos gz_statep state;
296*e041647aSSascha Wildner voidp buf;
297*e041647aSSascha Wildner z_size_t len;
298*e041647aSSascha Wildner {
299*e041647aSSascha Wildner z_size_t got;
300*e041647aSSascha Wildner unsigned n;
301fe927c51SPeter Avalos
302fe927c51SPeter Avalos /* if len is zero, avoid unnecessary operations */
303fe927c51SPeter Avalos if (len == 0)
304fe927c51SPeter Avalos return 0;
305fe927c51SPeter Avalos
306fe927c51SPeter Avalos /* process a skip request */
307fe927c51SPeter Avalos if (state->seek) {
308fe927c51SPeter Avalos state->seek = 0;
309fe927c51SPeter Avalos if (gz_skip(state, state->skip) == -1)
310*e041647aSSascha Wildner return 0;
311fe927c51SPeter Avalos }
312fe927c51SPeter Avalos
313fe927c51SPeter Avalos /* get len bytes to buf, or less than len if at the end */
314fe927c51SPeter Avalos got = 0;
315fe927c51SPeter Avalos do {
316*e041647aSSascha Wildner /* set n to the maximum amount of len that fits in an unsigned int */
317*e041647aSSascha Wildner n = -1;
318*e041647aSSascha Wildner if (n > len)
319*e041647aSSascha Wildner n = len;
320*e041647aSSascha Wildner
321fe927c51SPeter Avalos /* first just try copying data from the output buffer */
322712f98b7SJohn Marino if (state->x.have) {
323*e041647aSSascha Wildner if (state->x.have < n)
324*e041647aSSascha Wildner n = state->x.have;
325712f98b7SJohn Marino memcpy(buf, state->x.next, n);
326712f98b7SJohn Marino state->x.next += n;
327712f98b7SJohn Marino state->x.have -= n;
328fe927c51SPeter Avalos }
329fe927c51SPeter Avalos
330fe927c51SPeter Avalos /* output buffer empty -- return if we're at the end of the input */
331*e041647aSSascha Wildner else if (state->eof && state->strm.avail_in == 0) {
332712f98b7SJohn Marino state->past = 1; /* tried to read past end */
333fe927c51SPeter Avalos break;
334712f98b7SJohn Marino }
335fe927c51SPeter Avalos
336fe927c51SPeter Avalos /* need output data -- for small len or new stream load up our output
337fe927c51SPeter Avalos buffer */
338*e041647aSSascha Wildner else if (state->how == LOOK || n < (state->size << 1)) {
339fe927c51SPeter Avalos /* get more output, looking for header if required */
340712f98b7SJohn Marino if (gz_fetch(state) == -1)
341*e041647aSSascha Wildner return 0;
342712f98b7SJohn Marino continue; /* no progress yet -- go back to copy above */
343fe927c51SPeter Avalos /* the copy above assures that we will leave with space in the
344fe927c51SPeter Avalos output buffer, allowing at least one gzungetc() to succeed */
345fe927c51SPeter Avalos }
346fe927c51SPeter Avalos
347fe927c51SPeter Avalos /* large len -- read directly into user buffer */
348fe927c51SPeter Avalos else if (state->how == COPY) { /* read directly */
349*e041647aSSascha Wildner if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
350*e041647aSSascha Wildner return 0;
351fe927c51SPeter Avalos }
352fe927c51SPeter Avalos
353fe927c51SPeter Avalos /* large len -- decompress directly into user buffer */
354fe927c51SPeter Avalos else { /* state->how == GZIP */
355*e041647aSSascha Wildner state->strm.avail_out = n;
356*e041647aSSascha Wildner state->strm.next_out = (unsigned char *)buf;
357fe927c51SPeter Avalos if (gz_decomp(state) == -1)
358*e041647aSSascha Wildner return 0;
359712f98b7SJohn Marino n = state->x.have;
360712f98b7SJohn Marino state->x.have = 0;
361fe927c51SPeter Avalos }
362fe927c51SPeter Avalos
363fe927c51SPeter Avalos /* update progress */
364fe927c51SPeter Avalos len -= n;
365fe927c51SPeter Avalos buf = (char *)buf + n;
366fe927c51SPeter Avalos got += n;
367712f98b7SJohn Marino state->x.pos += n;
368fe927c51SPeter Avalos } while (len);
369fe927c51SPeter Avalos
370*e041647aSSascha Wildner /* return number of bytes read into user buffer */
371*e041647aSSascha Wildner return got;
372*e041647aSSascha Wildner }
373*e041647aSSascha Wildner
374*e041647aSSascha Wildner /* -- see zlib.h -- */
gzread(file,buf,len)375*e041647aSSascha Wildner int ZEXPORT gzread(file, buf, len)
376*e041647aSSascha Wildner gzFile file;
377*e041647aSSascha Wildner voidp buf;
378*e041647aSSascha Wildner unsigned len;
379*e041647aSSascha Wildner {
380*e041647aSSascha Wildner gz_statep state;
381*e041647aSSascha Wildner
382*e041647aSSascha Wildner /* get internal structure */
383*e041647aSSascha Wildner if (file == NULL)
384*e041647aSSascha Wildner return -1;
385*e041647aSSascha Wildner state = (gz_statep)file;
386*e041647aSSascha Wildner
387*e041647aSSascha Wildner /* check that we're reading and that there's no (serious) error */
388*e041647aSSascha Wildner if (state->mode != GZ_READ ||
389*e041647aSSascha Wildner (state->err != Z_OK && state->err != Z_BUF_ERROR))
390*e041647aSSascha Wildner return -1;
391*e041647aSSascha Wildner
392*e041647aSSascha Wildner /* since an int is returned, make sure len fits in one, otherwise return
393*e041647aSSascha Wildner with an error (this avoids a flaw in the interface) */
394*e041647aSSascha Wildner if ((int)len < 0) {
395*e041647aSSascha Wildner gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
396*e041647aSSascha Wildner return -1;
397*e041647aSSascha Wildner }
398*e041647aSSascha Wildner
399*e041647aSSascha Wildner /* read len or fewer bytes to buf */
400*e041647aSSascha Wildner len = gz_read(state, buf, len);
401*e041647aSSascha Wildner
402*e041647aSSascha Wildner /* check for an error */
403*e041647aSSascha Wildner if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
404*e041647aSSascha Wildner return -1;
405*e041647aSSascha Wildner
406*e041647aSSascha Wildner /* return the number of bytes read (this is assured to fit in an int) */
407*e041647aSSascha Wildner return (int)len;
408*e041647aSSascha Wildner }
409*e041647aSSascha Wildner
410*e041647aSSascha Wildner /* -- see zlib.h -- */
gzfread(buf,size,nitems,file)411*e041647aSSascha Wildner z_size_t ZEXPORT gzfread(buf, size, nitems, file)
412*e041647aSSascha Wildner voidp buf;
413*e041647aSSascha Wildner z_size_t size;
414*e041647aSSascha Wildner z_size_t nitems;
415*e041647aSSascha Wildner gzFile file;
416*e041647aSSascha Wildner {
417*e041647aSSascha Wildner z_size_t len;
418*e041647aSSascha Wildner gz_statep state;
419*e041647aSSascha Wildner
420*e041647aSSascha Wildner /* get internal structure */
421*e041647aSSascha Wildner if (file == NULL)
422*e041647aSSascha Wildner return 0;
423*e041647aSSascha Wildner state = (gz_statep)file;
424*e041647aSSascha Wildner
425*e041647aSSascha Wildner /* check that we're reading and that there's no (serious) error */
426*e041647aSSascha Wildner if (state->mode != GZ_READ ||
427*e041647aSSascha Wildner (state->err != Z_OK && state->err != Z_BUF_ERROR))
428*e041647aSSascha Wildner return 0;
429*e041647aSSascha Wildner
430*e041647aSSascha Wildner /* compute bytes to read -- error on overflow */
431*e041647aSSascha Wildner len = nitems * size;
432*e041647aSSascha Wildner if (size && len / size != nitems) {
433*e041647aSSascha Wildner gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
434*e041647aSSascha Wildner return 0;
435*e041647aSSascha Wildner }
436*e041647aSSascha Wildner
437*e041647aSSascha Wildner /* read len or fewer bytes to buf, return the number of full items read */
438*e041647aSSascha Wildner return len ? gz_read(state, buf, len) / size : 0;
439fe927c51SPeter Avalos }
440fe927c51SPeter Avalos
441fe927c51SPeter Avalos /* -- see zlib.h -- */
44253ddf67cSJohn Marino #ifdef Z_PREFIX_SET
44353ddf67cSJohn Marino # undef z_gzgetc
44453ddf67cSJohn Marino #else
445712f98b7SJohn Marino # undef gzgetc
44653ddf67cSJohn Marino #endif
gzgetc(file)447fe927c51SPeter Avalos int ZEXPORT gzgetc(file)
448fe927c51SPeter Avalos gzFile file;
449fe927c51SPeter Avalos {
450fe927c51SPeter Avalos int ret;
451fe927c51SPeter Avalos unsigned char buf[1];
452fe927c51SPeter Avalos gz_statep state;
453fe927c51SPeter Avalos
454fe927c51SPeter Avalos /* get internal structure */
455fe927c51SPeter Avalos if (file == NULL)
456fe927c51SPeter Avalos return -1;
457fe927c51SPeter Avalos state = (gz_statep)file;
458fe927c51SPeter Avalos
459712f98b7SJohn Marino /* check that we're reading and that there's no (serious) error */
460712f98b7SJohn Marino if (state->mode != GZ_READ ||
461712f98b7SJohn Marino (state->err != Z_OK && state->err != Z_BUF_ERROR))
462fe927c51SPeter Avalos return -1;
463fe927c51SPeter Avalos
464fe927c51SPeter Avalos /* try output buffer (no need to check for skip request) */
465712f98b7SJohn Marino if (state->x.have) {
466712f98b7SJohn Marino state->x.have--;
467712f98b7SJohn Marino state->x.pos++;
468712f98b7SJohn Marino return *(state->x.next)++;
469fe927c51SPeter Avalos }
470fe927c51SPeter Avalos
471*e041647aSSascha Wildner /* nothing there -- try gz_read() */
472*e041647aSSascha Wildner ret = gz_read(state, buf, 1);
473fe927c51SPeter Avalos return ret < 1 ? -1 : buf[0];
474fe927c51SPeter Avalos }
475fe927c51SPeter Avalos
gzgetc_(file)476712f98b7SJohn Marino int ZEXPORT gzgetc_(file)
477712f98b7SJohn Marino gzFile file;
478712f98b7SJohn Marino {
479712f98b7SJohn Marino return gzgetc(file);
480712f98b7SJohn Marino }
481712f98b7SJohn Marino
482fe927c51SPeter Avalos /* -- see zlib.h -- */
gzungetc(c,file)483fe927c51SPeter Avalos int ZEXPORT gzungetc(c, file)
484fe927c51SPeter Avalos int c;
485fe927c51SPeter Avalos gzFile file;
486fe927c51SPeter Avalos {
487fe927c51SPeter Avalos gz_statep state;
488fe927c51SPeter Avalos
489fe927c51SPeter Avalos /* get internal structure */
490fe927c51SPeter Avalos if (file == NULL)
491fe927c51SPeter Avalos return -1;
492fe927c51SPeter Avalos state = (gz_statep)file;
493fe927c51SPeter Avalos
494712f98b7SJohn Marino /* check that we're reading and that there's no (serious) error */
495712f98b7SJohn Marino if (state->mode != GZ_READ ||
496712f98b7SJohn Marino (state->err != Z_OK && state->err != Z_BUF_ERROR))
497fe927c51SPeter Avalos return -1;
498fe927c51SPeter Avalos
499fe927c51SPeter Avalos /* process a skip request */
500fe927c51SPeter Avalos if (state->seek) {
501fe927c51SPeter Avalos state->seek = 0;
502fe927c51SPeter Avalos if (gz_skip(state, state->skip) == -1)
503fe927c51SPeter Avalos return -1;
504fe927c51SPeter Avalos }
505fe927c51SPeter Avalos
506fe927c51SPeter Avalos /* can't push EOF */
507fe927c51SPeter Avalos if (c < 0)
508fe927c51SPeter Avalos return -1;
509fe927c51SPeter Avalos
510fe927c51SPeter Avalos /* if output buffer empty, put byte at end (allows more pushing) */
511712f98b7SJohn Marino if (state->x.have == 0) {
512712f98b7SJohn Marino state->x.have = 1;
513712f98b7SJohn Marino state->x.next = state->out + (state->size << 1) - 1;
514*e041647aSSascha Wildner state->x.next[0] = (unsigned char)c;
515712f98b7SJohn Marino state->x.pos--;
516712f98b7SJohn Marino state->past = 0;
517fe927c51SPeter Avalos return c;
518fe927c51SPeter Avalos }
519fe927c51SPeter Avalos
520fe927c51SPeter Avalos /* if no room, give up (must have already done a gzungetc()) */
521712f98b7SJohn Marino if (state->x.have == (state->size << 1)) {
522712f98b7SJohn Marino gz_error(state, Z_DATA_ERROR, "out of room to push characters");
523fe927c51SPeter Avalos return -1;
524fe927c51SPeter Avalos }
525fe927c51SPeter Avalos
526fe927c51SPeter Avalos /* slide output data if needed and insert byte before existing data */
527712f98b7SJohn Marino if (state->x.next == state->out) {
528712f98b7SJohn Marino unsigned char *src = state->out + state->x.have;
529fe927c51SPeter Avalos unsigned char *dest = state->out + (state->size << 1);
530fe927c51SPeter Avalos while (src > state->out)
531fe927c51SPeter Avalos *--dest = *--src;
532712f98b7SJohn Marino state->x.next = dest;
533fe927c51SPeter Avalos }
534712f98b7SJohn Marino state->x.have++;
535712f98b7SJohn Marino state->x.next--;
536*e041647aSSascha Wildner state->x.next[0] = (unsigned char)c;
537712f98b7SJohn Marino state->x.pos--;
538712f98b7SJohn Marino state->past = 0;
539fe927c51SPeter Avalos return c;
540fe927c51SPeter Avalos }
541fe927c51SPeter Avalos
542fe927c51SPeter Avalos /* -- see zlib.h -- */
gzgets(file,buf,len)543fe927c51SPeter Avalos char * ZEXPORT gzgets(file, buf, len)
544fe927c51SPeter Avalos gzFile file;
545fe927c51SPeter Avalos char *buf;
546fe927c51SPeter Avalos int len;
547fe927c51SPeter Avalos {
548fe927c51SPeter Avalos unsigned left, n;
549fe927c51SPeter Avalos char *str;
550fe927c51SPeter Avalos unsigned char *eol;
551fe927c51SPeter Avalos gz_statep state;
552fe927c51SPeter Avalos
553fe927c51SPeter Avalos /* check parameters and get internal structure */
554fe927c51SPeter Avalos if (file == NULL || buf == NULL || len < 1)
555fe927c51SPeter Avalos return NULL;
556fe927c51SPeter Avalos state = (gz_statep)file;
557fe927c51SPeter Avalos
558712f98b7SJohn Marino /* check that we're reading and that there's no (serious) error */
559712f98b7SJohn Marino if (state->mode != GZ_READ ||
560712f98b7SJohn Marino (state->err != Z_OK && state->err != Z_BUF_ERROR))
561fe927c51SPeter Avalos return NULL;
562fe927c51SPeter Avalos
563fe927c51SPeter Avalos /* process a skip request */
564fe927c51SPeter Avalos if (state->seek) {
565fe927c51SPeter Avalos state->seek = 0;
566fe927c51SPeter Avalos if (gz_skip(state, state->skip) == -1)
567fe927c51SPeter Avalos return NULL;
568fe927c51SPeter Avalos }
569fe927c51SPeter Avalos
570fe927c51SPeter Avalos /* copy output bytes up to new line or len - 1, whichever comes first --
571fe927c51SPeter Avalos append a terminating zero to the string (we don't check for a zero in
572fe927c51SPeter Avalos the contents, let the user worry about that) */
573fe927c51SPeter Avalos str = buf;
574fe927c51SPeter Avalos left = (unsigned)len - 1;
575fe927c51SPeter Avalos if (left) do {
576fe927c51SPeter Avalos /* assure that something is in the output buffer */
577712f98b7SJohn Marino if (state->x.have == 0 && gz_fetch(state) == -1)
578fe927c51SPeter Avalos return NULL; /* error */
579712f98b7SJohn Marino if (state->x.have == 0) { /* end of file */
580712f98b7SJohn Marino state->past = 1; /* read past end */
581712f98b7SJohn Marino break; /* return what we have */
582fe927c51SPeter Avalos }
583fe927c51SPeter Avalos
584fe927c51SPeter Avalos /* look for end-of-line in current output buffer */
585712f98b7SJohn Marino n = state->x.have > left ? left : state->x.have;
58653ddf67cSJohn Marino eol = (unsigned char *)memchr(state->x.next, '\n', n);
587fe927c51SPeter Avalos if (eol != NULL)
588712f98b7SJohn Marino n = (unsigned)(eol - state->x.next) + 1;
589fe927c51SPeter Avalos
590fe927c51SPeter Avalos /* copy through end-of-line, or remainder if not found */
591712f98b7SJohn Marino memcpy(buf, state->x.next, n);
592712f98b7SJohn Marino state->x.have -= n;
593712f98b7SJohn Marino state->x.next += n;
594712f98b7SJohn Marino state->x.pos += n;
595fe927c51SPeter Avalos left -= n;
596fe927c51SPeter Avalos buf += n;
597fe927c51SPeter Avalos } while (left && eol == NULL);
598fe927c51SPeter Avalos
599712f98b7SJohn Marino /* return terminated string, or if nothing, end of file */
600712f98b7SJohn Marino if (buf == str)
601712f98b7SJohn Marino return NULL;
602fe927c51SPeter Avalos buf[0] = 0;
603fe927c51SPeter Avalos return str;
604fe927c51SPeter Avalos }
605fe927c51SPeter Avalos
606fe927c51SPeter Avalos /* -- see zlib.h -- */
gzdirect(file)607fe927c51SPeter Avalos int ZEXPORT gzdirect(file)
608fe927c51SPeter Avalos gzFile file;
609fe927c51SPeter Avalos {
610fe927c51SPeter Avalos gz_statep state;
611fe927c51SPeter Avalos
612fe927c51SPeter Avalos /* get internal structure */
613fe927c51SPeter Avalos if (file == NULL)
614fe927c51SPeter Avalos return 0;
615fe927c51SPeter Avalos state = (gz_statep)file;
616fe927c51SPeter Avalos
617fe927c51SPeter Avalos /* if the state is not known, but we can find out, then do so (this is
618fe927c51SPeter Avalos mainly for right after a gzopen() or gzdopen()) */
619712f98b7SJohn Marino if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
620712f98b7SJohn Marino (void)gz_look(state);
621fe927c51SPeter Avalos
622712f98b7SJohn Marino /* return 1 if transparent, 0 if processing a gzip stream */
623fe927c51SPeter Avalos return state->direct;
624fe927c51SPeter Avalos }
625fe927c51SPeter Avalos
626fe927c51SPeter Avalos /* -- see zlib.h -- */
gzclose_r(file)627fe927c51SPeter Avalos int ZEXPORT gzclose_r(file)
628fe927c51SPeter Avalos gzFile file;
629fe927c51SPeter Avalos {
630712f98b7SJohn Marino int ret, err;
631fe927c51SPeter Avalos gz_statep state;
632fe927c51SPeter Avalos
633fe927c51SPeter Avalos /* get internal structure */
634fe927c51SPeter Avalos if (file == NULL)
635fe927c51SPeter Avalos return Z_STREAM_ERROR;
636fe927c51SPeter Avalos state = (gz_statep)file;
637fe927c51SPeter Avalos
638fe927c51SPeter Avalos /* check that we're reading */
639fe927c51SPeter Avalos if (state->mode != GZ_READ)
640fe927c51SPeter Avalos return Z_STREAM_ERROR;
641fe927c51SPeter Avalos
642fe927c51SPeter Avalos /* free memory and close file */
643fe927c51SPeter Avalos if (state->size) {
644fe927c51SPeter Avalos inflateEnd(&(state->strm));
645fe927c51SPeter Avalos free(state->out);
646fe927c51SPeter Avalos free(state->in);
647fe927c51SPeter Avalos }
648712f98b7SJohn Marino err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
649fe927c51SPeter Avalos gz_error(state, Z_OK, NULL);
650fe927c51SPeter Avalos free(state->path);
651fe927c51SPeter Avalos ret = close(state->fd);
652fe927c51SPeter Avalos free(state);
653712f98b7SJohn Marino return ret ? Z_ERRNO : err;
654fe927c51SPeter Avalos }
655