kusano fc6ab3
/* gzlib.c -- zlib functions common to reading and writing gzip files
kusano fc6ab3
 * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
kusano fc6ab3
 * For conditions of distribution and use, see copyright notice in zlib.h
kusano fc6ab3
 */
kusano fc6ab3
kusano fc6ab3
#include "gzguts.h"
kusano fc6ab3
kusano fc6ab3
#if defined(_WIN32) && !defined(__BORLANDC__)
kusano fc6ab3
#  define LSEEK _lseeki64
kusano fc6ab3
#else
kusano fc6ab3
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
kusano fc6ab3
#  define LSEEK lseek64
kusano fc6ab3
#else
kusano fc6ab3
#  define LSEEK lseek
kusano fc6ab3
#endif
kusano fc6ab3
#endif
kusano fc6ab3
kusano fc6ab3
/* Local functions */
kusano fc6ab3
local void gz_reset OF((gz_statep));
kusano fc6ab3
local gzFile gz_open OF((const void *, int, const char *));
kusano fc6ab3
kusano fc6ab3
#if defined UNDER_CE
kusano fc6ab3
kusano fc6ab3
/* Map the Windows error number in ERROR to a locale-dependent error message
kusano fc6ab3
   string and return a pointer to it.  Typically, the values for ERROR come
kusano fc6ab3
   from GetLastError.
kusano fc6ab3
kusano fc6ab3
   The string pointed to shall not be modified by the application, but may be
kusano fc6ab3
   overwritten by a subsequent call to gz_strwinerror
kusano fc6ab3
kusano fc6ab3
   The gz_strwinerror function does not change the current setting of
kusano fc6ab3
   GetLastError. */
kusano fc6ab3
char ZLIB_INTERNAL *gz_strwinerror (error)
kusano fc6ab3
     DWORD error;
kusano fc6ab3
{
kusano fc6ab3
    static char buf[1024];
kusano fc6ab3
kusano fc6ab3
    wchar_t *msgbuf;
kusano fc6ab3
    DWORD lasterr = GetLastError();
kusano fc6ab3
    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
kusano fc6ab3
        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
kusano fc6ab3
        NULL,
kusano fc6ab3
        error,
kusano fc6ab3
        0, /* Default language */
kusano fc6ab3
        (LPVOID)&msgbuf,
kusano fc6ab3
        0,
kusano fc6ab3
        NULL);
kusano fc6ab3
    if (chars != 0) {
kusano fc6ab3
        /* If there is an \r\n appended, zap it.  */
kusano fc6ab3
        if (chars >= 2
kusano fc6ab3
            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
kusano fc6ab3
            chars -= 2;
kusano fc6ab3
            msgbuf[chars] = 0;
kusano fc6ab3
        }
kusano fc6ab3
kusano fc6ab3
        if (chars > sizeof (buf) - 1) {
kusano fc6ab3
            chars = sizeof (buf) - 1;
kusano fc6ab3
            msgbuf[chars] = 0;
kusano fc6ab3
        }
kusano fc6ab3
kusano fc6ab3
        wcstombs(buf, msgbuf, chars + 1);
kusano fc6ab3
        LocalFree(msgbuf);
kusano fc6ab3
    }
