The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/libkern/zlib/gzio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2008 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /* gzio.c -- IO on .gz files
   29  * Copyright (C) 1995-2005 Jean-loup Gailly.
   30  * For conditions of distribution and use, see copyright notice in zlib.h
   31  *
   32  * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
   33  */
   34 
   35 /* @(#) $Id$ */
   36 
   37 #include <stdio.h>
   38 
   39 #include "zutil.h"
   40 
   41 #ifdef NO_DEFLATE       /* for compatibility with old definition */
   42 #  define NO_GZCOMPRESS
   43 #endif
   44 
   45 #ifndef NO_DUMMY_DECL
   46 struct internal_state {int dummy;}; /* for buggy compilers */
   47 #endif
   48 
   49 #ifndef Z_BUFSIZE
   50 #  ifdef MAXSEG_64K
   51 #    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
   52 #  else
   53 #    define Z_BUFSIZE 16384
   54 #  endif
   55 #endif
   56 #ifndef Z_PRINTF_BUFSIZE
   57 #  define Z_PRINTF_BUFSIZE 4096
   58 #endif
   59 
   60 #ifdef __MVS__
   61 #  pragma map (fdopen , "\174\174FDOPEN")
   62    FILE *fdopen(int, const char *);
   63 #endif
   64 
   65 #ifndef STDC
   66 extern voidp  malloc OF((uInt size));
   67 extern void   free   OF((voidpf ptr));
   68 #endif
   69 
   70 #define ALLOC(size) malloc(size)
   71 #define TRYFREE(p) {if (p) free(p);}
   72 
   73 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
   74 
   75 /* gzip flag byte */
   76 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
   77 #define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
   78 #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
   79 #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
   80 #define COMMENT      0x10 /* bit 4 set: file comment present */
   81 #define RESERVED     0xE0 /* bits 5..7: reserved */
   82 
   83 typedef struct gz_stream {
   84     z_stream stream;
   85     int      z_err;   /* error code for last stream operation */
   86     int      z_eof;   /* set if end of input file */
   87     FILE     *file;   /* .gz file */
   88     Byte     *inbuf;  /* input buffer */
   89     Byte     *outbuf; /* output buffer */
   90     uLong    crc;     /* crc32 of uncompressed data */
   91     char     *msg;    /* error message */
   92     char     *path;   /* path name for debugging only */
   93     int      transparent; /* 1 if input file is not a .gz file */
   94     char     mode;    /* 'w' or 'r' */
   95     z_off_t  start;   /* start of compressed data in file (header skipped) */
   96     z_off_t  in;      /* bytes into deflate or inflate */
   97     z_off_t  out;     /* bytes out of deflate or inflate */
   98     int      back;    /* one character push-back */
   99     int      last;    /* true if push-back is last character */
  100 } gz_stream;
  101 
  102 
  103 local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
  104 local int do_flush        OF((gzFile file, int flush));
  105 local int    get_byte     OF((gz_stream *s));
  106 local void   check_header OF((gz_stream *s));
  107 local int    destroy      OF((gz_stream *s));
  108 local void   putLong      OF((FILE *file, uLong x));
  109 local uLong  getLong      OF((gz_stream *s));
  110 
  111 /* ===========================================================================
  112      Opens a gzip (.gz) file for reading or writing. The mode parameter
  113    is as in fopen ("rb" or "wb"). The file is given either by file descriptor
  114    or path name (if fd == -1).
  115      gz_open returns NULL if the file could not be opened or if there was
  116    insufficient memory to allocate the (de)compression state; errno
  117    can be checked to distinguish the two cases (if errno is zero, the
  118    zlib error is Z_MEM_ERROR).
  119 */
  120 local gzFile gz_open (path, mode, fd)
  121     const char *path;
  122     const char *mode;
  123     int  fd;
  124 {
  125     int err;
  126     int level = Z_DEFAULT_COMPRESSION; /* compression level */
  127     int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
  128     char *p = (char*)mode;
  129     gz_stream *s;
  130     char fmode[80]; /* copy of mode, without the compression level */
  131     char *m = fmode;
  132 
  133     if (!path || !mode) return Z_NULL;
  134 
  135     s = (gz_stream *)ALLOC(sizeof(gz_stream));
  136     if (!s) return Z_NULL;
  137 
  138     s->stream.zalloc = (alloc_func)0;
  139     s->stream.zfree = (free_func)0;
  140     s->stream.opaque = (voidpf)0;
  141     s->stream.next_in = s->inbuf = Z_NULL;
  142     s->stream.next_out = s->outbuf = Z_NULL;
  143     s->stream.avail_in = s->stream.avail_out = 0;
  144     s->file = NULL;
  145     s->z_err = Z_OK;
  146     s->z_eof = 0;
  147     s->in = 0;
  148     s->out = 0;
  149     s->back = EOF;
  150     s->crc = z_crc32(0L, Z_NULL, 0);
  151     s->msg = NULL;
  152     s->transparent = 0;
  153 
  154     s->path = (char*)ALLOC(strlen(path)+1);
  155     if (s->path == NULL) {
  156         return destroy(s), (gzFile)Z_NULL;
  157     }
  158     strcpy(s->path, path); /* do this early for debugging */
  159 
  160     s->mode = '\0';
  161     do {
  162         if (*p == 'r') s->mode = 'r';
  163         if (*p == 'w' || *p == 'a') s->mode = 'w';
  164         if (*p >= '' && *p <= '9') {
  165             level = *p - '';
  166         } else if (*p == 'f') {
  167           strategy = Z_FILTERED;
  168         } else if (*p == 'h') {
  169           strategy = Z_HUFFMAN_ONLY;
  170         } else if (*p == 'R') {
  171           strategy = Z_RLE;
  172         } else {
  173             *m++ = *p; /* copy the mode */
  174         }
  175     } while (*p++ && m != fmode + sizeof(fmode));
  176     if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
  177 
  178     if (s->mode == 'w') {
  179 #ifdef NO_GZCOMPRESS
  180         err = Z_STREAM_ERROR;
  181 #else
  182         err = deflateInit2(&(s->stream), level,
  183                            Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
  184         /* windowBits is passed < 0 to suppress zlib header */
  185 
  186         s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
  187 #endif
  188         if (err != Z_OK || s->outbuf == Z_NULL) {
  189             return destroy(s), (gzFile)Z_NULL;
  190         }
  191     } else {
  192         s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
  193 
  194         err = inflateInit2(&(s->stream), -MAX_WBITS);
  195         /* windowBits is passed < 0 to tell that there is no zlib header.
  196          * Note that in this case inflate *requires* an extra "dummy" byte
  197          * after the compressed stream in order to complete decompression and
  198          * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
  199          * present after the compressed stream.
  200          */
  201         if (err != Z_OK || s->inbuf == Z_NULL) {
  202             return destroy(s), (gzFile)Z_NULL;
  203         }
  204     }
  205     s->stream.avail_out = Z_BUFSIZE;
  206 
  207     errno = 0;
  208     s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
  209 
  210     if (s->file == NULL) {
  211         return destroy(s), (gzFile)Z_NULL;
  212     }
  213     if (s->mode == 'w') {
  214         /* Write a very simple .gz header:
  215          */
  216         fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
  217              Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
  218         s->start = 10L;
  219         /* We use 10L instead of ftell(s->file) to because ftell causes an
  220          * fflush on some systems. This version of the library doesn't use
  221          * start anyway in write mode, so this initialization is not
  222          * necessary.
  223          */
  224     } else {
  225         check_header(s); /* skip the .gz header */
  226         s->start = ftell(s->file) - s->stream.avail_in;
  227     }
  228 
  229     return (gzFile)s;
  230 }
  231 
  232 /* ===========================================================================
  233      Opens a gzip (.gz) file for reading or writing.
  234 */
  235 gzFile ZEXPORT gzopen (path, mode)
  236     const char *path;
  237     const char *mode;
  238 {
  239     return gz_open (path, mode, -1);
  240 }
  241 
  242 /* ===========================================================================
  243      Associate a gzFile with the file descriptor fd. fd is not dup'ed here
  244    to mimic the behavio(u)r of fdopen.
  245 */
  246 gzFile ZEXPORT gzdopen (fd, mode)
  247     int fd;
  248     const char *mode;
  249 {
  250     char name[46];      /* allow for up to 128-bit integers */
  251 
  252     if (fd < 0) return (gzFile)Z_NULL;
  253     sprintf(name, "<fd:%d>", fd); /* for debugging */
  254 
  255     return gz_open (name, mode, fd);
  256 }
  257 
  258 /* ===========================================================================
  259  * Update the compression level and strategy
  260  */
  261 int ZEXPORT gzsetparams (file, level, strategy)
  262     gzFile file;
  263     int level;
  264     int strategy;
  265 {
  266     gz_stream *s = (gz_stream*)file;
  267 
  268     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
  269 
  270     /* Make room to allow flushing */
  271     if (s->stream.avail_out == 0) {
  272 
  273         s->stream.next_out = s->outbuf;
  274         if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
  275             s->z_err = Z_ERRNO;
  276         }
  277         s->stream.avail_out = Z_BUFSIZE;
  278     }
  279 
  280     return deflateParams (&(s->stream), level, strategy);
  281 }
  282 
  283 /* ===========================================================================
  284      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
  285    for end of file.
  286    IN assertion: the stream s has been sucessfully opened for reading.
  287 */
  288 local int get_byte(s)
  289     gz_stream *s;
  290 {
  291     if (s->z_eof) return EOF;
  292     if (s->stream.avail_in == 0) {
  293         errno = 0;
  294         s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
  295         if (s->stream.avail_in == 0) {
  296             s->z_eof = 1;
  297             if (ferror(s->file)) s->z_err = Z_ERRNO;
  298             return EOF;
  299         }
  300         s->stream.next_in = s->inbuf;
  301     }
  302     s->stream.avail_in--;
  303     return *(s->stream.next_in)++;
  304 }
  305 
  306 /* ===========================================================================
  307       Check the gzip header of a gz_stream opened for reading. Set the stream
  308     mode to transparent if the gzip magic header is not present; set s->err
  309     to Z_DATA_ERROR if the magic header is present but the rest of the header
  310     is incorrect.
  311     IN assertion: the stream s has already been created sucessfully;
  312        s->stream.avail_in is zero for the first time, but may be non-zero
  313        for concatenated .gz files.
  314 */
  315 local void check_header(s)
  316     gz_stream *s;
  317 {
  318     int method; /* method byte */
  319     int flags;  /* flags byte */
  320     uInt len;
  321     int c;
  322 
  323     /* Assure two bytes in the buffer so we can peek ahead -- handle case
  324        where first byte of header is at the end of the buffer after the last
  325        gzip segment */
  326     len = s->stream.avail_in;
  327     if (len < 2) {
  328         if (len) s->inbuf[0] = s->stream.next_in[0];
  329         errno = 0;
  330         len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
  331         if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
  332         s->stream.avail_in += len;
  333         s->stream.next_in = s->inbuf;
  334         if (s->stream.avail_in < 2) {
  335             s->transparent = s->stream.avail_in;
  336             return;
  337         }
  338     }
  339 
  340     /* Peek ahead to check the gzip magic header */
  341     if (s->stream.next_in[0] != gz_magic[0] ||
  342         s->stream.next_in[1] != gz_magic[1]) {
  343         s->transparent = 1;
  344         return;
  345     }
  346     s->stream.avail_in -= 2;
  347     s->stream.next_in += 2;
  348 
  349     /* Check the rest of the gzip header */
  350     method = get_byte(s);
  351     flags = get_byte(s);
  352     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
  353         s->z_err = Z_DATA_ERROR;
  354         return;
  355     }
  356 
  357     /* Discard time, xflags and OS code: */
  358     for (len = 0; len < 6; len++) (void)get_byte(s);
  359 
  360     if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
  361         len  =  (uInt)get_byte(s);
  362         len += ((uInt)get_byte(s))<<8;
  363         /* len is garbage if EOF but the loop below will quit anyway */
  364         while (len-- != 0 && get_byte(s) != EOF) ;
  365     }
  366     if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
  367         while ((c = get_byte(s)) != 0 && c != EOF) ;
  368     }
  369     if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
  370         while ((c = get_byte(s)) != 0 && c != EOF) ;
  371     }
  372     if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
  373         for (len = 0; len < 2; len++) (void)get_byte(s);
  374     }
  375     s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
  376 }
  377 
  378  /* ===========================================================================
  379  * Cleanup then free the given gz_stream. Return a zlib error code.
  380    Try freeing in the reverse order of allocations.
  381  */
  382 local int destroy (s)
  383     gz_stream *s;
  384 {
  385     int err = Z_OK;
  386 
  387     if (!s) return Z_STREAM_ERROR;
  388 
  389     TRYFREE(s->msg);
  390 
  391     if (s->stream.state != NULL) {
  392         if (s->mode == 'w') {
  393 #ifdef NO_GZCOMPRESS
  394             err = Z_STREAM_ERROR;
  395 #else
  396             err = deflateEnd(&(s->stream));
  397 #endif
  398         } else if (s->mode == 'r') {
  399             err = inflateEnd(&(s->stream));
  400         }
  401     }
  402     if (s->file != NULL && fclose(s->file)) {
  403 #ifdef ESPIPE
  404         if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
  405 #endif
  406             err = Z_ERRNO;
  407     }
  408     if (s->z_err < 0) err = s->z_err;
  409 
  410     TRYFREE(s->inbuf);
  411     TRYFREE(s->outbuf);
  412     TRYFREE(s->path);
  413     TRYFREE(s);
  414     return err;
  415 }
  416 
  417 /* ===========================================================================
  418      Reads the given number of uncompressed bytes from the compressed file.
  419    gzread returns the number of bytes actually read (0 for end of file).
  420 */
  421 int ZEXPORT gzread (file, buf, len)
  422     gzFile file;
  423     voidp buf;
  424     unsigned len;
  425 {
  426     gz_stream *s = (gz_stream*)file;
  427     Bytef *start = (Bytef*)buf; /* starting point for crc computation */
  428     Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
  429 
  430     if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
  431 
  432     if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
  433     if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
  434 
  435     next_out = (Byte*)buf;
  436     s->stream.next_out = (Bytef*)buf;
  437     s->stream.avail_out = len;
  438 
  439     if (s->stream.avail_out && s->back != EOF) {
  440         *next_out++ = s->back;
  441         s->stream.next_out++;
  442         s->stream.avail_out--;
  443         s->back = EOF;
  444         s->out++;
  445         start++;
  446         if (s->last) {
  447             s->z_err = Z_STREAM_END;
  448             return 1;
  449         }
  450     }
  451 
  452     while (s->stream.avail_out != 0) {
  453 
  454         if (s->transparent) {
  455             /* Copy first the lookahead bytes: */
  456             uInt n = s->stream.avail_in;
  457             if (n > s->stream.avail_out) n = s->stream.avail_out;
  458             if (n > 0) {
  459                 zmemcpy(s->stream.next_out, s->stream.next_in, n);
  460                 next_out += n;
  461                 s->stream.next_out = next_out;
  462                 s->stream.next_in   += n;
  463                 s->stream.avail_out -= n;
  464                 s->stream.avail_in  -= n;
  465             }
  466             if (s->stream.avail_out > 0) {
  467                 s->stream.avail_out -=
  468                     (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
  469             }
  470             len -= s->stream.avail_out;
  471             s->in  += len;
  472             s->out += len;
  473             if (len == 0) s->z_eof = 1;
  474             return (int)len;
  475         }
  476         if (s->stream.avail_in == 0 && !s->z_eof) {
  477 
  478             errno = 0;
  479             s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
  480             if (s->stream.avail_in == 0) {
  481                 s->z_eof = 1;
  482                 if (ferror(s->file)) {
  483                     s->z_err = Z_ERRNO;
  484                     break;
  485                 }
  486             }
  487             s->stream.next_in = s->inbuf;
  488         }
  489         s->in += s->stream.avail_in;
  490         s->out += s->stream.avail_out;
  491         s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
  492         s->in -= s->stream.avail_in;
  493         s->out -= s->stream.avail_out;
  494 
  495         if (s->z_err == Z_STREAM_END) {
  496             /* Check CRC and original size */
  497             s->crc = z_crc32(s->crc, start, (uInt)(s->stream.next_out - start));
  498             start = s->stream.next_out;
  499 
  500             if (getLong(s) != s->crc) {
  501                 s->z_err = Z_DATA_ERROR;
  502             } else {
  503                 (void)getLong(s);
  504                 /* The uncompressed length returned by above getlong() may be
  505                  * different from s->out in case of concatenated .gz files.
  506                  * Check for such files:
  507                  */
  508                 check_header(s);
  509                 if (s->z_err == Z_OK) {
  510                     inflateReset(&(s->stream));
  511                     s->crc = z_crc32(0L, Z_NULL, 0);
  512                 }
  513             }
  514         }
  515         if (s->z_err != Z_OK || s->z_eof) break;
  516     }
  517     s->crc = z_crc32(s->crc, start, (uInt)(s->stream.next_out - start));
  518 
  519     if (len == s->stream.avail_out &&
  520         (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
  521         return -1;
  522     return (int)(len - s->stream.avail_out);
  523 }
  524 
  525 
  526 /* ===========================================================================
  527       Reads one byte from the compressed file. gzgetc returns this byte
  528    or -1 in case of end of file or error.
  529 */
  530 int ZEXPORT gzgetc(file)
  531     gzFile file;
  532 {
  533     unsigned char c;
  534 
  535     return gzread(file, &c, 1) == 1 ? c : -1;
  536 }
  537 
  538 
  539 /* ===========================================================================
  540       Push one byte back onto the stream.
  541 */
  542 int ZEXPORT gzungetc(c, file)
  543     int c;
  544     gzFile file;
  545 {
  546     gz_stream *s = (gz_stream*)file;
  547 
  548     if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
  549     s->back = c;
  550     s->out--;
  551     s->last = (s->z_err == Z_STREAM_END);
  552     if (s->last) s->z_err = Z_OK;
  553     s->z_eof = 0;
  554     return c;
  555 }
  556 
  557 
  558 /* ===========================================================================
  559       Reads bytes from the compressed file until len-1 characters are
  560    read, or a newline character is read and transferred to buf, or an
  561    end-of-file condition is encountered.  The string is then terminated
  562    with a null character.
  563       gzgets returns buf, or Z_NULL in case of error.
  564 
  565       The current implementation is not optimized at all.
  566 */
  567 char * ZEXPORT gzgets(file, buf, len)
  568     gzFile file;
  569     char *buf;
  570     int len;
  571 {
  572     char *b = buf;
  573     if (buf == Z_NULL || len <= 0) return Z_NULL;
  574 
  575     while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
  576     *buf = '\0';
  577     return b == buf && len > 0 ? Z_NULL : b;
  578 }
  579 
  580 
  581 #ifndef NO_GZCOMPRESS
  582 /* ===========================================================================
  583      Writes the given number of uncompressed bytes into the compressed file.
  584    gzwrite returns the number of bytes actually written (0 in case of error).
  585 */
  586 int ZEXPORT gzwrite (file, buf, len)
  587     gzFile file;
  588     voidpc buf;
  589     unsigned len;
  590 {
  591     gz_stream *s = (gz_stream*)file;
  592 
  593     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
  594 
  595     s->stream.next_in = (Bytef*)buf;
  596     s->stream.avail_in = len;
  597 
  598     while (s->stream.avail_in != 0) {
  599 
  600         if (s->stream.avail_out == 0) {
  601 
  602             s->stream.next_out = s->outbuf;
  603             if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
  604                 s->z_err = Z_ERRNO;
  605                 break;
  606             }
  607             s->stream.avail_out = Z_BUFSIZE;
  608         }
  609         s->in += s->stream.avail_in;
  610         s->out += s->stream.avail_out;
  611         s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
  612         s->in -= s->stream.avail_in;
  613         s->out -= s->stream.avail_out;
  614         if (s->z_err != Z_OK) break;
  615     }
  616     s->crc = z_crc32(s->crc, (const Bytef *)buf, len);
  617 
  618     return (int)(len - s->stream.avail_in);
  619 }
  620 
  621 
  622 /* ===========================================================================
  623      Converts, formats, and writes the args to the compressed file under
  624    control of the format string, as in fprintf. gzprintf returns the number of
  625    uncompressed bytes actually written (0 in case of error).
  626 */
  627 #ifdef STDC
  628 #include <stdarg.h>
  629 
  630 int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
  631 {
  632     char buf[Z_PRINTF_BUFSIZE];
  633     va_list va;
  634     int len;
  635 
  636     buf[sizeof(buf) - 1] = 0;
  637     va_start(va, format);
  638 #ifdef NO_vsnprintf
  639 #  ifdef HAS_vsprintf_void
  640     (void)vsprintf(buf, format, va);
  641     va_end(va);
  642     for (len = 0; len < sizeof(buf); len++)
  643         if (buf[len] == 0) break;
  644 #  else
  645     len = vsprintf(buf, format, va);
  646     va_end(va);
  647 #  endif
  648 #else
  649 #  ifdef HAS_vsnprintf_void
  650     (void)vsnprintf(buf, sizeof(buf), format, va);
  651     va_end(va);
  652     len = strlen(buf);
  653 #  else
  654     len = vsnprintf(buf, sizeof(buf), format, va);
  655     va_end(va);
  656 #  endif
  657 #endif
  658     if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
  659         return 0;
  660     return gzwrite(file, buf, (unsigned)len);
  661 }
  662 #else /* not ANSI C */
  663 
  664 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
  665                        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
  666     gzFile file;
  667     const char *format;
  668     int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
  669         a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
  670 {
  671     char buf[Z_PRINTF_BUFSIZE];
  672     int len;
  673 
  674     buf[sizeof(buf) - 1] = 0;
  675 #ifdef NO_snprintf
  676 #  ifdef HAS_sprintf_void
  677     sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
  678             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
  679     for (len = 0; len < sizeof(buf); len++)
  680         if (buf[len] == 0) break;
  681 #  else
  682     len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
  683                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
  684 #  endif
  685 #else
  686 #  ifdef HAS_snprintf_void
  687     snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
  688              a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
  689     len = strlen(buf);
  690 #  else
  691     len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
  692                  a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
  693 #  endif
  694 #endif
  695     if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
  696         return 0;
  697     return gzwrite(file, buf, len);
  698 }
  699 #endif
  700 
  701 /* ===========================================================================
  702       Writes c, converted to an unsigned char, into the compressed file.
  703    gzputc returns the value that was written, or -1 in case of error.
  704 */
  705 int ZEXPORT gzputc(file, c)
  706     gzFile file;
  707     int c;
  708 {
  709     unsigned char cc = (unsigned char) c; /* required for big endian systems */
  710 
  711     return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
  712 }
  713 
  714 
  715 /* ===========================================================================
  716       Writes the given null-terminated string to the compressed file, excluding
  717    the terminating null character.
  718       gzputs returns the number of characters written, or -1 in case of error.
  719 */
  720 int ZEXPORT gzputs(file, s)
  721     gzFile file;
  722     const char *s;
  723 {
  724     return gzwrite(file, (char*)s, (unsigned)strlen(s));
  725 }
  726 
  727 
  728 /* ===========================================================================
  729      Flushes all pending output into the compressed file. The parameter
  730    flush is as in the deflate() function.
  731 */
  732 local int do_flush (file, flush)
  733     gzFile file;
  734     int flush;
  735 {
  736     uInt len;
  737     int done = 0;
  738     gz_stream *s = (gz_stream*)file;
  739 
  740     if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
  741 
  742     s->stream.avail_in = 0; /* should be zero already anyway */
  743 
  744     for (;;) {
  745         len = Z_BUFSIZE - s->stream.avail_out;
  746 
  747         if (len != 0) {
  748             if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
  749                 s->z_err = Z_ERRNO;
  750                 return Z_ERRNO;
  751             }
  752             s->stream.next_out = s->outbuf;
  753             s->stream.avail_out = Z_BUFSIZE;
  754         }
  755         if (done) break;
  756         s->out += s->stream.avail_out;
  757         s->z_err = deflate(&(s->stream), flush);
  758         s->out -= s->stream.avail_out;
  759 
  760         /* Ignore the second of two consecutive flushes: */
  761         if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
  762 
  763         /* deflate has finished flushing only when it hasn't used up
  764          * all the available space in the output buffer:
  765          */
  766         done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
  767 
  768         if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
  769     }
  770     return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
  771 }
  772 
  773 int ZEXPORT gzflush (file, flush)
  774      gzFile file;
  775      int flush;
  776 {
  777     gz_stream *s = (gz_stream*)file;
  778     int err = do_flush (file, flush);
  779 
  780     if (err) return err;
  781     fflush(s->file);
  782     return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
  783 }
  784 #endif /* NO_GZCOMPRESS */
  785 
  786 /* ===========================================================================
  787       Sets the starting position for the next gzread or gzwrite on the given
  788    compressed file. The offset represents a number of bytes in the
  789       gzseek returns the resulting offset location as measured in bytes from
  790    the beginning of the uncompressed stream, or -1 in case of error.
  791       SEEK_END is not implemented, returns error.
  792       In this version of the library, gzseek can be extremely slow.
  793 */
  794 z_off_t ZEXPORT gzseek (file, offset, whence)
  795     gzFile file;
  796     z_off_t offset;
  797     int whence;
  798 {
  799     gz_stream *s = (gz_stream*)file;
  800 
  801     if (s == NULL || whence == SEEK_END ||
  802         s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
  803         return -1L;
  804     }
  805 
  806     if (s->mode == 'w') {
  807 #ifdef NO_GZCOMPRESS
  808         return -1L;
  809 #else
  810         if (whence == SEEK_SET) {
  811             offset -= s->in;
  812         }
  813         if (offset < 0) return -1L;
  814 
  815         /* At this point, offset is the number of zero bytes to write. */
  816         if (s->inbuf == Z_NULL) {
  817             s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
  818             if (s->inbuf == Z_NULL) return -1L;
  819             zmemzero(s->inbuf, Z_BUFSIZE);
  820         }
  821         while (offset > 0)  {
  822             uInt size = Z_BUFSIZE;
  823             if (offset < Z_BUFSIZE) size = (uInt)offset;
  824 
  825             size = gzwrite(file, s->inbuf, size);
  826             if (size == 0) return -1L;
  827 
  828             offset -= size;
  829         }
  830         return s->in;
  831 #endif
  832     }
  833     /* Rest of function is for reading only */
  834 
  835     /* compute absolute position */
  836     if (whence == SEEK_CUR) {
  837         offset += s->out;
  838     }
  839     if (offset < 0) return -1L;
  840 
  841     if (s->transparent) {
  842         /* map to fseek */
  843         s->back = EOF;
  844         s->stream.avail_in = 0;
  845         s->stream.next_in = s->inbuf;
  846         if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
  847 
  848         s->in = s->out = offset;
  849         return offset;
  850     }
  851 
  852     /* For a negative seek, rewind and use positive seek */
  853     if (offset >= s->out) {
  854         offset -= s->out;
  855     } else if (gzrewind(file) < 0) {
  856         return -1L;
  857     }
  858     /* offset is now the number of bytes to skip. */
  859 
  860     if (offset != 0 && s->outbuf == Z_NULL) {
  861         s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
  862         if (s->outbuf == Z_NULL) return -1L;
  863     }
  864     if (offset && s->back != EOF) {
  865         s->back = EOF;
  866         s->out++;
  867         offset--;
  868         if (s->last) s->z_err = Z_STREAM_END;
  869     }
  870     while (offset > 0)  {
  871         int size = Z_BUFSIZE;
  872         if (offset < Z_BUFSIZE) size = (int)offset;
  873 
  874         size = gzread(file, s->outbuf, (uInt)size);
  875         if (size <= 0) return -1L;
  876         offset -= size;
  877     }
  878     return s->out;
  879 }
  880 
  881 /* ===========================================================================
  882      Rewinds input file.
  883 */
  884 int ZEXPORT gzrewind (file)
  885     gzFile file;
  886 {
  887     gz_stream *s = (gz_stream*)file;
  888 
  889     if (s == NULL || s->mode != 'r') return -1;
  890 
  891     s->z_err = Z_OK;
  892     s->z_eof = 0;
  893     s->back = EOF;
  894     s->stream.avail_in = 0;
  895     s->stream.next_in = s->inbuf;
  896     s->crc = z_crc32(0L, Z_NULL, 0);
  897     if (!s->transparent) (void)inflateReset(&s->stream);
  898     s->in = 0;
  899     s->out = 0;
  900     return fseek(s->file, s->start, SEEK_SET);
  901 }
  902 
  903 /* ===========================================================================
  904      Returns the starting position for the next gzread or gzwrite on the
  905    given compressed file. This position represents a number of bytes in the
  906    uncompressed data stream.
  907 */
  908 z_off_t ZEXPORT gztell (file)
  909     gzFile file;
  910 {
  911     return gzseek(file, 0L, SEEK_CUR);
  912 }
  913 
  914 /* ===========================================================================
  915      Returns 1 when EOF has previously been detected reading the given
  916    input stream, otherwise zero.
  917 */
  918 int ZEXPORT gzeof (file)
  919     gzFile file;
  920 {
  921     gz_stream *s = (gz_stream*)file;
  922 
  923     /* With concatenated compressed files that can have embedded
  924      * crc trailers, z_eof is no longer the only/best indicator of EOF
  925      * on a gz_stream. Handle end-of-stream error explicitly here.
  926      */
  927     if (s == NULL || s->mode != 'r') return 0;
  928     if (s->z_eof) return 1;
  929     return s->z_err == Z_STREAM_END;
  930 }
  931 
  932 /* ===========================================================================
  933      Returns 1 if reading and doing so transparently, otherwise zero.
  934 */
  935 int ZEXPORT gzdirect (file)
  936     gzFile file;
  937 {
  938     gz_stream *s = (gz_stream*)file;
  939 
  940     if (s == NULL || s->mode != 'r') return 0;
  941     return s->transparent;
  942 }
  943 
  944 /* ===========================================================================
  945    Outputs a long in LSB order to the given file
  946 */
  947 local void putLong (file, x)
  948     FILE *file;
  949     uLong x;
  950 {
  951     int n;
  952     for (n = 0; n < 4; n++) {
  953         fputc((int)(x & 0xff), file);
  954         x >>= 8;
  955     }
  956 }
  957 
  958 /* ===========================================================================
  959    Reads a long in LSB order from the given gz_stream. Sets z_err in case
  960    of error.
  961 */
  962 local uLong getLong (s)
  963     gz_stream *s;
  964 {
  965     uLong x = (uLong)get_byte(s);
  966     int c;
  967 
  968     x += ((uLong)get_byte(s))<<8;
  969     x += ((uLong)get_byte(s))<<16;
  970     c = get_byte(s);
  971     if (c == EOF) s->z_err = Z_DATA_ERROR;
  972     x += ((uLong)c)<<24;
  973     return x;
  974 }
  975 
  976 /* ===========================================================================
  977      Flushes all pending output if necessary, closes the compressed file
  978    and deallocates all the (de)compression state.
  979 */
  980 int ZEXPORT gzclose (file)
  981     gzFile file;
  982 {
  983     gz_stream *s = (gz_stream*)file;
  984 
  985     if (s == NULL) return Z_STREAM_ERROR;
  986 
  987     if (s->mode == 'w') {
  988 #ifdef NO_GZCOMPRESS
  989         return Z_STREAM_ERROR;
  990 #else
  991         if (do_flush (file, Z_FINISH) != Z_OK)
  992             return destroy((gz_stream*)file);
  993 
  994         putLong (s->file, s->crc);
  995         putLong (s->file, (uLong)(s->in & 0xffffffff));
  996 #endif
  997     }
  998     return destroy((gz_stream*)file);
  999 }
 1000 
 1001 #ifdef STDC
 1002 #  define zstrerror(errnum) strerror(errnum)
 1003 #else
 1004 #  define zstrerror(errnum) ""
 1005 #endif
 1006 
 1007 /* ===========================================================================
 1008      Returns the error message for the last error which occurred on the
 1009    given compressed file. errnum is set to zlib error number. If an
 1010    error occurred in the file system and not in the compression library,
 1011    errnum is set to Z_ERRNO and the application may consult errno
 1012    to get the exact error code.
 1013 */
 1014 const char * ZEXPORT gzerror (file, errnum)
 1015     gzFile file;
 1016     int *errnum;
 1017 {
 1018     char *m;
 1019     gz_stream *s = (gz_stream*)file;
 1020 
 1021     if (s == NULL) {
 1022         *errnum = Z_STREAM_ERROR;
 1023         return (const char*)ERR_MSG(Z_STREAM_ERROR);
 1024     }
 1025     *errnum = s->z_err;
 1026     if (*errnum == Z_OK) return (const char*)"";
 1027 
 1028     m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
 1029 
 1030     if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
 1031 
 1032     TRYFREE(s->msg);
 1033     s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
 1034     if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
 1035     strcpy(s->msg, s->path);
 1036     strcat(s->msg, ": ");
 1037     strcat(s->msg, m);
 1038     return (const char*)s->msg;
 1039 }
 1040 
 1041 /* ===========================================================================
 1042      Clear the error and end-of-file flags, and do the same for the real file.
 1043 */
 1044 void ZEXPORT gzclearerr (file)
 1045     gzFile file;
 1046 {
 1047     gz_stream *s = (gz_stream*)file;
 1048 
 1049     if (s == NULL) return;
 1050     if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
 1051     s->z_eof = 0;
 1052     clearerr(s->file);
 1053 }

Cache object: 6d28c68cd7c956d21d6bb0ddfc7c34bb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.