18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* gzio.c -- IO on .gz files
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (C) 1995-2005 Jean-loup Gailly.
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * For conditions of distribution and use, see copyright notice in zlib.h
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* @(#) $Id$ */
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "zutil.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef NO_DEFLATE       /* for compatibility with old definition */
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define NO_GZCOMPRESS
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef NO_DUMMY_DECL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct internal_state {int dummy;}; /* for buggy compilers */
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef Z_BUFSIZE
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  ifdef MAXSEG_64K
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  else
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    define Z_BUFSIZE 16384
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef Z_PRINTF_BUFSIZE
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define Z_PRINTF_BUFSIZE 4096
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __MVS__
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  pragma map (fdopen , "\174\174FDOPEN")
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   FILE *fdopen(int, const char *);
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef STDC
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectextern voidp  malloc OF((uInt size));
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectextern void   free   OF((voidpf ptr));
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ALLOC(size) malloc(size)
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TRYFREE(p) {if (p) free(p);}
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* gzip flag byte */
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define COMMENT      0x10 /* bit 4 set: file comment present */
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define RESERVED     0xE0 /* bits 5..7: reserved */
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct gz_stream {
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    z_stream stream;
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int      z_err;   /* error code for last stream operation */
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int      z_eof;   /* set if end of input file */
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FILE     *file;   /* .gz file */
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Byte     *inbuf;  /* input buffer */
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Byte     *outbuf; /* output buffer */
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uLong    crc;     /* crc32 of uncompressed data */
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char     *msg;    /* error message */
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char     *path;   /* path name for debugging only */
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int      transparent; /* 1 if input file is not a .gz file */
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char     mode;    /* 'w' or 'r' */
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    z_off_t  start;   /* start of compressed data in file (header skipped) */
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    z_off_t  in;      /* bytes into deflate or inflate */
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    z_off_t  out;     /* bytes out of deflate or inflate */
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int      back;    /* one character push-back */
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int      last;    /* true if push-back is last character */
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} gz_stream;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal gzFile gz_open      OF((const char *path, const char *mode, int  fd));
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal int do_flush        OF((gzFile file, int flush));
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal int    get_byte     OF((gz_stream *s));
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal void   check_header OF((gz_stream *s));
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal int    destroy      OF((gz_stream *s));
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal void   putLong      OF((FILE *file, uLong x));
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal uLong  getLong      OF((gz_stream *s));
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Opens a gzip (.gz) file for reading or writing. The mode parameter
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   or path name (if fd == -1).
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     gz_open returns NULL if the file could not be opened or if there was
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   insufficient memory to allocate the (de)compression state; errno
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   can be checked to distinguish the two cases (if errno is zero, the
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   zlib error is Z_MEM_ERROR).
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal gzFile gz_open (path, mode, fd)
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *path;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *mode;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  fd;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int level = Z_DEFAULT_COMPRESSION; /* compression level */
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *p = (char*)mode;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char fmode[80]; /* copy of mode, without the compression level */
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *m = fmode;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!path || !mode) return Z_NULL;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = (gz_stream *)ALLOC(sizeof(gz_stream));
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s) return Z_NULL;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.zalloc = (alloc_func)0;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.zfree = (free_func)0;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.opaque = (voidpf)0;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.next_in = s->inbuf = Z_NULL;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.next_out = s->outbuf = Z_NULL;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_in = s->stream.avail_out = 0;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->file = NULL;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->z_err = Z_OK;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->z_eof = 0;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->in = 0;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->out = 0;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->back = EOF;
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->crc = crc32(0L, Z_NULL, 0);
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->msg = NULL;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->transparent = 0;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->path = (char*)ALLOC(strlen(path)+1);
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->path == NULL) {
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return destroy(s), (gzFile)Z_NULL;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strcpy(s->path, path); /* do this early for debugging */
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->mode = '\0';
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do {
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*p == 'r') s->mode = 'r';
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*p == 'w' || *p == 'a') s->mode = 'w';
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*p >= '0' && *p <= '9') {
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            level = *p - '0';
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (*p == 'f') {
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          strategy = Z_FILTERED;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (*p == 'h') {
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          strategy = Z_HUFFMAN_ONLY;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (*p == 'R') {
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          strategy = Z_RLE;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *m++ = *p; /* copy the mode */
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (*p++ && m != fmode + sizeof(fmode));
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->mode == 'w') {
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef NO_GZCOMPRESS
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        err = Z_STREAM_ERROR;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        err = deflateInit2(&(s->stream), level,
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* windowBits is passed < 0 to suppress zlib header */
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (err != Z_OK || s->outbuf == Z_NULL) {
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return destroy(s), (gzFile)Z_NULL;
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        err = inflateInit2(&(s->stream), -MAX_WBITS);
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* windowBits is passed < 0 to tell that there is no zlib header.
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * Note that in this case inflate *requires* an extra "dummy" byte
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * after the compressed stream in order to complete decompression and
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * present after the compressed stream.
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         */
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (err != Z_OK || s->inbuf == Z_NULL) {
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return destroy(s), (gzFile)Z_NULL;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_out = Z_BUFSIZE;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = 0;
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->file == NULL) {
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return destroy(s), (gzFile)Z_NULL;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->mode == 'w') {
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Write a very simple .gz header:
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         */
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->start = 10L;
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* We use 10L instead of ftell(s->file) to because ftell causes an
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * fflush on some systems. This version of the library doesn't use
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * start anyway in write mode, so this initialization is not
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * necessary.
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         */
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        check_header(s); /* skip the .gz header */
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->start = ftell(s->file) - s->stream.avail_in;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (gzFile)s;
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Opens a gzip (.gz) file for reading or writing.
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectgzFile ZEXPORT gzopen (path, mode)
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *path;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *mode;
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gz_open (path, mode, -1);
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   to mimic the behavio(u)r of fdopen.
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectgzFile ZEXPORT gzdopen (fd, mode)
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *mode;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char name[46];      /* allow for up to 128-bit integers */
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0) return (gzFile)Z_NULL;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sprintf(name, "<fd:%d>", fd); /* for debugging */
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gz_open (name, mode, fd);
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Update the compression level and strategy
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzsetparams (file, level, strategy)
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int level;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int strategy;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Make room to allow flushing */
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->stream.avail_out == 0) {
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_out = s->outbuf;
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->z_err = Z_ERRNO;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.avail_out = Z_BUFSIZE;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return deflateParams (&(s->stream), level, strategy);
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for end of file.
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   IN assertion: the stream s has been sucessfully opened for reading.
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal int get_byte(s)
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s;
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->z_eof) return EOF;
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->stream.avail_in == 0) {
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        errno = 0;
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->stream.avail_in == 0) {
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->z_eof = 1;
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ferror(s->file)) s->z_err = Z_ERRNO;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return EOF;
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_in = s->inbuf;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_in--;
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return *(s->stream.next_in)++;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      Check the gzip header of a gz_stream opened for reading. Set the stream
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mode to transparent if the gzip magic header is not present; set s->err
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    to Z_DATA_ERROR if the magic header is present but the rest of the header
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is incorrect.
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    IN assertion: the stream s has already been created sucessfully;
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       s->stream.avail_in is zero for the first time, but may be non-zero
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       for concatenated .gz files.
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal void check_header(s)
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int method; /* method byte */
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int flags;  /* flags byte */
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uInt len;
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int c;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Assure two bytes in the buffer so we can peek ahead -- handle case
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       where first byte of header is at the end of the buffer after the last
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       gzip segment */
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = s->stream.avail_in;
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len < 2) {
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len) s->inbuf[0] = s->stream.next_in[0];
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        errno = 0;
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.avail_in += len;
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_in = s->inbuf;
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->stream.avail_in < 2) {
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->transparent = s->stream.avail_in;
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Peek ahead to check the gzip magic header */
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->stream.next_in[0] != gz_magic[0] ||
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_in[1] != gz_magic[1]) {
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->transparent = 1;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_in -= 2;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.next_in += 2;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Check the rest of the gzip header */
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    method = get_byte(s);
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    flags = get_byte(s);
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->z_err = Z_DATA_ERROR;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Discard time, xflags and OS code: */
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (len = 0; len < 6; len++) (void)get_byte(s);
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len  =  (uInt)get_byte(s);
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len += ((uInt)get_byte(s))<<8;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* len is garbage if EOF but the loop below will quit anyway */
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (len-- != 0 && get_byte(s) != EOF) ;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while ((c = get_byte(s)) != 0 && c != EOF) ;
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while ((c = get_byte(s)) != 0 && c != EOF) ;
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (len = 0; len < 2; len++) (void)get_byte(s);
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ===========================================================================
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Cleanup then free the given gz_stream. Return a zlib error code.
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Try freeing in the reverse order of allocations.
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal int destroy (s)
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err = Z_OK;
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s) return Z_STREAM_ERROR;
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TRYFREE(s->msg);
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->stream.state != NULL) {
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->mode == 'w') {
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef NO_GZCOMPRESS
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            err = Z_STREAM_ERROR;
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            err = deflateEnd(&(s->stream));
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (s->mode == 'r') {
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            err = inflateEnd(&(s->stream));
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->file != NULL && fclose(s->file)) {
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef ESPIPE
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            err = Z_ERRNO;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->z_err < 0) err = s->z_err;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TRYFREE(s->inbuf);
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TRYFREE(s->outbuf);
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TRYFREE(s->path);
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TRYFREE(s);
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return err;
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Reads the given number of uncompressed bytes from the compressed file.
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   gzread returns the number of bytes actually read (0 for end of file).
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzread (file, buf, len)
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    voidp buf;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned len;
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Bytef *start = (Bytef*)buf; /* starting point for crc computation */
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    next_out = (Byte*)buf;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.next_out = (Bytef*)buf;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_out = len;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->stream.avail_out && s->back != EOF) {
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *next_out++ = s->back;
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_out++;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.avail_out--;
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->back = EOF;
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out++;
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        start++;
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->last) {
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->z_err = Z_STREAM_END;
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (s->stream.avail_out != 0) {
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->transparent) {
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Copy first the lookahead bytes: */
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uInt n = s->stream.avail_in;
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (n > s->stream.avail_out) n = s->stream.avail_out;
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (n > 0) {
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                zmemcpy(s->stream.next_out, s->stream.next_in, n);
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                next_out += n;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->stream.next_out = next_out;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->stream.next_in   += n;
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->stream.avail_out -= n;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->stream.avail_in  -= n;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->stream.avail_out > 0) {
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->stream.avail_out -=
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len -= s->stream.avail_out;
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->in  += len;
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->out += len;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (len == 0) s->z_eof = 1;
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return (int)len;
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->stream.avail_in == 0 && !s->z_eof) {
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            errno = 0;
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->stream.avail_in == 0) {
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->z_eof = 1;
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (ferror(s->file)) {
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->z_err = Z_ERRNO;
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->stream.next_in = s->inbuf;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->in += s->stream.avail_in;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out += s->stream.avail_out;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->in -= s->stream.avail_in;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out -= s->stream.avail_out;
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->z_err == Z_STREAM_END) {
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Check CRC and original size */
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            start = s->stream.next_out;
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (getLong(s) != s->crc) {
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->z_err = Z_DATA_ERROR;
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (void)getLong(s);
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* The uncompressed length returned by above getlong() may be
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 * different from s->out in case of concatenated .gz files.
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 * Check for such files:
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 */
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                check_header(s);
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (s->z_err == Z_OK) {
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    inflateReset(&(s->stream));
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->crc = crc32(0L, Z_NULL, 0);
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->z_err != Z_OK || s->z_eof) break;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == s->stream.avail_out &&
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (int)(len - s->stream.avail_out);
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      Reads one byte from the compressed file. gzgetc returns this byte
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   or -1 in case of end of file or error.
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzgetc(file)
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char c;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gzread(file, &c, 1) == 1 ? c : -1;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      Push one byte back onto the stream.
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzungetc(c, file)
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int c;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->back = c;
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->out--;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->last = (s->z_err == Z_STREAM_END);
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->last) s->z_err = Z_OK;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->z_eof = 0;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return c;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      Reads bytes from the compressed file until len-1 characters are
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   read, or a newline character is read and transferred to buf, or an
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   end-of-file condition is encountered.  The string is then terminated
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   with a null character.
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      gzgets returns buf, or Z_NULL in case of error.
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      The current implementation is not optimized at all.
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar * ZEXPORT gzgets(file, buf, len)
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *buf;
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *b = buf;
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (buf == Z_NULL || len <= 0) return Z_NULL;
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *buf = '\0';
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return b == buf && len > 0 ? Z_NULL : b;
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef NO_GZCOMPRESS
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Writes the given number of uncompressed bytes into the compressed file.
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   gzwrite returns the number of bytes actually written (0 in case of error).
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzwrite (file, buf, len)
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    voidpc buf;
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned len;
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.next_in = (Bytef*)buf;
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_in = len;
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (s->stream.avail_in != 0) {
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->stream.avail_out == 0) {
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->stream.next_out = s->outbuf;
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->z_err = Z_ERRNO;
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->stream.avail_out = Z_BUFSIZE;
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->in += s->stream.avail_in;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out += s->stream.avail_out;
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->in -= s->stream.avail_in;
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out -= s->stream.avail_out;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->z_err != Z_OK) break;
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->crc = crc32(s->crc, (const Bytef *)buf, len);
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (int)(len - s->stream.avail_in);
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Converts, formats, and writes the args to the compressed file under
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   control of the format string, as in fprintf. gzprintf returns the number of
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   uncompressed bytes actually written (0 in case of error).
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef STDC
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf[Z_PRINTF_BUFSIZE];
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list va;
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf[sizeof(buf) - 1] = 0;
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start(va, format);
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef NO_vsnprintf
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  ifdef HAS_vsprintf_void
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void)vsprintf(buf, format, va);
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(va);
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (len = 0; len < sizeof(buf); len++)
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (buf[len] == 0) break;
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  else
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = vsprintf(buf, format, va);
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(va);
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  ifdef HAS_vsnprintf_void
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void)vsnprintf(buf, sizeof(buf), format, va);
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(va);
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = strlen(buf);
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  else
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = vsnprintf(buf, sizeof(buf), format, va);
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(va);
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gzwrite(file, buf, (unsigned)len);
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* not ANSI C */
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *format;
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf[Z_PRINTF_BUFSIZE];
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf[sizeof(buf) - 1] = 0;
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef NO_snprintf
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  ifdef HAS_sprintf_void
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (len = 0; len < sizeof(buf); len++)
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (buf[len] == 0) break;
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  else
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  ifdef HAS_snprintf_void
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = strlen(buf);
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  else
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gzwrite(file, buf, len);
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      Writes c, converted to an unsigned char, into the compressed file.
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   gzputc returns the value that was written, or -1 in case of error.
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzputc(file, c)
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int c;
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char cc = (unsigned char) c; /* required for big endian systems */
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      Writes the given null-terminated string to the compressed file, excluding
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   the terminating null character.
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      gzputs returns the number of characters written, or -1 in case of error.
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzputs(file, s)
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *s;
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gzwrite(file, (char*)s, (unsigned)strlen(s));
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Flushes all pending output into the compressed file. The parameter
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   flush is as in the deflate() function.
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal int do_flush (file, flush)
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int flush;
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uInt len;
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int done = 0;
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_in = 0; /* should be zero already anyway */
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = Z_BUFSIZE - s->stream.avail_out;
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len != 0) {
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->z_err = Z_ERRNO;
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return Z_ERRNO;
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->stream.next_out = s->outbuf;
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->stream.avail_out = Z_BUFSIZE;
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (done) break;
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out += s->stream.avail_out;
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->z_err = deflate(&(s->stream), flush);
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out -= s->stream.avail_out;
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Ignore the second of two consecutive flushes: */
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* deflate has finished flushing only when it hasn't used up
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * all the available space in the output buffer:
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         */
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzflush (file, flush)
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     gzFile file;
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     int flush;
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err = do_flush (file, flush);
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) return err;
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fflush(s->file);
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* NO_GZCOMPRESS */
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      Sets the starting position for the next gzread or gzwrite on the given
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   compressed file. The offset represents a number of bytes in the
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      gzseek returns the resulting offset location as measured in bytes from
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   the beginning of the uncompressed stream, or -1 in case of error.
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      SEEK_END is not implemented, returns error.
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      In this version of the library, gzseek can be extremely slow.
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectz_off_t ZEXPORT gzseek (file, offset, whence)
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    z_off_t offset;
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int whence;
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || whence == SEEK_END ||
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1L;
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->mode == 'w') {
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef NO_GZCOMPRESS
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1L;
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (whence == SEEK_SET) {
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset -= s->in;
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (offset < 0) return -1L;
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* At this point, offset is the number of zero bytes to write. */
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->inbuf == Z_NULL) {
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->inbuf == Z_NULL) return -1L;
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            zmemzero(s->inbuf, Z_BUFSIZE);
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (offset > 0)  {
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uInt size = Z_BUFSIZE;
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (offset < Z_BUFSIZE) size = (uInt)offset;
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            size = gzwrite(file, s->inbuf, size);
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size == 0) return -1L;
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset -= size;
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return s->in;
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Rest of function is for reading only */
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* compute absolute position */
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (whence == SEEK_CUR) {
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset += s->out;
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (offset < 0) return -1L;
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->transparent) {
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* map to fseek */
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->back = EOF;
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.avail_in = 0;
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->stream.next_in = s->inbuf;
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->in = s->out = offset;
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return offset;
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* For a negative seek, rewind and use positive seek */
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (offset >= s->out) {
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset -= s->out;
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (gzrewind(file) < 0) {
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1L;
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* offset is now the number of bytes to skip. */
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (offset != 0 && s->outbuf == Z_NULL) {
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->outbuf == Z_NULL) return -1L;
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (offset && s->back != EOF) {
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->back = EOF;
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->out++;
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset--;
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->last) s->z_err = Z_STREAM_END;
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (offset > 0)  {
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int size = Z_BUFSIZE;
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (offset < Z_BUFSIZE) size = (int)offset;
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        size = gzread(file, s->outbuf, (uInt)size);
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (size <= 0) return -1L;
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset -= size;
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s->out;
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Rewinds input file.
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzrewind (file)
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'r') return -1;
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->z_err = Z_OK;
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->z_eof = 0;
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->back = EOF;
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.avail_in = 0;
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->stream.next_in = s->inbuf;
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->crc = crc32(0L, Z_NULL, 0);
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s->transparent) (void)inflateReset(&s->stream);
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->in = 0;
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->out = 0;
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fseek(s->file, s->start, SEEK_SET);
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Returns the starting position for the next gzread or gzwrite on the
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   given compressed file. This position represents a number of bytes in the
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   uncompressed data stream.
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectz_off_t ZEXPORT gztell (file)
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return gzseek(file, 0L, SEEK_CUR);
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Returns 1 when EOF has previously been detected reading the given
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   input stream, otherwise zero.
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzeof (file)
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* With concatenated compressed files that can have embedded
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * crc trailers, z_eof is no longer the only/best indicator of EOF
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * on a gz_stream. Handle end-of-stream error explicitly here.
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     */
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'r') return 0;
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->z_eof) return 1;
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s->z_err == Z_STREAM_END;
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Returns 1 if reading and doing so transparently, otherwise zero.
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzdirect (file)
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL || s->mode != 'r') return 0;
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s->transparent;
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Outputs a long in LSB order to the given file
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal void putLong (file, x)
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    FILE *file;
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uLong x;
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int n;
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (n = 0; n < 4; n++) {
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fputc((int)(x & 0xff), file);
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        x >>= 8;
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Reads a long in LSB order from the given gz_stream. Sets z_err in case
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   of error.
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectlocal uLong getLong (s)
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s;
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uLong x = (uLong)get_byte(s);
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int c;
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    x += ((uLong)get_byte(s))<<8;
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    x += ((uLong)get_byte(s))<<16;
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    c = get_byte(s);
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (c == EOF) s->z_err = Z_DATA_ERROR;
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    x += ((uLong)c)<<24;
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return x;
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Flushes all pending output if necessary, closes the compressed file
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   and deallocates all the (de)compression state.
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint ZEXPORT gzclose (file)
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL) return Z_STREAM_ERROR;
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->mode == 'w') {
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef NO_GZCOMPRESS
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return Z_STREAM_ERROR;
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (do_flush (file, Z_FINISH) != Z_OK)
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return destroy((gz_stream*)file);
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        putLong (s->file, s->crc);
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        putLong (s->file, (uLong)(s->in & 0xffffffff));
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return destroy((gz_stream*)file);
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef STDC
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define zstrerror(errnum) strerror(errnum)
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define zstrerror(errnum) ""
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Returns the error message for the last error which occurred on the
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   given compressed file. errnum is set to zlib error number. If an
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   error occurred in the file system and not in the compression library,
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   errnum is set to Z_ERRNO and the application may consult errno
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   to get the exact error code.
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char * ZEXPORT gzerror (file, errnum)
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int *errnum;
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *m;
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL) {
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *errnum = Z_STREAM_ERROR;
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (const char*)ERR_MSG(Z_STREAM_ERROR);
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *errnum = s->z_err;
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*errnum == Z_OK) return (const char*)"";
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TRYFREE(s->msg);
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strcpy(s->msg, s->path);
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strcat(s->msg, ": ");
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    strcat(s->msg, m);
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (const char*)s->msg;
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ===========================================================================
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     Clear the error and end-of-file flags, and do the same for the real file.
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid ZEXPORT gzclearerr (file)
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gzFile file;
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gz_stream *s = (gz_stream*)file;
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s == NULL) return;
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->z_eof = 0;
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    clearerr(s->file);
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1027