~ubuntu-branches/ubuntu/raring/clamav/raring-updates

« back to all changes in this revision

Viewing changes to win32/3rdparty/zlib/gzread.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2011-06-18 11:56:34 UTC
  • mfrom: (0.35.21 sid)
  • Revision ID: james.westby@ubuntu.com-20110618115634-u2lovivet0qx34d0
Tags: 0.97.1+dfsg-1ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop build-dep on electric-fence (in Universe)
  - Add apparmor profiles for clamd and freshclam along with maintainer
    script changes

Show diffs side-by-side

added added

removed removed

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