117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* gzlib.c -- zlib functions common to reading and writing gzip files
217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner * For conditions of distribution and use, see copyright notice in zlib.h
417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner */
517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#include "gzguts.h"
717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#if defined(_WIN32) && !defined(__BORLANDC__)
917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#  define LSEEK _lseeki64
1017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#else
1117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
1217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#  define LSEEK lseek64
1317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#else
1417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#  define LSEEK lseek
1517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
1617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
1717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
1817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* Local functions */
1917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerlocal void gz_reset OF((gz_statep));
2017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerlocal gzFile gz_open OF((const void *, int, const char *));
2117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
2217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#if defined UNDER_CE
2317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
2417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* Map the Windows error number in ERROR to a locale-dependent error message
2517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   string and return a pointer to it.  Typically, the values for ERROR come
2617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   from GetLastError.
2717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
2817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   The string pointed to shall not be modified by the application, but may be
2917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   overwritten by a subsequent call to gz_strwinerror
3017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
3117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   The gz_strwinerror function does not change the current setting of
3217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   GetLastError. */
3317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerchar ZLIB_INTERNAL *gz_strwinerror (error)
3417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner     DWORD error;
3517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
3617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    static char buf[1024];
3717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
3817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    wchar_t *msgbuf;
3917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    DWORD lasterr = GetLastError();
4017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
4117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
4217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        NULL,
4317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        error,
4417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        0, /* Default language */
4517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        (LPVOID)&msgbuf,
4617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        0,
4717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        NULL);
4817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (chars != 0) {
4917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        /* If there is an \r\n appended, zap it.  */
5017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (chars >= 2
5117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
5217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            chars -= 2;
5317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            msgbuf[chars] = 0;
5417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        }
5517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
5617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (chars > sizeof (buf) - 1) {
5717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            chars = sizeof (buf) - 1;
5817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            msgbuf[chars] = 0;
5917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        }
6017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
6117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        wcstombs(buf, msgbuf, chars + 1);
6217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        LocalFree(msgbuf);
6317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
6417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    else {
6517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        sprintf(buf, "unknown win32 error (%ld)", error);
6617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
6717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
6817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    SetLastError(lasterr);
6917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return buf;
7017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
7117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
7217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif /* UNDER_CE */
7317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
7417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* Reset gzip file state */
7517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerlocal void gz_reset(state)
7617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
7717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
7817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->x.have = 0;              /* no output data available */
7917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_READ) {   /* for reading ... */
8017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->eof = 0;             /* not at end of file */
8117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->past = 0;            /* have not read past end yet */
8217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->how = LOOK;          /* look for gzip header */
8317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
8417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->seek = 0;                /* no seek request pending */
8517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_error(state, Z_OK, NULL);    /* clear error */
8617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->x.pos = 0;               /* no uncompressed data yet */
8717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->strm.avail_in = 0;       /* no input data yet */
8817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
8917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
9017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* Open a gzip file either by name or file descriptor. */
9117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerlocal gzFile gz_open(path, fd, mode)
9217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const void *path;
9317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int fd;
9417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *mode;
9517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
9617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
9717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    size_t len;
9817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int oflag;
9917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_CLOEXEC
10017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int cloexec = 0;
10117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
10217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_EXCL
10317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int exclusive = 0;
10417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
10517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
10617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* check input */
10717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (path == NULL)
10817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
10917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
11017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* allocate gzFile structure to return */
11117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)malloc(sizeof(gz_state));
11217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state == NULL)
11317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
11417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->size = 0;            /* no buffers allocated yet */
11517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->want = GZBUFSIZE;    /* requested buffer size */
11617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->msg = NULL;          /* no error message yet */
11717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
11817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* interpret mode */
11917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->mode = GZ_NONE;
12017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->level = Z_DEFAULT_COMPRESSION;
12117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->strategy = Z_DEFAULT_STRATEGY;
12217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->direct = 0;
12317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    while (*mode) {
12417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (*mode >= '0' && *mode <= '9')
12517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            state->level = *mode - '0';
12617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        else
12717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            switch (*mode) {
12817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'r':
12917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->mode = GZ_READ;
13017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
13117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifndef NO_GZCOMPRESS
13217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'w':
13317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->mode = GZ_WRITE;
13417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
13517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'a':
13617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->mode = GZ_APPEND;
13717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
13817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
13917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case '+':       /* can't read and write at the same time */
14017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                free(state);
14117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                return NULL;
14217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'b':       /* ignore -- will request binary anyway */
14317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
14417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_CLOEXEC
14517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'e':
14617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                cloexec = 1;
14717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
14817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
14917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_EXCL
15017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'x':
15117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                exclusive = 1;
15217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
15317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
15417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'f':
15517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->strategy = Z_FILTERED;
15617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
15717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'h':
15817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->strategy = Z_HUFFMAN_ONLY;
15917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
16017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'R':
16117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->strategy = Z_RLE;
16217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
16317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'F':
16417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->strategy = Z_FIXED;
16517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
16617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            case 'T':
16717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                state->direct = 1;
16817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                break;
16917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            default:        /* could consider as an error, but just ignore */
17017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                ;
17117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            }
17217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        mode++;
17317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
17417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
17517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* must provide an "r", "w", or "a" */
17617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_NONE) {
17717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        free(state);
17817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
17917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
18017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
18117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* can't force transparent read */
18217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_READ) {
18317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (state->direct) {
18417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            free(state);
18517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            return NULL;
18617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        }
18717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->direct = 1;      /* for empty file */
18817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
18917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
19017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* save the path name for error messages */
19117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef _WIN32
19217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (fd == -2) {
19317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        len = wcstombs(NULL, path, 0);
19417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (len == (size_t)-1)
19517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            len = 0;
19617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
19717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    else
19817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
19917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        len = strlen((const char *)path);
20017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->path = (char *)malloc(len + 1);
20117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->path == NULL) {
20217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        free(state);
20317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
20417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
20517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef _WIN32
20617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (fd == -2)
20717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (len)
20817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            wcstombs(state->path, path, len + 1);
20917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        else
21017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            *(state->path) = 0;
21117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    else
21217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
21317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
21417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        snprintf(state->path, len + 1, "%s", (const char *)path);
21517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#else
21617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        strcpy(state->path, path);
21717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
21817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
21917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* compute the flags for open() */
22017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    oflag =
22117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_LARGEFILE
22217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        O_LARGEFILE |
22317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
22417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_BINARY
22517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        O_BINARY |
22617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
22717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_CLOEXEC
22817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        (cloexec ? O_CLOEXEC : 0) |
22917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
23017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        (state->mode == GZ_READ ?
23117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner         O_RDONLY :
23217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner         (O_WRONLY | O_CREAT |
23317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef O_EXCL
23417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner          (exclusive ? O_EXCL : 0) |
23517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
23617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner          (state->mode == GZ_WRITE ?
23717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner           O_TRUNC :
23817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner           O_APPEND)));
23917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
24017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* open the file with the appropriate flags (or just use fd) */
24117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->fd = fd > -1 ? fd : (
24217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef _WIN32
24317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        fd == -2 ? _wopen(path, oflag, 0666) :
24417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
24517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        open((const char *)path, oflag, 0666));
24617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->fd == -1) {
24717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        free(state->path);
24817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        free(state);
24917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
25017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
25117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_APPEND)
25217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->mode = GZ_WRITE;         /* simplify later checks */
25317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
25417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* save the current position for rewinding (only if reading) */
25517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_READ) {
25617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->start = LSEEK(state->fd, 0, SEEK_CUR);
25717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (state->start == -1) state->start = 0;
25817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
25917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
26017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* initialize stream */
26117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_reset(state);
26217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
26317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* return stream */
26417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return (gzFile)state;
26517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
26617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
26717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
26817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' TurnergzFile ZEXPORT gzopen(path, mode)
26917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *path;
27017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *mode;
27117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
27217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return gz_open(path, -1, mode);
27317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
27417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
27517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
27617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' TurnergzFile ZEXPORT gzopen64(path, mode)
27717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *path;
27817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *mode;
27917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
28017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return gz_open(path, -1, mode);
28117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
28217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
28317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
28417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' TurnergzFile ZEXPORT gzdopen(fd, mode)
28517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int fd;
28617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *mode;
28717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
28817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    char *path;         /* identifier for error messages */
28917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile gz;
29017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
29117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
29217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
29317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
29417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
29517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#else
29617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    sprintf(path, "<fd:%d>", fd);   /* for debugging */
29717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
29817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz = gz_open(path, fd, mode);
29917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    free(path);
30017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return gz;
30117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
30217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
30317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
30417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifdef _WIN32
30517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' TurnergzFile ZEXPORT gzopen_w(path, mode)
30617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const wchar_t *path;
30717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *mode;
30817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
30917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return gz_open(path, -2, mode);
31017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
31117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
31217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
31317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
31417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerint ZEXPORT gzbuffer(file, size)
31517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
31617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    unsigned size;
31717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
31817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
31917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
32017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure and check integrity */
32117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
32217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
32317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
32417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
32517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
32617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
32717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* make sure we haven't already allocated memory */
32817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->size != 0)
32917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
33017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
33117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* check and set requested size */
33217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (size < 2)
33317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        size = 2;               /* need two bytes to check magic header */
33417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->want = size;
33517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return 0;
33617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
33717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
33817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
33917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerint ZEXPORT gzrewind(file)
34017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
34117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
34217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
34317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
34417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure */
34517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
34617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
34717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
34817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
34917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* check that we're reading and that there's no error */
35017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ ||
35117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            (state->err != Z_OK && state->err != Z_BUF_ERROR))
35217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
35317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
35417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* back up and start over */
35517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
35617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
35717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_reset(state);
35817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return 0;
35917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
36017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
36117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
36217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerz_off64_t ZEXPORT gzseek64(file, offset, whence)
36317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
36417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    z_off64_t offset;
36517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int whence;
36617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
36717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    unsigned n;
36817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    z_off64_t ret;
36917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
37017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
37117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure and check integrity */
37217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
37317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
37417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
37517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
37617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
37717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
37817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* check that there's no error */
37917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
38017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
38117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
38217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* can only seek from start or relative to current position */
38317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (whence != SEEK_SET && whence != SEEK_CUR)
38417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
38517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
38617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* normalize offset to a SEEK_CUR specification */
38717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (whence == SEEK_SET)
38817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        offset -= state->x.pos;
38917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    else if (state->seek)
39017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        offset += state->skip;
39117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->seek = 0;
39217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
39317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* if within raw area while reading, just go there */
39417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_READ && state->how == COPY &&
39517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            state->x.pos + offset >= 0) {
39617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
39717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (ret == -1)
39817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            return -1;
39917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->x.have = 0;
40017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->eof = 0;
40117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->past = 0;
40217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->seek = 0;
40317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        gz_error(state, Z_OK, NULL);
40417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->strm.avail_in = 0;
40517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->x.pos += offset;
40617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return state->x.pos;
40717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
40817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
40917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* calculate skip amount, rewinding if needed for back seek when reading */
41017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (offset < 0) {
41117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
41217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            return -1;
41317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        offset += state->x.pos;
41417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (offset < 0)                     /* before start of file! */
41517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            return -1;
41617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
41717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            return -1;
41817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
41917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
42017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* if reading, skip what's in output buffer (one less gzgetc() check) */
42117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_READ) {
42217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
42317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            (unsigned)offset : state->x.have;
42417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->x.have -= n;
42517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->x.next += n;
42617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->x.pos += n;
42717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        offset -= n;
42817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
42917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
43017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* request skip (if not zero) */
43117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (offset) {
43217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->seek = 1;
43317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->skip = offset;
43417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
43517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return state->x.pos + offset;
43617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
43717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
43817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
43917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerz_off_t ZEXPORT gzseek(file, offset, whence)
44017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
44117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    z_off_t offset;
44217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int whence;
44317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
44417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    z_off64_t ret;
44517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
44617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    ret = gzseek64(file, (z_off64_t)offset, whence);
44717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
44817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
44917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
45017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
45117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerz_off64_t ZEXPORT gztell64(file)
45217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
45317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
45417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
45517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
45617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure and check integrity */
45717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
45817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
45917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
46017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
46117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
46217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
46317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* return position */
46417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return state->x.pos + (state->seek ? state->skip : 0);
46517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
46617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
46717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
46817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerz_off_t ZEXPORT gztell(file)
46917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
47017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
47117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    z_off64_t ret;
47217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
47317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    ret = gztell64(file);
47417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
47517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
47617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
47717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
47817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerz_off64_t ZEXPORT gzoffset64(file)
47917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
48017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
48117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    z_off64_t offset;
48217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
48317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
48417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure and check integrity */
48517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
48617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
48717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
48817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
48917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
49017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
49117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* compute and return effective offset in file */
49217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    offset = LSEEK(state->fd, 0, SEEK_CUR);
49317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (offset == -1)
49417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return -1;
49517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_READ)             /* reading */
49617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        offset -= state->strm.avail_in;     /* don't count buffered input */
49717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return offset;
49817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
49917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
50017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
50117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerz_off_t ZEXPORT gzoffset(file)
50217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
50317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
50417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    z_off64_t ret;
50517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
50617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    ret = gzoffset64(file);
50717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
50817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
50917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
51017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
51117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerint ZEXPORT gzeof(file)
51217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
51317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
51417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
51517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
51617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure and check integrity */
51717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
51817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return 0;
51917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
52017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
52117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return 0;
52217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
52317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* return end-of-file state */
52417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return state->mode == GZ_READ ? state->past : 0;
52517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
52617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
52717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
52817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerconst char * ZEXPORT gzerror(file, errnum)
52917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
53017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int *errnum;
53117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
53217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
53317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
53417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure and check integrity */
53517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
53617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
53717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
53817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
53917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return NULL;
54017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
54117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* return error information */
54217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (errnum != NULL)
54317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        *errnum = state->err;
54417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return state->err == Z_MEM_ERROR ? "out of memory" :
54517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner                                       (state->msg == NULL ? "" : state->msg);
54617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
54717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
54817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* -- see zlib.h -- */
54917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnervoid ZEXPORT gzclearerr(file)
55017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gzFile file;
55117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
55217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
55317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
55417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* get internal structure and check integrity */
55517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (file == NULL)
55617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return;
55717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state = (gz_statep)file;
55817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
55917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return;
56017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
56117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* clear error and end-of-file */
56217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->mode == GZ_READ) {
56317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->eof = 0;
56417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->past = 0;
56517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
56617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_error(state, Z_OK, NULL);
56717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
56817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
56917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* Create an error message in allocated memory and set state->err and
57017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   state->msg accordingly.  Free any previous error message already there.  Do
57117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   not try to free or allocate space if the error is Z_MEM_ERROR (out of
57217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   memory).  Simply save the error message as a static string.  If there is an
57317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   allocation failure constructing the error message, then convert the error to
57417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   out of memory. */
57517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnervoid ZLIB_INTERNAL gz_error(state, err, msg)
57617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    gz_statep state;
57717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    int err;
57817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    const char *msg;
57917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
58017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* free previously allocated message and clear */
58117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (state->msg != NULL) {
58217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        if (state->err != Z_MEM_ERROR)
58317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            free(state->msg);
58417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->msg = NULL;
58517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
58617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
58717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
58817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (err != Z_OK && err != Z_BUF_ERROR)
58917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->x.have = 0;
59017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
59117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* set error code, and if no message, then done */
59217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    state->err = err;
59317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (msg == NULL)
59417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return;
59517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
59617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* for an out of memory error, return literal string when requested */
59717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if (err == Z_MEM_ERROR)
59817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return;
59917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
60017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    /* construct error message with path */
60117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
60217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner            NULL) {
60317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        state->err = Z_MEM_ERROR;
60417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        return;
60517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    }
60617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
60717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
60817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner             "%s%s%s", state->path, ": ", msg);
60917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#else
61017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    strcpy(state->msg, state->path);
61117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    strcat(state->msg, ": ");
61217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    strcat(state->msg, msg);
61317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
61417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return;
61517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
61617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
61717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#ifndef INT_MAX
61817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner/* portably return maximum value for an int (when limits.h presumed not
61917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   available) -- we need to do this to cover cases where 2's complement not
62017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   used, since C standard permits 1's complement and sign-bit representations,
62117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner   otherwise we could just use ((unsigned)-1) >> 1 */
62217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turnerunsigned ZLIB_INTERNAL gz_intmax()
62317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner{
62417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    unsigned p, q;
62517b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner
62617b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    p = 1;
62717b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    do {
62817b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        q = p;
62917b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        p <<= 1;
63017b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner        p++;
63117b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    } while (p > q);
63217b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner    return q >> 1;
63317b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner}
63417b20e6f38ad2263e47a6884c4f68ce9773d8b29David 'Digit' Turner#endif
635