Coverage Report

Created: 2026-08-31 06:32

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