Annotation of embedaddon/sudo/zlib/gzread.c, revision 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>