Coverage Report

Created: 2026-01-10 06:46

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