Coverage Report

Created: 2025-07-12 06:16

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