1c9083b85SXin LI /* gzread.c -- zlib functions for reading gzip files
2cd882207SXin LI * Copyright (C) 2004-2017 Mark Adler
3c9083b85SXin LI * For conditions of distribution and use, see copyright notice in zlib.h
4c9083b85SXin LI */
5c9083b85SXin LI
6c9083b85SXin LI #include "gzguts.h"
7c9083b85SXin LI #include <unistd.h>
8c9083b85SXin LI
9c9083b85SXin LI /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
10c9083b85SXin LI state->fd, and update state->eof, state->err, and state->msg as appropriate.
11c9083b85SXin LI This function needs to loop on read(), since read() is not guaranteed to
12c9083b85SXin LI read the number of bytes requested, depending on the type of descriptor. */
gz_load(gz_statep state,unsigned char * buf,unsigned len,unsigned * have)13*4717628eSXin LI local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
14*4717628eSXin LI unsigned *have) {
15c9083b85SXin LI int ret;
16c9083b85SXin LI unsigned get, max = ((unsigned)-1 >> 2) + 1;
17c9083b85SXin LI
18c9083b85SXin LI *have = 0;
19c9083b85SXin LI do {
20c9083b85SXin LI get = len - *have;
21c9083b85SXin LI if (get > max)
22c9083b85SXin LI get = max;
23c9083b85SXin LI ret = read(state->fd, buf + *have, get);
24c9083b85SXin LI if (ret <= 0)
25c9083b85SXin LI break;
26c9083b85SXin LI *have += (unsigned)ret;
27c9083b85SXin LI } while (*have < len);
28c9083b85SXin LI if (ret < 0) {
29c9083b85SXin LI gz_error(state, Z_ERRNO, zstrerror());
30c9083b85SXin LI return -1;
31c9083b85SXin LI }
32c9083b85SXin LI if (ret == 0)
33c9083b85SXin LI state->eof = 1;
34c9083b85SXin LI return 0;
35c9083b85SXin LI }
36c9083b85SXin LI
37c9083b85SXin LI /* Load up input buffer and set eof flag if last data loaded -- return -1 on
38c9083b85SXin LI error, 0 otherwise. Note that the eof flag is set when the end of the input
39c9083b85SXin LI file is reached, even though there may be unused data in the buffer. Once
40c9083b85SXin LI that data has been used, no more attempts will be made to read the file.
41c9083b85SXin LI If strm->avail_in != 0, then the current data is moved to the beginning of
42c9083b85SXin LI the input buffer, and then the remainder of the buffer is loaded with the
43c9083b85SXin LI available data from the input file. */
gz_avail(gz_statep state)44*4717628eSXin LI local int gz_avail(gz_statep state) {
45c9083b85SXin LI unsigned got;
46c9083b85SXin LI z_streamp strm = &(state->strm);
47c9083b85SXin LI
48c9083b85SXin LI if (state->err != Z_OK && state->err != Z_BUF_ERROR)
49c9083b85SXin LI return -1;
50c9083b85SXin LI if (state->eof == 0) {
51c9083b85SXin LI if (strm->avail_in) { /* copy what's there to the start */
52c9083b85SXin LI unsigned char *p = state->in;
53c9083b85SXin LI unsigned const char *q = strm->next_in;
54c9083b85SXin LI unsigned n = strm->avail_in;
55c9083b85SXin LI do {
56c9083b85SXin LI *p++ = *q++;
57c9083b85SXin LI } while (--n);
58c9083b85SXin LI }
59c9083b85SXin LI if (gz_load(state, state->in + strm->avail_in,
60c9083b85SXin LI state->size - strm->avail_in, &got) == -1)
61c9083b85SXin LI return -1;
62c9083b85SXin LI strm->avail_in += got;
63c9083b85SXin LI strm->next_in = state->in;
64c9083b85SXin LI }
65c9083b85SXin LI return 0;
66c9083b85SXin LI }
67c9083b85SXin LI
68c9083b85SXin LI /* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
69c9083b85SXin LI If this is the first time in, allocate required memory. state->how will be
70c9083b85SXin LI left unchanged if there is no more input data available, will be set to COPY
71c9083b85SXin LI if there is no gzip header and direct copying will be performed, or it will
72c9083b85SXin LI be set to GZIP for decompression. If direct copying, then leftover input
73c9083b85SXin LI data from the input buffer will be copied to the output buffer. In that
74c9083b85SXin LI case, all further file reads will be directly to either the output buffer or
75c9083b85SXin LI a user buffer. If decompressing, the inflate state will be initialized.
76c9083b85SXin LI gz_look() will return 0 on success or -1 on failure. */
gz_look(gz_statep state)77*4717628eSXin LI local int gz_look(gz_statep state) {
78c9083b85SXin LI z_streamp strm = &(state->strm);
79c9083b85SXin LI
80c9083b85SXin LI /* allocate read buffers and inflate memory */
81c9083b85SXin LI if (state->size == 0) {
82c9083b85SXin LI /* allocate buffers */
83c9083b85SXin LI state->in = (unsigned char *)malloc(state->want);
84c9083b85SXin LI state->out = (unsigned char *)malloc(state->want << 1);
85c9083b85SXin LI if (state->in == NULL || state->out == NULL) {
86c9083b85SXin LI free(state->out);
87c9083b85SXin LI free(state->in);
88c9083b85SXin LI gz_error(state, Z_MEM_ERROR, "out of memory");
89c9083b85SXin LI return -1;
90c9083b85SXin LI }
91c9083b85SXin LI state->size = state->want;
92c9083b85SXin LI
93c9083b85SXin LI /* allocate inflate memory */
94c9083b85SXin LI state->strm.zalloc = Z_NULL;
95c9083b85SXin LI state->strm.zfree = Z_NULL;
96c9083b85SXin LI state->strm.opaque = Z_NULL;
97c9083b85SXin LI state->strm.avail_in = 0;
98c9083b85SXin LI state->strm.next_in = Z_NULL;
99c9083b85SXin LI if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
100c9083b85SXin LI free(state->out);
101c9083b85SXin LI free(state->in);
102c9083b85SXin LI state->size = 0;
103c9083b85SXin LI gz_error(state, Z_MEM_ERROR, "out of memory");
104c9083b85SXin LI return -1;
105c9083b85SXin LI }
106c9083b85SXin LI }
107c9083b85SXin LI
108c9083b85SXin LI /* get at least the magic bytes in the input buffer */
109c9083b85SXin LI if (strm->avail_in < 2) {
110c9083b85SXin LI if (gz_avail(state) == -1)
111c9083b85SXin LI return -1;
112c9083b85SXin LI if (strm->avail_in == 0)
113c9083b85SXin LI return 0;
114c9083b85SXin LI }
115c9083b85SXin LI
116c9083b85SXin LI /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
117c9083b85SXin LI a logical dilemma here when considering the case of a partially written
118c9083b85SXin LI gzip file, to wit, if a single 31 byte is written, then we cannot tell
119c9083b85SXin LI whether this is a single-byte file, or just a partially written gzip
120c9083b85SXin LI file -- for here we assume that if a gzip file is being written, then
121c9083b85SXin LI the header will be written in a single operation, so that reading a
122c9083b85SXin LI single byte is sufficient indication that it is not a gzip file) */
123c9083b85SXin LI if (strm->avail_in > 1 &&
124c9083b85SXin LI strm->next_in[0] == 31 && strm->next_in[1] == 139) {
125c9083b85SXin LI inflateReset(strm);
126c9083b85SXin LI state->how = GZIP;
127c9083b85SXin LI state->direct = 0;
128c9083b85SXin LI return 0;
129c9083b85SXin LI }
130c9083b85SXin LI
131c9083b85SXin LI /* no gzip header -- if we were decoding gzip before, then this is trailing
132c9083b85SXin LI garbage. Ignore the trailing garbage and finish. */
133c9083b85SXin LI if (state->direct == 0) {
134c9083b85SXin LI strm->avail_in = 0;
135c9083b85SXin LI state->eof = 1;
136c9083b85SXin LI state->x.have = 0;
137c9083b85SXin LI return 0;
138c9083b85SXin LI }
139c9083b85SXin LI
140c9083b85SXin LI /* doing raw i/o, copy any leftover input to output -- this assumes that
141c9083b85SXin LI the output buffer is larger than the input buffer, which also assures
142c9083b85SXin LI space for gzungetc() */
143c9083b85SXin LI state->x.next = state->out;
144c9083b85SXin LI memcpy(state->x.next, strm->next_in, strm->avail_in);
145c9083b85SXin LI state->x.have = strm->avail_in;
146c9083b85SXin LI strm->avail_in = 0;
147c9083b85SXin LI state->how = COPY;
148c9083b85SXin LI state->direct = 1;
149c9083b85SXin LI return 0;
150c9083b85SXin LI }
151c9083b85SXin LI
152c9083b85SXin LI /* Decompress from input to the provided next_out and avail_out in the state.
153c9083b85SXin LI On return, state->x.have and state->x.next point to the just decompressed
154c9083b85SXin LI data. If the gzip stream completes, state->how is reset to LOOK to look for
155c9083b85SXin LI the next gzip stream or raw data, once state->x.have is depleted. Returns 0
156c9083b85SXin LI on success, -1 on failure. */
gz_decomp(gz_statep state)157*4717628eSXin LI local int gz_decomp(gz_statep state) {
158c9083b85SXin LI int ret = Z_OK;
159c9083b85SXin LI unsigned had;
160c9083b85SXin LI z_streamp strm = &(state->strm);
161c9083b85SXin LI
162c9083b85SXin LI /* fill output buffer up to end of deflate stream */
163c9083b85SXin LI had = strm->avail_out;
164c9083b85SXin LI do {
165c9083b85SXin LI /* get more input for inflate() */
166c9083b85SXin LI if (strm->avail_in == 0 && gz_avail(state) == -1)
167c9083b85SXin LI return -1;
168c9083b85SXin LI if (strm->avail_in == 0) {
169c9083b85SXin LI gz_error(state, Z_BUF_ERROR, "unexpected end of file");
170c9083b85SXin LI break;
171c9083b85SXin LI }
172c9083b85SXin LI
173c9083b85SXin LI /* decompress and handle errors */
174c9083b85SXin LI ret = inflate(strm, Z_NO_FLUSH);
175c9083b85SXin LI if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
176c9083b85SXin LI gz_error(state, Z_STREAM_ERROR,
177c9083b85SXin LI "internal error: inflate stream corrupt");
178c9083b85SXin LI return -1;
179c9083b85SXin LI }
180c9083b85SXin LI if (ret == Z_MEM_ERROR) {
181c9083b85SXin LI gz_error(state, Z_MEM_ERROR, "out of memory");
182c9083b85SXin LI return -1;
183c9083b85SXin LI }
184c9083b85SXin LI if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
185c9083b85SXin LI gz_error(state, Z_DATA_ERROR,
186c9083b85SXin LI strm->msg == NULL ? "compressed data error" : strm->msg);
187c9083b85SXin LI return -1;
188c9083b85SXin LI }
189c9083b85SXin LI } while (strm->avail_out && ret != Z_STREAM_END);
190c9083b85SXin LI
191c9083b85SXin LI /* update available output */
192c9083b85SXin LI state->x.have = had - strm->avail_out;
193c9083b85SXin LI state->x.next = strm->next_out - state->x.have;
194c9083b85SXin LI
195c9083b85SXin LI /* if the gzip stream completed successfully, look for another */
196c9083b85SXin LI if (ret == Z_STREAM_END)
197c9083b85SXin LI state->how = LOOK;
198c9083b85SXin LI
199c9083b85SXin LI /* good decompression */
200c9083b85SXin LI return 0;
201c9083b85SXin LI }
202c9083b85SXin LI
203c9083b85SXin LI /* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
204c9083b85SXin LI Data is either copied from the input file or decompressed from the input
205c9083b85SXin LI file depending on state->how. If state->how is LOOK, then a gzip header is
206c9083b85SXin LI looked for to determine whether to copy or decompress. Returns -1 on error,
207c9083b85SXin LI otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
208c9083b85SXin LI end of the input file has been reached and all data has been processed. */
gz_fetch(gz_statep state)209*4717628eSXin LI local int gz_fetch(gz_statep state) {
210c9083b85SXin LI z_streamp strm = &(state->strm);
211c9083b85SXin LI
212c9083b85SXin LI do {
213c9083b85SXin LI switch(state->how) {
214c9083b85SXin LI case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
215c9083b85SXin LI if (gz_look(state) == -1)
216c9083b85SXin LI return -1;
217c9083b85SXin LI if (state->how == LOOK)
218c9083b85SXin LI return 0;
219c9083b85SXin LI break;
220c9083b85SXin LI case COPY: /* -> COPY */
221c9083b85SXin LI if (gz_load(state, state->out, state->size << 1, &(state->x.have))
222c9083b85SXin LI == -1)
223c9083b85SXin LI return -1;
224c9083b85SXin LI state->x.next = state->out;
225c9083b85SXin LI return 0;
226c9083b85SXin LI case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
227c9083b85SXin LI strm->avail_out = state->size << 1;
228c9083b85SXin LI strm->next_out = state->out;
229c9083b85SXin LI if (gz_decomp(state) == -1)
230c9083b85SXin LI return -1;
231c9083b85SXin LI }
232c9083b85SXin LI } while (state->x.have == 0 && (!state->eof || strm->avail_in));
233c9083b85SXin LI return 0;
234c9083b85SXin LI }
235c9083b85SXin LI
236c9083b85SXin LI /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
gz_skip(gz_statep state,z_off64_t len)237*4717628eSXin LI local int gz_skip(gz_statep state, z_off64_t len) {
238c9083b85SXin LI unsigned n;
239c9083b85SXin LI
240c9083b85SXin LI /* skip over len bytes or reach end-of-file, whichever comes first */
241c9083b85SXin LI while (len)
242c9083b85SXin LI /* skip over whatever is in output buffer */
243c9083b85SXin LI if (state->x.have) {
244c9083b85SXin LI n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
245c9083b85SXin LI (unsigned)len : state->x.have;
246c9083b85SXin LI state->x.have -= n;
247c9083b85SXin LI state->x.next += n;
248c9083b85SXin LI state->x.pos += n;
249c9083b85SXin LI len -= n;
250c9083b85SXin LI }
251c9083b85SXin LI
252c9083b85SXin LI /* output buffer empty -- return if we're at the end of the input */
253c9083b85SXin LI else if (state->eof && state->strm.avail_in == 0)
254c9083b85SXin LI break;
255c9083b85SXin LI
256c9083b85SXin LI /* need more data to skip -- load up output buffer */
257c9083b85SXin LI else {
258c9083b85SXin LI /* get more output, looking for header if required */
259c9083b85SXin LI if (gz_fetch(state) == -1)
260c9083b85SXin LI return -1;
261c9083b85SXin LI }
262c9083b85SXin LI return 0;
263c9083b85SXin LI }
264c9083b85SXin LI
265c9083b85SXin LI /* Read len bytes into buf from file, or less than len up to the end of the
266c9083b85SXin LI input. Return the number of bytes read. If zero is returned, either the
267c9083b85SXin LI end of file was reached, or there was an error. state->err must be
268c9083b85SXin LI consulted in that case to determine which. */
gz_read(gz_statep state,voidp buf,z_size_t len)269*4717628eSXin LI local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
270c9083b85SXin LI z_size_t got;
271c9083b85SXin LI unsigned n;
272c9083b85SXin LI
273c9083b85SXin LI /* if len is zero, avoid unnecessary operations */
274c9083b85SXin LI if (len == 0)
275c9083b85SXin LI return 0;
276c9083b85SXin LI
277c9083b85SXin LI /* process a skip request */
278c9083b85SXin LI if (state->seek) {
279c9083b85SXin LI state->seek = 0;
280c9083b85SXin LI if (gz_skip(state, state->skip) == -1)
281c9083b85SXin LI return 0;
282c9083b85SXin LI }
283c9083b85SXin LI
284c9083b85SXin LI /* get len bytes to buf, or less than len if at the end */
285c9083b85SXin LI got = 0;
286c9083b85SXin LI do {
287c9083b85SXin LI /* set n to the maximum amount of len that fits in an unsigned int */
288cd882207SXin LI n = (unsigned)-1;
289c9083b85SXin LI if (n > len)
290cd882207SXin LI n = (unsigned)len;
291c9083b85SXin LI
292c9083b85SXin LI /* first just try copying data from the output buffer */
293c9083b85SXin LI if (state->x.have) {
294c9083b85SXin LI if (state->x.have < n)
295c9083b85SXin LI n = state->x.have;
296c9083b85SXin LI memcpy(buf, state->x.next, n);
297c9083b85SXin LI state->x.next += n;
298c9083b85SXin LI state->x.have -= n;
299c9083b85SXin LI }
300c9083b85SXin LI
301c9083b85SXin LI /* output buffer empty -- return if we're at the end of the input */
302c9083b85SXin LI else if (state->eof && state->strm.avail_in == 0) {
303c9083b85SXin LI state->past = 1; /* tried to read past end */
304c9083b85SXin LI break;
305c9083b85SXin LI }
306c9083b85SXin LI
307c9083b85SXin LI /* need output data -- for small len or new stream load up our output
308c9083b85SXin LI buffer */
309c9083b85SXin LI else if (state->how == LOOK || n < (state->size << 1)) {
310c9083b85SXin LI /* get more output, looking for header if required */
311c9083b85SXin LI if (gz_fetch(state) == -1)
312c9083b85SXin LI return 0;
313c9083b85SXin LI continue; /* no progress yet -- go back to copy above */
314c9083b85SXin LI /* the copy above assures that we will leave with space in the
315c9083b85SXin LI output buffer, allowing at least one gzungetc() to succeed */
316c9083b85SXin LI }
317c9083b85SXin LI
318c9083b85SXin LI /* large len -- read directly into user buffer */
319c9083b85SXin LI else if (state->how == COPY) { /* read directly */
320c9083b85SXin LI if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
321c9083b85SXin LI return 0;
322c9083b85SXin LI }
323c9083b85SXin LI
324c9083b85SXin LI /* large len -- decompress directly into user buffer */
325c9083b85SXin LI else { /* state->how == GZIP */
326c9083b85SXin LI state->strm.avail_out = n;
327c9083b85SXin LI state->strm.next_out = (unsigned char *)buf;
328c9083b85SXin LI if (gz_decomp(state) == -1)
329c9083b85SXin LI return 0;
330c9083b85SXin LI n = state->x.have;
331c9083b85SXin LI state->x.have = 0;
332c9083b85SXin LI }
333c9083b85SXin LI
334c9083b85SXin LI /* update progress */
335c9083b85SXin LI len -= n;
336c9083b85SXin LI buf = (char *)buf + n;
337c9083b85SXin LI got += n;
338c9083b85SXin LI state->x.pos += n;
339c9083b85SXin LI } while (len);
340c9083b85SXin LI
341c9083b85SXin LI /* return number of bytes read into user buffer */
342c9083b85SXin LI return got;
343c9083b85SXin LI }
344c9083b85SXin LI
345c9083b85SXin LI /* -- see zlib.h -- */
gzread(gzFile file,voidp buf,unsigned len)346*4717628eSXin LI int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
347c9083b85SXin LI gz_statep state;
348c9083b85SXin LI
349c9083b85SXin LI /* get internal structure */
350c9083b85SXin LI if (file == NULL)
351c9083b85SXin LI return -1;
352c9083b85SXin LI state = (gz_statep)file;
353c9083b85SXin LI
354c9083b85SXin LI /* check that we're reading and that there's no (serious) error */
355c9083b85SXin LI if (state->mode != GZ_READ ||
356c9083b85SXin LI (state->err != Z_OK && state->err != Z_BUF_ERROR))
357c9083b85SXin LI return -1;
358c9083b85SXin LI
359c9083b85SXin LI /* since an int is returned, make sure len fits in one, otherwise return
360c9083b85SXin LI with an error (this avoids a flaw in the interface) */
361c9083b85SXin LI if ((int)len < 0) {
362c9083b85SXin LI gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
363c9083b85SXin LI return -1;
364c9083b85SXin LI }
365c9083b85SXin LI
366c9083b85SXin LI /* read len or fewer bytes to buf */
367cd882207SXin LI len = (unsigned)gz_read(state, buf, len);
368c9083b85SXin LI
369c9083b85SXin LI /* check for an error */
370c9083b85SXin LI if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
371c9083b85SXin LI return -1;
372c9083b85SXin LI
373c9083b85SXin LI /* return the number of bytes read (this is assured to fit in an int) */
374c9083b85SXin LI return (int)len;
375c9083b85SXin LI }
376c9083b85SXin LI
377c9083b85SXin LI /* -- see zlib.h -- */
gzfread(voidp buf,z_size_t size,z_size_t nitems,gzFile file)378*4717628eSXin LI z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
379c9083b85SXin LI z_size_t len;
380c9083b85SXin LI gz_statep state;
381c9083b85SXin LI
382c9083b85SXin LI /* get internal structure */
383c9083b85SXin LI if (file == NULL)
384c9083b85SXin LI return 0;
385c9083b85SXin LI state = (gz_statep)file;
386c9083b85SXin LI
387c9083b85SXin LI /* check that we're reading and that there's no (serious) error */
388c9083b85SXin LI if (state->mode != GZ_READ ||
389c9083b85SXin LI (state->err != Z_OK && state->err != Z_BUF_ERROR))
390c9083b85SXin LI return 0;
391c9083b85SXin LI
392c9083b85SXin LI /* compute bytes to read -- error on overflow */
393c9083b85SXin LI len = nitems * size;
394c9083b85SXin LI if (size && len / size != nitems) {
395c9083b85SXin LI gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
396c9083b85SXin LI return 0;
397c9083b85SXin LI }
398c9083b85SXin LI
399c9083b85SXin LI /* read len or fewer bytes to buf, return the number of full items read */
400c9083b85SXin LI return len ? gz_read(state, buf, len) / size : 0;
401c9083b85SXin LI }
402c9083b85SXin LI
403c9083b85SXin LI /* -- see zlib.h -- */
404c9083b85SXin LI #ifdef Z_PREFIX_SET
405c9083b85SXin LI # undef z_gzgetc
406c9083b85SXin LI #else
407c9083b85SXin LI # undef gzgetc
408c9083b85SXin LI #endif
gzgetc(gzFile file)409*4717628eSXin LI int ZEXPORT gzgetc(gzFile file) {
410c9083b85SXin LI unsigned char buf[1];
411c9083b85SXin LI gz_statep state;
412c9083b85SXin LI
413c9083b85SXin LI /* get internal structure */
414c9083b85SXin LI if (file == NULL)
415c9083b85SXin LI return -1;
416c9083b85SXin LI state = (gz_statep)file;
417c9083b85SXin LI
418c9083b85SXin LI /* check that we're reading and that there's no (serious) error */
419c9083b85SXin LI if (state->mode != GZ_READ ||
420c9083b85SXin LI (state->err != Z_OK && state->err != Z_BUF_ERROR))
421c9083b85SXin LI return -1;
422c9083b85SXin LI
423c9083b85SXin LI /* try output buffer (no need to check for skip request) */
424c9083b85SXin LI if (state->x.have) {
425c9083b85SXin LI state->x.have--;
426c9083b85SXin LI state->x.pos++;
427c9083b85SXin LI return *(state->x.next)++;
428c9083b85SXin LI }
429c9083b85SXin LI
430c9083b85SXin LI /* nothing there -- try gz_read() */
431cd882207SXin LI return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
432c9083b85SXin LI }
433c9083b85SXin LI
gzgetc_(gzFile file)434*4717628eSXin LI int ZEXPORT gzgetc_(gzFile file) {
435c9083b85SXin LI return gzgetc(file);
436c9083b85SXin LI }
437c9083b85SXin LI
438c9083b85SXin LI /* -- see zlib.h -- */
gzungetc(int c,gzFile file)439*4717628eSXin LI int ZEXPORT gzungetc(int c, gzFile file) {
440c9083b85SXin LI gz_statep state;
441c9083b85SXin LI
442c9083b85SXin LI /* get internal structure */
443c9083b85SXin LI if (file == NULL)
444c9083b85SXin LI return -1;
445c9083b85SXin LI state = (gz_statep)file;
446c9083b85SXin LI
447*4717628eSXin LI /* in case this was just opened, set up the input buffer */
448*4717628eSXin LI if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
449*4717628eSXin LI (void)gz_look(state);
450*4717628eSXin LI
451c9083b85SXin LI /* check that we're reading and that there's no (serious) error */
452c9083b85SXin LI if (state->mode != GZ_READ ||
453c9083b85SXin LI (state->err != Z_OK && state->err != Z_BUF_ERROR))
454c9083b85SXin LI return -1;
455c9083b85SXin LI
456c9083b85SXin LI /* process a skip request */
457c9083b85SXin LI if (state->seek) {
458c9083b85SXin LI state->seek = 0;
459c9083b85SXin LI if (gz_skip(state, state->skip) == -1)
460c9083b85SXin LI return -1;
461c9083b85SXin LI }
462c9083b85SXin LI
463c9083b85SXin LI /* can't push EOF */
464c9083b85SXin LI if (c < 0)
465c9083b85SXin LI return -1;
466c9083b85SXin LI
467c9083b85SXin LI /* if output buffer empty, put byte at end (allows more pushing) */
468c9083b85SXin LI if (state->x.have == 0) {
469c9083b85SXin LI state->x.have = 1;
470c9083b85SXin LI state->x.next = state->out + (state->size << 1) - 1;
471c9083b85SXin LI state->x.next[0] = (unsigned char)c;
472c9083b85SXin LI state->x.pos--;
473c9083b85SXin LI state->past = 0;
474c9083b85SXin LI return c;
475c9083b85SXin LI }
476c9083b85SXin LI
477c9083b85SXin LI /* if no room, give up (must have already done a gzungetc()) */
478c9083b85SXin LI if (state->x.have == (state->size << 1)) {
479c9083b85SXin LI gz_error(state, Z_DATA_ERROR, "out of room to push characters");
480c9083b85SXin LI return -1;
481c9083b85SXin LI }
482c9083b85SXin LI
483c9083b85SXin LI /* slide output data if needed and insert byte before existing data */
484c9083b85SXin LI if (state->x.next == state->out) {
485c9083b85SXin LI unsigned char *src = state->out + state->x.have;
486c9083b85SXin LI unsigned char *dest = state->out + (state->size << 1);
487c9083b85SXin LI while (src > state->out)
488c9083b85SXin LI *--dest = *--src;
489c9083b85SXin LI state->x.next = dest;
490c9083b85SXin LI }
491c9083b85SXin LI state->x.have++;
492c9083b85SXin LI state->x.next--;
493c9083b85SXin LI state->x.next[0] = (unsigned char)c;
494c9083b85SXin LI state->x.pos--;
495c9083b85SXin LI state->past = 0;
496c9083b85SXin LI return c;
497c9083b85SXin LI }
498c9083b85SXin LI
499c9083b85SXin LI /* -- see zlib.h -- */
gzgets(gzFile file,char * buf,int len)500*4717628eSXin LI char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
501c9083b85SXin LI unsigned left, n;
502c9083b85SXin LI char *str;
503c9083b85SXin LI unsigned char *eol;
504c9083b85SXin LI gz_statep state;
505c9083b85SXin LI
506c9083b85SXin LI /* check parameters and get internal structure */
507c9083b85SXin LI if (file == NULL || buf == NULL || len < 1)
508c9083b85SXin LI return NULL;
509c9083b85SXin LI state = (gz_statep)file;
510c9083b85SXin LI
511c9083b85SXin LI /* check that we're reading and that there's no (serious) error */
512c9083b85SXin LI if (state->mode != GZ_READ ||
513c9083b85SXin LI (state->err != Z_OK && state->err != Z_BUF_ERROR))
514c9083b85SXin LI return NULL;
515c9083b85SXin LI
516c9083b85SXin LI /* process a skip request */
517c9083b85SXin LI if (state->seek) {
518c9083b85SXin LI state->seek = 0;
519c9083b85SXin LI if (gz_skip(state, state->skip) == -1)
520c9083b85SXin LI return NULL;
521c9083b85SXin LI }
522c9083b85SXin LI
523c9083b85SXin LI /* copy output bytes up to new line or len - 1, whichever comes first --
524c9083b85SXin LI append a terminating zero to the string (we don't check for a zero in
525c9083b85SXin LI the contents, let the user worry about that) */
526c9083b85SXin LI str = buf;
527c9083b85SXin LI left = (unsigned)len - 1;
528c9083b85SXin LI if (left) do {
529c9083b85SXin LI /* assure that something is in the output buffer */
530c9083b85SXin LI if (state->x.have == 0 && gz_fetch(state) == -1)
531c9083b85SXin LI return NULL; /* error */
532c9083b85SXin LI if (state->x.have == 0) { /* end of file */
533c9083b85SXin LI state->past = 1; /* read past end */
534c9083b85SXin LI break; /* return what we have */
535c9083b85SXin LI }
536c9083b85SXin LI
537c9083b85SXin LI /* look for end-of-line in current output buffer */
538c9083b85SXin LI n = state->x.have > left ? left : state->x.have;
539c9083b85SXin LI eol = (unsigned char *)memchr(state->x.next, '\n', n);
540c9083b85SXin LI if (eol != NULL)
541c9083b85SXin LI n = (unsigned)(eol - state->x.next) + 1;
542c9083b85SXin LI
543c9083b85SXin LI /* copy through end-of-line, or remainder if not found */
544c9083b85SXin LI memcpy(buf, state->x.next, n);
545c9083b85SXin LI state->x.have -= n;
546c9083b85SXin LI state->x.next += n;
547c9083b85SXin LI state->x.pos += n;
548c9083b85SXin LI left -= n;
549c9083b85SXin LI buf += n;
550c9083b85SXin LI } while (left && eol == NULL);
551c9083b85SXin LI
552c9083b85SXin LI /* return terminated string, or if nothing, end of file */
553c9083b85SXin LI if (buf == str)
554c9083b85SXin LI return NULL;
555c9083b85SXin LI buf[0] = 0;
556c9083b85SXin LI return str;
557c9083b85SXin LI }
558c9083b85SXin LI
559c9083b85SXin LI /* -- see zlib.h -- */
gzdirect(gzFile file)560*4717628eSXin LI int ZEXPORT gzdirect(gzFile file) {
561c9083b85SXin LI gz_statep state;
562c9083b85SXin LI
563c9083b85SXin LI /* get internal structure */
564c9083b85SXin LI if (file == NULL)
565c9083b85SXin LI return 0;
566c9083b85SXin LI state = (gz_statep)file;
567c9083b85SXin LI
568c9083b85SXin LI /* if the state is not known, but we can find out, then do so (this is
569c9083b85SXin LI mainly for right after a gzopen() or gzdopen()) */
570c9083b85SXin LI if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
571c9083b85SXin LI (void)gz_look(state);
572c9083b85SXin LI
573c9083b85SXin LI /* return 1 if transparent, 0 if processing a gzip stream */
574c9083b85SXin LI return state->direct;
575c9083b85SXin LI }
576c9083b85SXin LI
577c9083b85SXin LI /* -- see zlib.h -- */
gzclose_r(gzFile file)578*4717628eSXin LI int ZEXPORT gzclose_r(gzFile file) {
579c9083b85SXin LI int ret, err;
580c9083b85SXin LI gz_statep state;
581c9083b85SXin LI
582c9083b85SXin LI /* get internal structure */
583c9083b85SXin LI if (file == NULL)
584c9083b85SXin LI return Z_STREAM_ERROR;
585c9083b85SXin LI state = (gz_statep)file;
586c9083b85SXin LI
587c9083b85SXin LI /* check that we're reading */
588c9083b85SXin LI if (state->mode != GZ_READ)
589c9083b85SXin LI return Z_STREAM_ERROR;
590c9083b85SXin LI
591c9083b85SXin LI /* free memory and close file */
592c9083b85SXin LI if (state->size) {
593c9083b85SXin LI inflateEnd(&(state->strm));
594c9083b85SXin LI free(state->out);
595c9083b85SXin LI free(state->in);
596c9083b85SXin LI }
597c9083b85SXin LI err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
598c9083b85SXin LI gz_error(state, Z_OK, NULL);
599c9083b85SXin LI free(state->path);
600c9083b85SXin LI ret = close(state->fd);
601c9083b85SXin LI free(state);
602c9083b85SXin LI return ret ? Z_ERRNO : err;
603c9083b85SXin LI }
604