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