Annotation of embedaddon/sudo/zlib/gzread.c, revision 1.1.1.1

1.1       misho       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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>