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