136f395ceStb /* gzlib.c -- zlib functions common to reading and writing gzip files
2d5e7bdb5Stb * Copyright (C) 2004-2024 Mark Adler
336f395ceStb * For conditions of distribution and use, see copyright notice in zlib.h
436f395ceStb */
536f395ceStb
636f395ceStb #include "gzguts.h"
736f395ceStb
8*d62e7792Stb #if defined(__DJGPP__)
9312b32e0Stb # define LSEEK llseek
10*d62e7792Stb #elif defined(_WIN32) && !defined(__BORLANDC__) && !defined(UNDER_CE)
1136f395ceStb # define LSEEK _lseeki64
12312b32e0Stb #elif defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
1336f395ceStb # define LSEEK lseek64
1436f395ceStb #else
1536f395ceStb # define LSEEK lseek
1636f395ceStb #endif
1736f395ceStb
1836f395ceStb #if defined UNDER_CE
1936f395ceStb
2036f395ceStb /* Map the Windows error number in ERROR to a locale-dependent error message
2136f395ceStb string and return a pointer to it. Typically, the values for ERROR come
2236f395ceStb from GetLastError.
2336f395ceStb
2436f395ceStb The string pointed to shall not be modified by the application, but may be
2536f395ceStb overwritten by a subsequent call to gz_strwinerror
2636f395ceStb
2736f395ceStb The gz_strwinerror function does not change the current setting of
2836f395ceStb GetLastError. */
gz_strwinerror(DWORD error)29a04ea15dStb char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
3036f395ceStb static char buf[1024];
3136f395ceStb
3236f395ceStb wchar_t *msgbuf;
3336f395ceStb DWORD lasterr = GetLastError();
3436f395ceStb DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
3536f395ceStb | FORMAT_MESSAGE_ALLOCATE_BUFFER,
3636f395ceStb NULL,
3736f395ceStb error,
3836f395ceStb 0, /* Default language */
3936f395ceStb (LPVOID)&msgbuf,
4036f395ceStb 0,
4136f395ceStb NULL);
4236f395ceStb if (chars != 0) {
4336f395ceStb /* If there is an \r\n appended, zap it. */
4436f395ceStb if (chars >= 2
4536f395ceStb && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
4636f395ceStb chars -= 2;
4736f395ceStb msgbuf[chars] = 0;
4836f395ceStb }
4936f395ceStb
5036f395ceStb if (chars > sizeof (buf) - 1) {
5136f395ceStb chars = sizeof (buf) - 1;
5236f395ceStb msgbuf[chars] = 0;
5336f395ceStb }
5436f395ceStb
55312b32e0Stb wcstombs(buf, msgbuf, chars + 1); // assumes buf is big enough
5636f395ceStb LocalFree(msgbuf);
5736f395ceStb }
5836f395ceStb else {
5936f395ceStb sprintf(buf, "unknown win32 error (%ld)", error);
6036f395ceStb }
6136f395ceStb
6236f395ceStb SetLastError(lasterr);
6336f395ceStb return buf;
6436f395ceStb }
6536f395ceStb
6636f395ceStb #endif /* UNDER_CE */
6736f395ceStb
6836f395ceStb /* Reset gzip file state */
gz_reset(gz_statep state)69a04ea15dStb local void gz_reset(gz_statep state) {
7036f395ceStb state->x.have = 0; /* no output data available */
7136f395ceStb if (state->mode == GZ_READ) { /* for reading ... */
7236f395ceStb state->eof = 0; /* not at end of file */
7336f395ceStb state->past = 0; /* have not read past end yet */
7436f395ceStb state->how = LOOK; /* look for gzip header */
7536f395ceStb }
76703d4924Stb else /* for writing ... */
77703d4924Stb state->reset = 0; /* no deflateReset pending */
7836f395ceStb state->seek = 0; /* no seek request pending */
7936f395ceStb gz_error(state, Z_OK, NULL); /* clear error */
8036f395ceStb state->x.pos = 0; /* no uncompressed data yet */
8136f395ceStb state->strm.avail_in = 0; /* no input data yet */
8236f395ceStb }
8336f395ceStb
8436f395ceStb /* Open a gzip file either by name or file descriptor. */
gz_open(const void * path,int fd,const char * mode)85a04ea15dStb local gzFile gz_open(const void *path, int fd, const char *mode) {
8636f395ceStb gz_statep state;
8736f395ceStb z_size_t len;
8836f395ceStb int oflag;
8936f395ceStb #ifdef O_CLOEXEC
9036f395ceStb int cloexec = 0;
9136f395ceStb #endif
9236f395ceStb #ifdef O_EXCL
9336f395ceStb int exclusive = 0;
9436f395ceStb #endif
9536f395ceStb
9636f395ceStb /* check input */
9736f395ceStb if (path == NULL)
9836f395ceStb return NULL;
9936f395ceStb
10036f395ceStb /* allocate gzFile structure to return */
10136f395ceStb state = (gz_statep)malloc(sizeof(gz_state));
10236f395ceStb if (state == NULL)
10336f395ceStb return NULL;
10436f395ceStb state->size = 0; /* no buffers allocated yet */
10536f395ceStb state->want = GZBUFSIZE; /* requested buffer size */
10636f395ceStb state->msg = NULL; /* no error message yet */
10736f395ceStb
10836f395ceStb /* interpret mode */
10936f395ceStb state->mode = GZ_NONE;
11036f395ceStb state->level = Z_DEFAULT_COMPRESSION;
11136f395ceStb state->strategy = Z_DEFAULT_STRATEGY;
11236f395ceStb state->direct = 0;
11336f395ceStb while (*mode) {
11436f395ceStb if (*mode >= '0' && *mode <= '9')
11536f395ceStb state->level = *mode - '0';
11636f395ceStb else
11736f395ceStb switch (*mode) {
11836f395ceStb case 'r':
11936f395ceStb state->mode = GZ_READ;
12036f395ceStb break;
12136f395ceStb #ifndef NO_GZCOMPRESS
12236f395ceStb case 'w':
12336f395ceStb state->mode = GZ_WRITE;
12436f395ceStb break;
12536f395ceStb case 'a':
12636f395ceStb state->mode = GZ_APPEND;
12736f395ceStb break;
12836f395ceStb #endif
12936f395ceStb case '+': /* can't read and write at the same time */
13036f395ceStb free(state);
13136f395ceStb return NULL;
13236f395ceStb case 'b': /* ignore -- will request binary anyway */
13336f395ceStb break;
13436f395ceStb #ifdef O_CLOEXEC
13536f395ceStb case 'e':
13636f395ceStb cloexec = 1;
13736f395ceStb break;
13836f395ceStb #endif
13936f395ceStb #ifdef O_EXCL
14036f395ceStb case 'x':
14136f395ceStb exclusive = 1;
14236f395ceStb break;
14336f395ceStb #endif
14436f395ceStb case 'f':
14536f395ceStb state->strategy = Z_FILTERED;
14636f395ceStb break;
14736f395ceStb case 'h':
14836f395ceStb state->strategy = Z_HUFFMAN_ONLY;
14936f395ceStb break;
15036f395ceStb case 'R':
15136f395ceStb state->strategy = Z_RLE;
15236f395ceStb break;
15336f395ceStb case 'F':
15436f395ceStb state->strategy = Z_FIXED;
15536f395ceStb break;
15636f395ceStb case 'T':
15736f395ceStb state->direct = 1;
15836f395ceStb break;
15936f395ceStb default: /* could consider as an error, but just ignore */
16036f395ceStb ;
16136f395ceStb }
16236f395ceStb mode++;
16336f395ceStb }
16436f395ceStb
16536f395ceStb /* must provide an "r", "w", or "a" */
16636f395ceStb if (state->mode == GZ_NONE) {
16736f395ceStb free(state);
16836f395ceStb return NULL;
16936f395ceStb }
17036f395ceStb
17136f395ceStb /* can't force transparent read */
17236f395ceStb if (state->mode == GZ_READ) {
17336f395ceStb if (state->direct) {
17436f395ceStb free(state);
17536f395ceStb return NULL;
17636f395ceStb }
17736f395ceStb state->direct = 1; /* for empty file */
17836f395ceStb }
17936f395ceStb
18036f395ceStb /* save the path name for error messages */
18136f395ceStb #ifdef WIDECHAR
182312b32e0Stb if (fd == -2)
183312b32e0Stb len = wcstombs(NULL, path, 0);
18436f395ceStb else
18536f395ceStb #endif
18636f395ceStb len = strlen((const char *)path);
18736f395ceStb state->path = (char *)malloc(len + 1);
18836f395ceStb if (state->path == NULL) {
18936f395ceStb free(state);
19036f395ceStb return NULL;
19136f395ceStb }
19236f395ceStb #ifdef WIDECHAR
193312b32e0Stb if (fd == -2) {
19436f395ceStb if (len)
195312b32e0Stb wcstombs(state->path, path, len + 1);
19636f395ceStb else
19736f395ceStb *(state->path) = 0;
198312b32e0Stb }
19936f395ceStb else
20036f395ceStb #endif
201312b32e0Stb {
20236f395ceStb #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
20336f395ceStb (void)snprintf(state->path, len + 1, "%s", (const char *)path);
20436f395ceStb #else
20536f395ceStb strcpy(state->path, path);
20636f395ceStb #endif
207312b32e0Stb }
20836f395ceStb
20936f395ceStb /* compute the flags for open() */
21036f395ceStb oflag =
21136f395ceStb #ifdef O_LARGEFILE
21236f395ceStb O_LARGEFILE |
21336f395ceStb #endif
21436f395ceStb #ifdef O_BINARY
21536f395ceStb O_BINARY |
21636f395ceStb #endif
21736f395ceStb #ifdef O_CLOEXEC
21836f395ceStb (cloexec ? O_CLOEXEC : 0) |
21936f395ceStb #endif
22036f395ceStb (state->mode == GZ_READ ?
22136f395ceStb O_RDONLY :
22236f395ceStb (O_WRONLY | O_CREAT |
22336f395ceStb #ifdef O_EXCL
22436f395ceStb (exclusive ? O_EXCL : 0) |
22536f395ceStb #endif
22636f395ceStb (state->mode == GZ_WRITE ?
22736f395ceStb O_TRUNC :
22836f395ceStb O_APPEND)));
22936f395ceStb
23036f395ceStb /* open the file with the appropriate flags (or just use fd) */
23184324f44Stb if (fd == -1)
23284324f44Stb state->fd = open((const char *)path, oflag, 0666);
23336f395ceStb #ifdef WIDECHAR
23484324f44Stb else if (fd == -2)
235312b32e0Stb state->fd = _wopen(path, oflag, _S_IREAD | _S_IWRITE);
23636f395ceStb #endif
23784324f44Stb else
23884324f44Stb state->fd = fd;
23936f395ceStb if (state->fd == -1) {
24036f395ceStb free(state->path);
24136f395ceStb free(state);
24236f395ceStb return NULL;
24336f395ceStb }
24436f395ceStb if (state->mode == GZ_APPEND) {
24536f395ceStb LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
24636f395ceStb state->mode = GZ_WRITE; /* simplify later checks */
24736f395ceStb }
24836f395ceStb
24936f395ceStb /* save the current position for rewinding (only if reading) */
25036f395ceStb if (state->mode == GZ_READ) {
25136f395ceStb state->start = LSEEK(state->fd, 0, SEEK_CUR);
25236f395ceStb if (state->start == -1) state->start = 0;
25336f395ceStb }
25436f395ceStb
25536f395ceStb /* initialize stream */
25636f395ceStb gz_reset(state);
25736f395ceStb
25836f395ceStb /* return stream */
25936f395ceStb return (gzFile)state;
26036f395ceStb }
26136f395ceStb
26236f395ceStb /* -- see zlib.h -- */
gzopen(const char * path,const char * mode)263a04ea15dStb gzFile ZEXPORT gzopen(const char *path, const char *mode) {
26436f395ceStb return gz_open(path, -1, mode);
26536f395ceStb }
26636f395ceStb
26736f395ceStb /* -- see zlib.h -- */
gzopen64(const char * path,const char * mode)268a04ea15dStb gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
26936f395ceStb return gz_open(path, -1, mode);
27036f395ceStb }
27136f395ceStb
27236f395ceStb /* -- see zlib.h -- */
gzdopen(int fd,const char * mode)273a04ea15dStb gzFile ZEXPORT gzdopen(int fd, const char *mode) {
27436f395ceStb char *path; /* identifier for error messages */
27536f395ceStb gzFile gz;
27636f395ceStb
27736f395ceStb if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
27836f395ceStb return NULL;
27936f395ceStb #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
28036f395ceStb (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
28136f395ceStb #else
28236f395ceStb sprintf(path, "<fd:%d>", fd); /* for debugging */
28336f395ceStb #endif
28436f395ceStb gz = gz_open(path, fd, mode);
28536f395ceStb free(path);
28636f395ceStb return gz;
28736f395ceStb }
28836f395ceStb
28936f395ceStb /* -- see zlib.h -- */
29036f395ceStb #ifdef WIDECHAR
gzopen_w(const wchar_t * path,const char * mode)291a04ea15dStb gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
29236f395ceStb return gz_open(path, -2, mode);
29336f395ceStb }
29436f395ceStb #endif
29536f395ceStb
29636f395ceStb /* -- see zlib.h -- */
gzbuffer(gzFile file,unsigned size)297a04ea15dStb int ZEXPORT gzbuffer(gzFile file, unsigned size) {
29836f395ceStb gz_statep state;
29936f395ceStb
30036f395ceStb /* get internal structure and check integrity */
30136f395ceStb if (file == NULL)
30236f395ceStb return -1;
30336f395ceStb state = (gz_statep)file;
30436f395ceStb if (state->mode != GZ_READ && state->mode != GZ_WRITE)
30536f395ceStb return -1;
30636f395ceStb
30736f395ceStb /* make sure we haven't already allocated memory */
30836f395ceStb if (state->size != 0)
30936f395ceStb return -1;
31036f395ceStb
31136f395ceStb /* check and set requested size */
31236f395ceStb if ((size << 1) < size)
31336f395ceStb return -1; /* need to be able to double it */
314cb4f93b0Stb if (size < 8)
315cb4f93b0Stb size = 8; /* needed to behave well with flushing */
31636f395ceStb state->want = size;
31736f395ceStb return 0;
31836f395ceStb }
31936f395ceStb
32036f395ceStb /* -- see zlib.h -- */
gzrewind(gzFile file)321a04ea15dStb int ZEXPORT gzrewind(gzFile file) {
32236f395ceStb gz_statep state;
32336f395ceStb
32436f395ceStb /* get internal structure */
32536f395ceStb if (file == NULL)
32636f395ceStb return -1;
32736f395ceStb state = (gz_statep)file;
32836f395ceStb
32936f395ceStb /* check that we're reading and that there's no error */
33036f395ceStb if (state->mode != GZ_READ ||
33136f395ceStb (state->err != Z_OK && state->err != Z_BUF_ERROR))
33236f395ceStb return -1;
33336f395ceStb
33436f395ceStb /* back up and start over */
33536f395ceStb if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
33636f395ceStb return -1;
33736f395ceStb gz_reset(state);
33836f395ceStb return 0;
33936f395ceStb }
34036f395ceStb
34136f395ceStb /* -- see zlib.h -- */
gzseek64(gzFile file,z_off64_t offset,int whence)342a04ea15dStb z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
34336f395ceStb unsigned n;
34436f395ceStb z_off64_t ret;
34536f395ceStb gz_statep state;
34636f395ceStb
34736f395ceStb /* get internal structure and check integrity */
34836f395ceStb if (file == NULL)
34936f395ceStb return -1;
35036f395ceStb state = (gz_statep)file;
35136f395ceStb if (state->mode != GZ_READ && state->mode != GZ_WRITE)
35236f395ceStb return -1;
35336f395ceStb
35436f395ceStb /* check that there's no error */
35536f395ceStb if (state->err != Z_OK && state->err != Z_BUF_ERROR)
35636f395ceStb return -1;
35736f395ceStb
35836f395ceStb /* can only seek from start or relative to current position */
35936f395ceStb if (whence != SEEK_SET && whence != SEEK_CUR)
36036f395ceStb return -1;
36136f395ceStb
36236f395ceStb /* normalize offset to a SEEK_CUR specification */
36336f395ceStb if (whence == SEEK_SET)
36436f395ceStb offset -= state->x.pos;
36536f395ceStb else if (state->seek)
36636f395ceStb offset += state->skip;
36736f395ceStb state->seek = 0;
36836f395ceStb
36936f395ceStb /* if within raw area while reading, just go there */
37036f395ceStb if (state->mode == GZ_READ && state->how == COPY &&
37136f395ceStb state->x.pos + offset >= 0) {
372703d4924Stb ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
37336f395ceStb if (ret == -1)
37436f395ceStb return -1;
37536f395ceStb state->x.have = 0;
37636f395ceStb state->eof = 0;
37736f395ceStb state->past = 0;
37836f395ceStb state->seek = 0;
37936f395ceStb gz_error(state, Z_OK, NULL);
38036f395ceStb state->strm.avail_in = 0;
38136f395ceStb state->x.pos += offset;
38236f395ceStb return state->x.pos;
38336f395ceStb }
38436f395ceStb
38536f395ceStb /* calculate skip amount, rewinding if needed for back seek when reading */
38636f395ceStb if (offset < 0) {
38736f395ceStb if (state->mode != GZ_READ) /* writing -- can't go backwards */
38836f395ceStb return -1;
38936f395ceStb offset += state->x.pos;
39036f395ceStb if (offset < 0) /* before start of file! */
39136f395ceStb return -1;
39236f395ceStb if (gzrewind(file) == -1) /* rewind, then skip to offset */
39336f395ceStb return -1;
39436f395ceStb }
39536f395ceStb
39636f395ceStb /* if reading, skip what's in output buffer (one less gzgetc() check) */
39736f395ceStb if (state->mode == GZ_READ) {
39836f395ceStb n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
39936f395ceStb (unsigned)offset : state->x.have;
40036f395ceStb state->x.have -= n;
40136f395ceStb state->x.next += n;
40236f395ceStb state->x.pos += n;
40336f395ceStb offset -= n;
40436f395ceStb }
40536f395ceStb
40636f395ceStb /* request skip (if not zero) */
40736f395ceStb if (offset) {
40836f395ceStb state->seek = 1;
40936f395ceStb state->skip = offset;
41036f395ceStb }
41136f395ceStb return state->x.pos + offset;
41236f395ceStb }
41336f395ceStb
41436f395ceStb /* -- see zlib.h -- */
gzseek(gzFile file,z_off_t offset,int whence)415a04ea15dStb z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
41636f395ceStb z_off64_t ret;
41736f395ceStb
41836f395ceStb ret = gzseek64(file, (z_off64_t)offset, whence);
41936f395ceStb return ret == (z_off_t)ret ? (z_off_t)ret : -1;
42036f395ceStb }
42136f395ceStb
42236f395ceStb /* -- see zlib.h -- */
gztell64(gzFile file)423a04ea15dStb z_off64_t ZEXPORT gztell64(gzFile file) {
42436f395ceStb gz_statep state;
42536f395ceStb
42636f395ceStb /* get internal structure and check integrity */
42736f395ceStb if (file == NULL)
42836f395ceStb return -1;
42936f395ceStb state = (gz_statep)file;
43036f395ceStb if (state->mode != GZ_READ && state->mode != GZ_WRITE)
43136f395ceStb return -1;
43236f395ceStb
43336f395ceStb /* return position */
43436f395ceStb return state->x.pos + (state->seek ? state->skip : 0);
43536f395ceStb }
43636f395ceStb
43736f395ceStb /* -- see zlib.h -- */
gztell(gzFile file)438a04ea15dStb z_off_t ZEXPORT gztell(gzFile file) {
43936f395ceStb z_off64_t ret;
44036f395ceStb
44136f395ceStb ret = gztell64(file);
44236f395ceStb return ret == (z_off_t)ret ? (z_off_t)ret : -1;
44336f395ceStb }
44436f395ceStb
44536f395ceStb /* -- see zlib.h -- */
gzoffset64(gzFile file)446a04ea15dStb z_off64_t ZEXPORT gzoffset64(gzFile file) {
44736f395ceStb z_off64_t offset;
44836f395ceStb gz_statep state;
44936f395ceStb
45036f395ceStb /* get internal structure and check integrity */
45136f395ceStb if (file == NULL)
45236f395ceStb return -1;
45336f395ceStb state = (gz_statep)file;
45436f395ceStb if (state->mode != GZ_READ && state->mode != GZ_WRITE)
45536f395ceStb return -1;
45636f395ceStb
45736f395ceStb /* compute and return effective offset in file */
45836f395ceStb offset = LSEEK(state->fd, 0, SEEK_CUR);
45936f395ceStb if (offset == -1)
46036f395ceStb return -1;
46136f395ceStb if (state->mode == GZ_READ) /* reading */
46236f395ceStb offset -= state->strm.avail_in; /* don't count buffered input */
46336f395ceStb return offset;
46436f395ceStb }
46536f395ceStb
46636f395ceStb /* -- see zlib.h -- */
gzoffset(gzFile file)467a04ea15dStb z_off_t ZEXPORT gzoffset(gzFile file) {
46836f395ceStb z_off64_t ret;
46936f395ceStb
47036f395ceStb ret = gzoffset64(file);
47136f395ceStb return ret == (z_off_t)ret ? (z_off_t)ret : -1;
47236f395ceStb }
47336f395ceStb
47436f395ceStb /* -- see zlib.h -- */
gzeof(gzFile file)475a04ea15dStb int ZEXPORT gzeof(gzFile file) {
47636f395ceStb gz_statep state;
47736f395ceStb
47836f395ceStb /* get internal structure and check integrity */
47936f395ceStb if (file == NULL)
48036f395ceStb return 0;
48136f395ceStb state = (gz_statep)file;
48236f395ceStb if (state->mode != GZ_READ && state->mode != GZ_WRITE)
48336f395ceStb return 0;
48436f395ceStb
48536f395ceStb /* return end-of-file state */
48636f395ceStb return state->mode == GZ_READ ? state->past : 0;
48736f395ceStb }
48836f395ceStb
48936f395ceStb /* -- see zlib.h -- */
gzerror(gzFile file,int * errnum)490a04ea15dStb const char * ZEXPORT gzerror(gzFile file, int *errnum) {
49136f395ceStb gz_statep state;
49236f395ceStb
49336f395ceStb /* get internal structure and check integrity */
49436f395ceStb if (file == NULL)
49536f395ceStb return NULL;
49636f395ceStb state = (gz_statep)file;
49736f395ceStb if (state->mode != GZ_READ && state->mode != GZ_WRITE)
49836f395ceStb return NULL;
49936f395ceStb
50036f395ceStb /* return error information */
50136f395ceStb if (errnum != NULL)
50236f395ceStb *errnum = state->err;
50336f395ceStb return state->err == Z_MEM_ERROR ? "out of memory" :
50436f395ceStb (state->msg == NULL ? "" : state->msg);
50536f395ceStb }
50636f395ceStb
50736f395ceStb /* -- see zlib.h -- */
gzclearerr(gzFile file)508a04ea15dStb void ZEXPORT gzclearerr(gzFile file) {
50936f395ceStb gz_statep state;
51036f395ceStb
51136f395ceStb /* get internal structure and check integrity */
51236f395ceStb if (file == NULL)
51336f395ceStb return;
51436f395ceStb state = (gz_statep)file;
51536f395ceStb if (state->mode != GZ_READ && state->mode != GZ_WRITE)
51636f395ceStb return;
51736f395ceStb
51836f395ceStb /* clear error and end-of-file */
51936f395ceStb if (state->mode == GZ_READ) {
52036f395ceStb state->eof = 0;
52136f395ceStb state->past = 0;
52236f395ceStb }
52336f395ceStb gz_error(state, Z_OK, NULL);
52436f395ceStb }
52536f395ceStb
52636f395ceStb /* Create an error message in allocated memory and set state->err and
52736f395ceStb state->msg accordingly. Free any previous error message already there. Do
52836f395ceStb not try to free or allocate space if the error is Z_MEM_ERROR (out of
52936f395ceStb memory). Simply save the error message as a static string. If there is an
53036f395ceStb allocation failure constructing the error message, then convert the error to
53136f395ceStb out of memory. */
gz_error(gz_statep state,int err,const char * msg)532a04ea15dStb void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
53336f395ceStb /* free previously allocated message and clear */
53436f395ceStb if (state->msg != NULL) {
53536f395ceStb if (state->err != Z_MEM_ERROR)
53636f395ceStb free(state->msg);
53736f395ceStb state->msg = NULL;
53836f395ceStb }
53936f395ceStb
54036f395ceStb /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
54136f395ceStb if (err != Z_OK && err != Z_BUF_ERROR)
54236f395ceStb state->x.have = 0;
54336f395ceStb
54436f395ceStb /* set error code, and if no message, then done */
54536f395ceStb state->err = err;
54636f395ceStb if (msg == NULL)
54736f395ceStb return;
54836f395ceStb
54936f395ceStb /* for an out of memory error, return literal string when requested */
55036f395ceStb if (err == Z_MEM_ERROR)
55136f395ceStb return;
55236f395ceStb
55336f395ceStb /* construct error message with path */
55436f395ceStb if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
55536f395ceStb NULL) {
55636f395ceStb state->err = Z_MEM_ERROR;
55736f395ceStb return;
55836f395ceStb }
55936f395ceStb #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
56036f395ceStb (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
56136f395ceStb "%s%s%s", state->path, ": ", msg);
56236f395ceStb #else
56336f395ceStb strcpy(state->msg, state->path);
56436f395ceStb strcat(state->msg, ": ");
56536f395ceStb strcat(state->msg, msg);
56636f395ceStb #endif
56736f395ceStb }
56836f395ceStb
56936f395ceStb /* portably return maximum value for an int (when limits.h presumed not
57036f395ceStb available) -- we need to do this to cover cases where 2's complement not
57136f395ceStb used, since C standard permits 1's complement and sign-bit representations,
57236f395ceStb otherwise we could just use ((unsigned)-1) >> 1 */
gz_intmax(void)573a04ea15dStb unsigned ZLIB_INTERNAL gz_intmax(void) {
574f5252e2dStb #ifdef INT_MAX
575f5252e2dStb return INT_MAX;
576f5252e2dStb #else
577f5252e2dStb unsigned p = 1, q;
57836f395ceStb do {
57936f395ceStb q = p;
58036f395ceStb p <<= 1;
58136f395ceStb p++;
58236f395ceStb } while (p > q);
58336f395ceStb return q >> 1;
58436f395ceStb #endif
585f5252e2dStb }
586