kusano fc6ab3
    else {
kusano fc6ab3
        sprintf(buf, "unknown win32 error (%ld)", error);
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    SetLastError(lasterr);
kusano fc6ab3
    return buf;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
#endif /* UNDER_CE */
kusano fc6ab3
kusano fc6ab3
/* Reset gzip file state */
kusano fc6ab3
local void gz_reset(state)
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
{
kusano fc6ab3
    state->x.have = 0;              /* no output data available */
kusano fc6ab3
    if (state->mode == GZ_READ) {   /* for reading ... */
kusano fc6ab3
        state->eof = 0;             /* not at end of file */
kusano fc6ab3
        state->past = 0;            /* have not read past end yet */
kusano fc6ab3
        state->how = LOOK;          /* look for gzip header */
kusano fc6ab3
    }
kusano fc6ab3
    state->seek = 0;                /* no seek request pending */
kusano fc6ab3
    gz_error(state, Z_OK, NULL);    /* clear error */
kusano fc6ab3
    state->x.pos = 0;               /* no uncompressed data yet */
kusano fc6ab3
    state->strm.avail_in = 0;       /* no input data yet */
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* Open a gzip file either by name or file descriptor. */
kusano fc6ab3
local gzFile gz_open(path, fd, mode)
kusano fc6ab3
    const void *path;
kusano fc6ab3
    int fd;
kusano fc6ab3
    const char *mode;
kusano fc6ab3
{
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
    size_t len;
kusano fc6ab3
    int oflag;
kusano fc6ab3
#ifdef O_CLOEXEC
kusano fc6ab3
    int cloexec = 0;
kusano fc6ab3
#endif
kusano fc6ab3
#ifdef O_EXCL
kusano fc6ab3
    int exclusive = 0;
kusano fc6ab3
#endif
kusano fc6ab3
kusano fc6ab3
    /* check input */
kusano fc6ab3
    if (path == NULL)
kusano fc6ab3
        return NULL;
kusano fc6ab3
kusano fc6ab3
    /* allocate gzFile structure to return */
kusano fc6ab3
    state = (gz_statep)malloc(sizeof(gz_state));
kusano fc6ab3
    if (state == NULL)
kusano fc6ab3
        return NULL;
kusano fc6ab3
    state->size = 0;            /* no buffers allocated yet */
kusano fc6ab3
    state->want = GZBUFSIZE;    /* requested buffer size */
kusano fc6ab3
    state->msg = NULL;          /* no error message yet */
kusano fc6ab3
kusano fc6ab3
    /* interpret mode */
kusano fc6ab3
    state->mode = GZ_NONE;
kusano fc6ab3
    state->level = Z_DEFAULT_COMPRESSION;
kusano fc6ab3
    state->strategy = Z_DEFAULT_STRATEGY;
kusano fc6ab3
    state->direct = 0;
kusano fc6ab3
    while (*mode) {
kusano fc6ab3
        if (*mode >= '0' && *mode <= '9')
kusano fc6ab3
            state->level = *mode - '0';
kusano fc6ab3
        else
kusano fc6ab3
            switch (*mode) {
kusano fc6ab3
            case 'r':
kusano fc6ab3
                state->mode = GZ_READ;
kusano fc6ab3
                break;
kusano fc6ab3
#ifndef NO_GZCOMPRESS
kusano fc6ab3
            case 'w':
kusano fc6ab3
                state->mode = GZ_WRITE;
kusano fc6ab3
                break;
kusano fc6ab3
            case 'a':
kusano fc6ab3
                state->mode = GZ_APPEND;
kusano fc6ab3
                break;
kusano fc6ab3
#endif
kusano fc6ab3
            case '+':       /* can't read and write at the same time */
kusano fc6ab3
                free(state);
kusano fc6ab3
                return NULL;
kusano fc6ab3
            case 'b':       /* ignore -- will request binary anyway */
kusano fc6ab3
                break;
kusano fc6ab3
#ifdef O_CLOEXEC
kusano fc6ab3
            case 'e':
kusano fc6ab3
                cloexec = 1;
kusano fc6ab3
                break;
kusano fc6ab3
#endif
kusano fc6ab3
#ifdef O_EXCL
kusano fc6ab3
            case 'x':
kusano fc6ab3
                exclusive = 1;
kusano fc6ab3
                break;
kusano fc6ab3
#endif
kusano fc6ab3
            case 'f':
kusano fc6ab3
                state->strategy = Z_FILTERED;
kusano fc6ab3
                break;
kusano fc6ab3
            case 'h':
kusano fc6ab3
                state->strategy = Z_HUFFMAN_ONLY;
kusano fc6ab3
                break;
kusano fc6ab3
            case 'R':
kusano fc6ab3
                state->strategy = Z_RLE;
kusano fc6ab3
                break;
kusano fc6ab3
            case 'F':
kusano fc6ab3
                state->strategy = Z_FIXED;
kusano fc6ab3
                break;
kusano fc6ab3
            case 'T':
kusano fc6ab3
                state->direct = 1;
kusano fc6ab3
                break;
kusano fc6ab3
            default:        /* could consider as an error, but just ignore */
kusano fc6ab3
                ;
kusano fc6ab3
            }
kusano fc6ab3
        mode++;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* must provide an "r", "w", or "a" */
kusano fc6ab3
    if (state->mode == GZ_NONE) {
kusano fc6ab3
        free(state);
kusano fc6ab3
        return NULL;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* can't force transparent read */
kusano fc6ab3
    if (state->mode == GZ_READ) {
kusano fc6ab3
        if (state->direct) {
kusano fc6ab3
            free(state);
kusano fc6ab3
            return NULL;
kusano fc6ab3
        }
kusano fc6ab3
        state->direct = 1;      /* for empty file */
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* save the path name for error messages */
kusano fc6ab3
#ifdef _WIN32
kusano fc6ab3
    if (fd == -2) {
kusano fc6ab3
        len = wcstombs(NULL, path, 0);
kusano fc6ab3
        if (len == (size_t)-1)
kusano fc6ab3
            len = 0;
kusano fc6ab3
    }
kusano fc6ab3
    else
kusano fc6ab3
#endif
kusano fc6ab3
        len = strlen((const char *)path);
kusano fc6ab3
    state->path = (char *)malloc(len + 1);
kusano fc6ab3
    if (state->path == NULL) {
kusano fc6ab3
        free(state);
kusano fc6ab3
        return NULL;
kusano fc6ab3
    }
kusano fc6ab3
#ifdef _WIN32
kusano fc6ab3
    if (fd == -2)
kusano fc6ab3
        if (len)
kusano fc6ab3
            wcstombs(state->path, path, len + 1);
kusano fc6ab3
        else
kusano fc6ab3
            *(state->path) = 0;
kusano fc6ab3
    else
kusano fc6ab3
#endif
kusano fc6ab3
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
kusano fc6ab3
        snprintf(state->path, len + 1, "%s", (const char *)path);
kusano fc6ab3
#else
kusano fc6ab3
        strcpy(state->path, path);
kusano fc6ab3
#endif
kusano fc6ab3
kusano fc6ab3
    /* compute the flags for open() */
kusano fc6ab3
    oflag =
kusano fc6ab3
#ifdef O_LARGEFILE
kusano fc6ab3
        O_LARGEFILE |
kusano fc6ab3
#endif
kusano fc6ab3
#ifdef O_BINARY
kusano fc6ab3
        O_BINARY |
kusano fc6ab3
#endif
kusano fc6ab3
#ifdef O_CLOEXEC
kusano fc6ab3
        (cloexec ? O_CLOEXEC : 0) |
kusano fc6ab3
#endif
kusano fc6ab3
        (state->mode == GZ_READ ?
kusano fc6ab3
         O_RDONLY :
kusano fc6ab3
         (O_WRONLY | O_CREAT |
kusano fc6ab3
#ifdef O_EXCL
kusano fc6ab3
          (exclusive ? O_EXCL : 0) |
kusano fc6ab3
#endif
kusano fc6ab3
          (state->mode == GZ_WRITE ?
kusano fc6ab3
           O_TRUNC :
kusano fc6ab3
           O_APPEND)));
kusano fc6ab3
kusano fc6ab3
    /* open the file with the appropriate flags (or just use fd) */
kusano fc6ab3
    state->fd = fd > -1 ? fd : (
kusano fc6ab3
#ifdef _WIN32
kusano fc6ab3
        fd == -2 ? _wopen(path, oflag, 0666) :
kusano fc6ab3
#endif
kusano fc6ab3
        open((const char *)path, oflag, 0666));
kusano fc6ab3
    if (state->fd == -1) {
kusano fc6ab3
        free(state->path);
kusano fc6ab3
        free(state);
kusano fc6ab3
        return NULL;
kusano fc6ab3
    }
kusano fc6ab3
    if (state->mode == GZ_APPEND)
kusano fc6ab3
        state->mode = GZ_WRITE;         /* simplify later checks */
kusano fc6ab3
kusano fc6ab3
    /* save the current position for rewinding (only if reading) */
kusano fc6ab3
    if (state->mode == GZ_READ) {
kusano fc6ab3
        state->start = LSEEK(state->fd, 0, SEEK_CUR);
kusano fc6ab3
        if (state->start == -1) state->start = 0;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* initialize stream */
kusano fc6ab3
    gz_reset(state);
kusano fc6ab3
kusano fc6ab3
    /* return stream */
kusano fc6ab3
    return (gzFile)state;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
gzFile ZEXPORT gzopen(path, mode)
kusano fc6ab3
    const char *path;
kusano fc6ab3
    const char *mode;
kusano fc6ab3
{
kusano fc6ab3
    return gz_open(path, -1, mode);
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
gzFile ZEXPORT gzopen64(path, mode)
kusano fc6ab3
    const char *path;
kusano fc6ab3
    const char *mode;
kusano fc6ab3
{
kusano fc6ab3
    return gz_open(path, -1, mode);
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
gzFile ZEXPORT gzdopen(fd, mode)
kusano fc6ab3
    int fd;
kusano fc6ab3
    const char *mode;
kusano fc6ab3
{
kusano fc6ab3
    char *path;         /* identifier for error messages */
kusano fc6ab3
    gzFile gz;
kusano fc6ab3
kusano fc6ab3
    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
kusano fc6ab3
        return NULL;
kusano fc6ab3
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
kusano fc6ab3
    snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */</fd:%d>
kusano fc6ab3
#else
kusano fc6ab3
    sprintf(path, "<fd:%d>", fd);   /* for debugging */</fd:%d>
kusano fc6ab3
#endif
kusano fc6ab3
    gz = gz_open(path, fd, mode);
kusano fc6ab3
    free(path);
kusano fc6ab3
    return gz;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
#ifdef _WIN32
kusano fc6ab3
gzFile ZEXPORT gzopen_w(path, mode)
kusano fc6ab3
    const wchar_t *path;
kusano fc6ab3
    const char *mode;
kusano fc6ab3
{
kusano fc6ab3
    return gz_open(path, -2, mode);
kusano fc6ab3
}
kusano fc6ab3
#endif
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
int ZEXPORT gzbuffer(file, size)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
    unsigned size;
kusano fc6ab3
{
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure and check integrity */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return -1;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* make sure we haven't already allocated memory */
kusano fc6ab3
    if (state->size != 0)
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* check and set requested size */
kusano fc6ab3
    if (size < 2)
kusano fc6ab3
        size = 2;               /* need two bytes to check magic header */
kusano fc6ab3
    state->want = size;
kusano fc6ab3
    return 0;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
int ZEXPORT gzrewind(file)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
{
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return -1;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
kusano fc6ab3
    /* check that we're reading and that there's no error */
kusano fc6ab3
    if (state->mode != GZ_READ ||
kusano fc6ab3
            (state->err != Z_OK && state->err != Z_BUF_ERROR))
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* back up and start over */
kusano fc6ab3
    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
kusano fc6ab3
        return -1;
kusano fc6ab3
    gz_reset(state);
kusano fc6ab3
    return 0;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
z_off64_t ZEXPORT gzseek64(file, offset, whence)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
    z_off64_t offset;
kusano fc6ab3
    int whence;
kusano fc6ab3
{
kusano fc6ab3
    unsigned n;
kusano fc6ab3
    z_off64_t ret;
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure and check integrity */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return -1;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* check that there's no error */
kusano fc6ab3
    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* can only seek from start or relative to current position */
kusano fc6ab3
    if (whence != SEEK_SET && whence != SEEK_CUR)
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* normalize offset to a SEEK_CUR specification */
kusano fc6ab3
    if (whence == SEEK_SET)
kusano fc6ab3
        offset -= state->x.pos;
kusano fc6ab3
    else if (state->seek)
kusano fc6ab3
        offset += state->skip;
kusano fc6ab3
    state->seek = 0;
kusano fc6ab3
kusano fc6ab3
    /* if within raw area while reading, just go there */
kusano fc6ab3
    if (state->mode == GZ_READ && state->how == COPY &&
kusano fc6ab3
            state->x.pos + offset >= 0) {
kusano fc6ab3
        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
kusano fc6ab3
        if (ret == -1)
kusano fc6ab3
            return -1;
kusano fc6ab3
        state->x.have = 0;
kusano fc6ab3
        state->eof = 0;
kusano fc6ab3
        state->past = 0;
kusano fc6ab3
        state->seek = 0;
kusano fc6ab3
        gz_error(state, Z_OK, NULL);
kusano fc6ab3
        state->strm.avail_in = 0;
kusano fc6ab3
        state->x.pos += offset;
kusano fc6ab3
        return state->x.pos;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* calculate skip amount, rewinding if needed for back seek when reading */
kusano fc6ab3
    if (offset < 0) {
kusano fc6ab3
        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
kusano fc6ab3
            return -1;
kusano fc6ab3
        offset += state->x.pos;
kusano fc6ab3
        if (offset < 0)                     /* before start of file! */
kusano fc6ab3
            return -1;
kusano fc6ab3
        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
kusano fc6ab3
            return -1;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* if reading, skip what's in output buffer (one less gzgetc() check) */
kusano fc6ab3
    if (state->mode == GZ_READ) {
kusano fc6ab3
        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
kusano fc6ab3
            (unsigned)offset : state->x.have;
kusano fc6ab3
        state->x.have -= n;
kusano fc6ab3
        state->x.next += n;
kusano fc6ab3
        state->x.pos += n;
kusano fc6ab3
        offset -= n;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* request skip (if not zero) */
kusano fc6ab3
    if (offset) {
kusano fc6ab3
        state->seek = 1;
kusano fc6ab3
        state->skip = offset;
kusano fc6ab3
    }
kusano fc6ab3
    return state->x.pos + offset;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
z_off_t ZEXPORT gzseek(file, offset, whence)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
    z_off_t offset;
kusano fc6ab3
    int whence;
kusano fc6ab3
{
kusano fc6ab3
    z_off64_t ret;
kusano fc6ab3
kusano fc6ab3
    ret = gzseek64(file, (z_off64_t)offset, whence);
kusano fc6ab3
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
z_off64_t ZEXPORT gztell64(file)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
{
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure and check integrity */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return -1;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* return position */
kusano fc6ab3
    return state->x.pos + (state->seek ? state->skip : 0);
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
z_off_t ZEXPORT gztell(file)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
{
kusano fc6ab3
    z_off64_t ret;
kusano fc6ab3
kusano fc6ab3
    ret = gztell64(file);
kusano fc6ab3
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
z_off64_t ZEXPORT gzoffset64(file)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
{
kusano fc6ab3
    z_off64_t offset;
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure and check integrity */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return -1;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
kusano fc6ab3
        return -1;
kusano fc6ab3
kusano fc6ab3
    /* compute and return effective offset in file */
kusano fc6ab3
    offset = LSEEK(state->fd, 0, SEEK_CUR);
kusano fc6ab3
    if (offset == -1)
kusano fc6ab3
        return -1;
kusano fc6ab3
    if (state->mode == GZ_READ)             /* reading */
kusano fc6ab3
        offset -= state->strm.avail_in;     /* don't count buffered input */
kusano fc6ab3
    return offset;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
z_off_t ZEXPORT gzoffset(file)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
{
kusano fc6ab3
    z_off64_t ret;
kusano fc6ab3
kusano fc6ab3
    ret = gzoffset64(file);
kusano fc6ab3
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
int ZEXPORT gzeof(file)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
{
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure and check integrity */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return 0;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
kusano fc6ab3
        return 0;
kusano fc6ab3
kusano fc6ab3
    /* return end-of-file state */
kusano fc6ab3
    return state->mode == GZ_READ ? state->past : 0;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
const char * ZEXPORT gzerror(file, errnum)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
    int *errnum;
kusano fc6ab3
{
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure and check integrity */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return NULL;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
kusano fc6ab3
        return NULL;
kusano fc6ab3
kusano fc6ab3
    /* return error information */
kusano fc6ab3
    if (errnum != NULL)
kusano fc6ab3
        *errnum = state->err;
kusano fc6ab3
    return state->err == Z_MEM_ERROR ? "out of memory" :
kusano fc6ab3
                                       (state->msg == NULL ? "" : state->msg);
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* -- see zlib.h -- */
kusano fc6ab3
void ZEXPORT gzclearerr(file)
kusano fc6ab3
    gzFile file;
kusano fc6ab3
{
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
kusano fc6ab3
    /* get internal structure and check integrity */
kusano fc6ab3
    if (file == NULL)
kusano fc6ab3
        return;
kusano fc6ab3
    state = (gz_statep)file;
kusano fc6ab3
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
kusano fc6ab3
        return;
kusano fc6ab3
kusano fc6ab3
    /* clear error and end-of-file */
kusano fc6ab3
    if (state->mode == GZ_READ) {
kusano fc6ab3
        state->eof = 0;
kusano fc6ab3
        state->past = 0;
kusano fc6ab3
    }
kusano fc6ab3
    gz_error(state, Z_OK, NULL);
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* Create an error message in allocated memory and set state->err and
kusano fc6ab3
   state->msg accordingly.  Free any previous error message already there.  Do
kusano fc6ab3
   not try to free or allocate space if the error is Z_MEM_ERROR (out of
kusano fc6ab3
   memory).  Simply save the error message as a static string.  If there is an
kusano fc6ab3
   allocation failure constructing the error message, then convert the error to
kusano fc6ab3
   out of memory. */
kusano fc6ab3
void ZLIB_INTERNAL gz_error(state, err, msg)
kusano fc6ab3
    gz_statep state;
kusano fc6ab3
    int err;
kusano fc6ab3
    const char *msg;
kusano fc6ab3
{
kusano fc6ab3
    /* free previously allocated message and clear */
kusano fc6ab3
    if (state->msg != NULL) {
kusano fc6ab3
        if (state->err != Z_MEM_ERROR)
kusano fc6ab3
            free(state->msg);
kusano fc6ab3
        state->msg = NULL;
kusano fc6ab3
    }
kusano fc6ab3
kusano fc6ab3
    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
kusano fc6ab3
    if (err != Z_OK && err != Z_BUF_ERROR)
kusano fc6ab3
        state->x.have = 0;
kusano fc6ab3
kusano fc6ab3
    /* set error code, and if no message, then done */
kusano fc6ab3
    state->err = err;
kusano fc6ab3
    if (msg == NULL)
kusano fc6ab3
        return;
kusano fc6ab3
kusano fc6ab3
    /* for an out of memory error, return literal string when requested */
kusano fc6ab3
    if (err == Z_MEM_ERROR)
kusano fc6ab3
        return;
kusano fc6ab3
kusano fc6ab3
    /* construct error message with path */
kusano fc6ab3
    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
kusano fc6ab3
            NULL) {
kusano fc6ab3
        state->err = Z_MEM_ERROR;
kusano fc6ab3
        return;
kusano fc6ab3
    }
kusano fc6ab3
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
kusano fc6ab3
    snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
kusano fc6ab3
             "%s%s%s", state->path, ": ", msg);
kusano fc6ab3
#else
kusano fc6ab3
    strcpy(state->msg, state->path);
kusano fc6ab3
    strcat(state->msg, ": ");
kusano fc6ab3
    strcat(state->msg, msg);
kusano fc6ab3
#endif
kusano fc6ab3
    return;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
#ifndef INT_MAX
kusano fc6ab3
/* portably return maximum value for an int (when limits.h presumed not
kusano fc6ab3
   available) -- we need to do this to cover cases where 2's complement not
kusano fc6ab3
   used, since C standard permits 1's complement and sign-bit representations,
kusano fc6ab3
   otherwise we could just use ((unsigned)-1) >> 1 */
kusano fc6ab3
unsigned ZLIB_INTERNAL gz_intmax()
kusano fc6ab3
{
kusano fc6ab3
    unsigned p, q;
kusano fc6ab3
kusano fc6ab3
    p = 1;
kusano fc6ab3
    do {
kusano fc6ab3
        q = p;
kusano fc6ab3
        p <<= 1;
kusano fc6ab3
        p++;
kusano fc6ab3
    } while (p > q);
kusano fc6ab3
    return q >> 1;
kusano fc6ab3
}
kusano fc6ab3
#endif