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