10c16b537SWarner Losh /* gzlib.c contains minimal changes required to be compiled with zlibWrapper:
20c16b537SWarner Losh * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
30c16b537SWarner Losh
40c16b537SWarner Losh /* gzlib.c -- zlib functions common to reading and writing gzip files
50c16b537SWarner Losh * Copyright (C) 2004-2017 Mark Adler
60c16b537SWarner Losh * For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
70c16b537SWarner Losh */
80c16b537SWarner Losh
90c16b537SWarner Losh #include "gzguts.h"
100c16b537SWarner Losh
110c16b537SWarner Losh #if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
120c16b537SWarner Losh # define LSEEK _lseeki64
130c16b537SWarner Losh #else
140c16b537SWarner Losh #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
150c16b537SWarner Losh # define LSEEK lseek64
160c16b537SWarner Losh #else
170c16b537SWarner Losh # define LSEEK lseek
180c16b537SWarner Losh #endif
190c16b537SWarner Losh #endif
200c16b537SWarner Losh
210c16b537SWarner Losh /* Local functions */
220c16b537SWarner Losh local void gz_reset OF((gz_statep));
230c16b537SWarner Losh local gzFile gz_open OF((const void *, int, const char *));
240c16b537SWarner Losh
250c16b537SWarner Losh #if defined UNDER_CE
260c16b537SWarner Losh
270c16b537SWarner Losh /* Map the Windows error number in ERROR to a locale-dependent error message
280c16b537SWarner Losh string and return a pointer to it. Typically, the values for ERROR come
290c16b537SWarner Losh from GetLastError.
300c16b537SWarner Losh
310c16b537SWarner Losh The string pointed to shall not be modified by the application, but may be
320c16b537SWarner Losh overwritten by a subsequent call to gz_strwinerror
330c16b537SWarner Losh
340c16b537SWarner Losh The gz_strwinerror function does not change the current setting of
350c16b537SWarner Losh GetLastError. */
gz_strwinerror(error)360c16b537SWarner Losh char ZLIB_INTERNAL *gz_strwinerror (error)
370c16b537SWarner Losh DWORD error;
380c16b537SWarner Losh {
390c16b537SWarner Losh static char buf[1024];
400c16b537SWarner Losh
410c16b537SWarner Losh wchar_t *msgbuf;
420c16b537SWarner Losh DWORD lasterr = GetLastError();
430c16b537SWarner Losh DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
440c16b537SWarner Losh | FORMAT_MESSAGE_ALLOCATE_BUFFER,
450c16b537SWarner Losh NULL,
460c16b537SWarner Losh error,
470c16b537SWarner Losh 0, /* Default language */
480c16b537SWarner Losh (LPVOID)&msgbuf,
490c16b537SWarner Losh 0,
500c16b537SWarner Losh NULL);
510c16b537SWarner Losh if (chars != 0) {
520c16b537SWarner Losh /* If there is an \r\n appended, zap it. */
530c16b537SWarner Losh if (chars >= 2
540c16b537SWarner Losh && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
550c16b537SWarner Losh chars -= 2;
560c16b537SWarner Losh msgbuf[chars] = 0;
570c16b537SWarner Losh }
580c16b537SWarner Losh
590c16b537SWarner Losh if (chars > sizeof (buf) - 1) {
600c16b537SWarner Losh chars = sizeof (buf) - 1;
610c16b537SWarner Losh msgbuf[chars] = 0;
620c16b537SWarner Losh }
630c16b537SWarner Losh
640c16b537SWarner Losh wcstombs(buf, msgbuf, chars + 1);
650c16b537SWarner Losh LocalFree(msgbuf);
660c16b537SWarner Losh }
670c16b537SWarner Losh else {
680c16b537SWarner Losh sprintf(buf, "unknown win32 error (%ld)", error);
690c16b537SWarner Losh }
700c16b537SWarner Losh
710c16b537SWarner Losh SetLastError(lasterr);
720c16b537SWarner Losh return buf;
730c16b537SWarner Losh }
740c16b537SWarner Losh
750c16b537SWarner Losh #endif /* UNDER_CE */
760c16b537SWarner Losh
770c16b537SWarner Losh /* Reset gzip file state */
gz_reset(state)780c16b537SWarner Losh local void gz_reset(state)
790c16b537SWarner Losh gz_statep state;
800c16b537SWarner Losh {
810c16b537SWarner Losh state.state->x.have = 0; /* no output data available */
820c16b537SWarner Losh if (state.state->mode == GZ_READ) { /* for reading ... */
830c16b537SWarner Losh state.state->eof = 0; /* not at end of file */
840c16b537SWarner Losh state.state->past = 0; /* have not read past end yet */
850c16b537SWarner Losh state.state->how = LOOK; /* look for gzip header */
860c16b537SWarner Losh }
870c16b537SWarner Losh state.state->seek = 0; /* no seek request pending */
880c16b537SWarner Losh gz_error(state, Z_OK, NULL); /* clear error */
890c16b537SWarner Losh state.state->x.pos = 0; /* no uncompressed data yet */
900c16b537SWarner Losh state.state->strm.avail_in = 0; /* no input data yet */
910c16b537SWarner Losh }
920c16b537SWarner Losh
930c16b537SWarner Losh /* Open a gzip file either by name or file descriptor. */
gz_open(path,fd,mode)940c16b537SWarner Losh local gzFile gz_open(path, fd, mode)
950c16b537SWarner Losh const void *path;
960c16b537SWarner Losh int fd;
970c16b537SWarner Losh const char *mode;
980c16b537SWarner Losh {
990c16b537SWarner Losh gz_statep state;
1000c16b537SWarner Losh z_size_t len;
1010c16b537SWarner Losh int oflag;
1020c16b537SWarner Losh #ifdef O_CLOEXEC
1030c16b537SWarner Losh int cloexec = 0;
1040c16b537SWarner Losh #endif
1050c16b537SWarner Losh #ifdef O_EXCL
1060c16b537SWarner Losh int exclusive = 0;
1070c16b537SWarner Losh #endif
1080c16b537SWarner Losh
1090c16b537SWarner Losh /* check input */
1100c16b537SWarner Losh if (path == NULL)
1110c16b537SWarner Losh return NULL;
1120c16b537SWarner Losh
1130c16b537SWarner Losh /* allocate gzFile structure to return */
1140f743729SConrad Meyer state.state = (gz_state*)malloc(sizeof(gz_state));
1150c16b537SWarner Losh if (state.state == NULL)
1160c16b537SWarner Losh return NULL;
1170c16b537SWarner Losh state.state->size = 0; /* no buffers allocated yet */
1180c16b537SWarner Losh state.state->want = GZBUFSIZE; /* requested buffer size */
1190c16b537SWarner Losh state.state->msg = NULL; /* no error message yet */
1200c16b537SWarner Losh
1210c16b537SWarner Losh /* interpret mode */
1220c16b537SWarner Losh state.state->mode = GZ_NONE;
1230c16b537SWarner Losh state.state->level = Z_DEFAULT_COMPRESSION;
1240c16b537SWarner Losh state.state->strategy = Z_DEFAULT_STRATEGY;
1250c16b537SWarner Losh state.state->direct = 0;
1260c16b537SWarner Losh while (*mode) {
1270c16b537SWarner Losh if (*mode >= '0' && *mode <= '9')
1280c16b537SWarner Losh state.state->level = *mode - '0';
1290c16b537SWarner Losh else
1300c16b537SWarner Losh switch (*mode) {
1310c16b537SWarner Losh case 'r':
1320c16b537SWarner Losh state.state->mode = GZ_READ;
1330c16b537SWarner Losh break;
1340c16b537SWarner Losh #ifndef NO_GZCOMPRESS
1350c16b537SWarner Losh case 'w':
1360c16b537SWarner Losh state.state->mode = GZ_WRITE;
1370c16b537SWarner Losh break;
1380c16b537SWarner Losh case 'a':
1390c16b537SWarner Losh state.state->mode = GZ_APPEND;
1400c16b537SWarner Losh break;
1410c16b537SWarner Losh #endif
1420c16b537SWarner Losh case '+': /* can't read and write at the same time */
1430c16b537SWarner Losh free(state.state);
1440c16b537SWarner Losh return NULL;
1450c16b537SWarner Losh case 'b': /* ignore -- will request binary anyway */
1460c16b537SWarner Losh break;
1470c16b537SWarner Losh #ifdef O_CLOEXEC
1480c16b537SWarner Losh case 'e':
1490c16b537SWarner Losh cloexec = 1;
1500c16b537SWarner Losh break;
1510c16b537SWarner Losh #endif
1520c16b537SWarner Losh #ifdef O_EXCL
1530c16b537SWarner Losh case 'x':
1540c16b537SWarner Losh exclusive = 1;
1550c16b537SWarner Losh break;
1560c16b537SWarner Losh #endif
1570c16b537SWarner Losh case 'f':
1580c16b537SWarner Losh state.state->strategy = Z_FILTERED;
1590c16b537SWarner Losh break;
1600c16b537SWarner Losh case 'h':
1610c16b537SWarner Losh state.state->strategy = Z_HUFFMAN_ONLY;
1620c16b537SWarner Losh break;
1630c16b537SWarner Losh case 'R':
1640c16b537SWarner Losh state.state->strategy = Z_RLE;
1650c16b537SWarner Losh break;
1660c16b537SWarner Losh case 'F':
1670c16b537SWarner Losh state.state->strategy = Z_FIXED;
1680c16b537SWarner Losh break;
1690c16b537SWarner Losh case 'T':
1700c16b537SWarner Losh state.state->direct = 1;
1710c16b537SWarner Losh break;
1720c16b537SWarner Losh default: /* could consider as an error, but just ignore */
1730c16b537SWarner Losh ;
1740c16b537SWarner Losh }
1750c16b537SWarner Losh mode++;
1760c16b537SWarner Losh }
1770c16b537SWarner Losh
1780c16b537SWarner Losh /* must provide an "r", "w", or "a" */
1790c16b537SWarner Losh if (state.state->mode == GZ_NONE) {
1800c16b537SWarner Losh free(state.state);
1810c16b537SWarner Losh return NULL;
1820c16b537SWarner Losh }
1830c16b537SWarner Losh
1840c16b537SWarner Losh /* can't force transparent read */
1850c16b537SWarner Losh if (state.state->mode == GZ_READ) {
1860c16b537SWarner Losh if (state.state->direct) {
1870c16b537SWarner Losh free(state.state);
1880c16b537SWarner Losh return NULL;
1890c16b537SWarner Losh }
1900c16b537SWarner Losh state.state->direct = 1; /* for empty file */
1910c16b537SWarner Losh }
1920c16b537SWarner Losh
1930c16b537SWarner Losh /* save the path name for error messages */
1940c16b537SWarner Losh #ifdef WIDECHAR
1950c16b537SWarner Losh if (fd == -2) {
1960c16b537SWarner Losh len = wcstombs(NULL, path, 0);
1970c16b537SWarner Losh if (len == (z_size_t)-1)
1980c16b537SWarner Losh len = 0;
1990c16b537SWarner Losh }
2000c16b537SWarner Losh else
2010c16b537SWarner Losh #endif
2020c16b537SWarner Losh len = strlen((const char *)path);
2030c16b537SWarner Losh state.state->path = (char *)malloc(len + 1);
2040c16b537SWarner Losh if (state.state->path == NULL) {
2050c16b537SWarner Losh free(state.state);
2060c16b537SWarner Losh return NULL;
2070c16b537SWarner Losh }
2080c16b537SWarner Losh #ifdef WIDECHAR
2090c16b537SWarner Losh if (fd == -2)
2100c16b537SWarner Losh if (len)
2110c16b537SWarner Losh wcstombs(state.state->path, path, len + 1);
2120c16b537SWarner Losh else
2130c16b537SWarner Losh *(state.state->path) = 0;
2140c16b537SWarner Losh else
2150c16b537SWarner Losh #endif
2160c16b537SWarner Losh #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
2170c16b537SWarner Losh (void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
2180c16b537SWarner Losh #else
219*9cbefe25SConrad Meyer strcpy(state.state->path, (const char*)path);
2200c16b537SWarner Losh #endif
2210c16b537SWarner Losh
2220c16b537SWarner Losh /* compute the flags for open() */
2230c16b537SWarner Losh oflag =
2240c16b537SWarner Losh #ifdef O_LARGEFILE
2250c16b537SWarner Losh O_LARGEFILE |
2260c16b537SWarner Losh #endif
2270c16b537SWarner Losh #ifdef O_BINARY
2280c16b537SWarner Losh O_BINARY |
2290c16b537SWarner Losh #endif
2300c16b537SWarner Losh #ifdef O_CLOEXEC
2310c16b537SWarner Losh (cloexec ? O_CLOEXEC : 0) |
2320c16b537SWarner Losh #endif
2330c16b537SWarner Losh (state.state->mode == GZ_READ ?
2340c16b537SWarner Losh O_RDONLY :
2350c16b537SWarner Losh (O_WRONLY | O_CREAT |
2360c16b537SWarner Losh #ifdef O_EXCL
2370c16b537SWarner Losh (exclusive ? O_EXCL : 0) |
2380c16b537SWarner Losh #endif
2390c16b537SWarner Losh (state.state->mode == GZ_WRITE ?
2400c16b537SWarner Losh O_TRUNC :
2410c16b537SWarner Losh O_APPEND)));
2420c16b537SWarner Losh
2430c16b537SWarner Losh /* open the file with the appropriate flags (or just use fd) */
2440c16b537SWarner Losh state.state->fd = fd > -1 ? fd : (
2450c16b537SWarner Losh #ifdef WIDECHAR
2460c16b537SWarner Losh fd == -2 ? _wopen(path, oflag, 0666) :
2470c16b537SWarner Losh #endif
2480c16b537SWarner Losh open((const char *)path, oflag, 0666));
2490c16b537SWarner Losh if (state.state->fd == -1) {
2500c16b537SWarner Losh free(state.state->path);
2510c16b537SWarner Losh free(state.state);
2520c16b537SWarner Losh return NULL;
2530c16b537SWarner Losh }
2540c16b537SWarner Losh if (state.state->mode == GZ_APPEND) {
2550c16b537SWarner Losh LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
2560c16b537SWarner Losh state.state->mode = GZ_WRITE; /* simplify later checks */
2570c16b537SWarner Losh }
2580c16b537SWarner Losh
2590c16b537SWarner Losh /* save the current position for rewinding (only if reading) */
2600c16b537SWarner Losh if (state.state->mode == GZ_READ) {
2610c16b537SWarner Losh state.state->start = LSEEK(state.state->fd, 0, SEEK_CUR);
2620c16b537SWarner Losh if (state.state->start == -1) state.state->start = 0;
2630c16b537SWarner Losh }
2640c16b537SWarner Losh
2650c16b537SWarner Losh /* initialize stream */
2660c16b537SWarner Losh gz_reset(state);
2670c16b537SWarner Losh
2680c16b537SWarner Losh /* return stream */
2690f743729SConrad Meyer return state.file;
2700c16b537SWarner Losh }
2710c16b537SWarner Losh
2720c16b537SWarner Losh /* -- see zlib.h -- */
gzopen(path,mode)2730c16b537SWarner Losh gzFile ZEXPORT gzopen(path, mode)
2740c16b537SWarner Losh const char *path;
2750c16b537SWarner Losh const char *mode;
2760c16b537SWarner Losh {
2770c16b537SWarner Losh return gz_open(path, -1, mode);
2780c16b537SWarner Losh }
2790c16b537SWarner Losh
2800c16b537SWarner Losh /* -- see zlib.h -- */
gzopen64(path,mode)2810c16b537SWarner Losh gzFile ZEXPORT gzopen64(path, mode)
2820c16b537SWarner Losh const char *path;
2830c16b537SWarner Losh const char *mode;
2840c16b537SWarner Losh {
2850c16b537SWarner Losh return gz_open(path, -1, mode);
2860c16b537SWarner Losh }
2870c16b537SWarner Losh
2880c16b537SWarner Losh /* -- see zlib.h -- */
gzdopen(fd,mode)2890c16b537SWarner Losh gzFile ZEXPORT gzdopen(fd, mode)
2900c16b537SWarner Losh int fd;
2910c16b537SWarner Losh const char *mode;
2920c16b537SWarner Losh {
2930c16b537SWarner Losh char *path; /* identifier for error messages */
2940c16b537SWarner Losh gzFile gz;
2950c16b537SWarner Losh
2960c16b537SWarner Losh if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
2970c16b537SWarner Losh return NULL;
2980c16b537SWarner Losh #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
2990c16b537SWarner Losh (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
3000c16b537SWarner Losh #else
3010c16b537SWarner Losh sprintf(path, "<fd:%d>", fd); /* for debugging */
3020c16b537SWarner Losh #endif
3030c16b537SWarner Losh gz = gz_open(path, fd, mode);
3040c16b537SWarner Losh free(path);
3050c16b537SWarner Losh return gz;
3060c16b537SWarner Losh }
3070c16b537SWarner Losh
3080c16b537SWarner Losh /* -- see zlib.h -- */
3090c16b537SWarner Losh #ifdef WIDECHAR
gzopen_w(path,mode)3100c16b537SWarner Losh gzFile ZEXPORT gzopen_w(path, mode)
3110c16b537SWarner Losh const wchar_t *path;
3120c16b537SWarner Losh const char *mode;
3130c16b537SWarner Losh {
3140c16b537SWarner Losh return gz_open(path, -2, mode);
3150c16b537SWarner Losh }
3160c16b537SWarner Losh #endif
3170c16b537SWarner Losh
3180c16b537SWarner Losh /* -- see zlib.h -- */
gzbuffer(file,size)3190c16b537SWarner Losh int ZEXPORT gzbuffer(file, size)
3200c16b537SWarner Losh gzFile file;
3210c16b537SWarner Losh unsigned size;
3220c16b537SWarner Losh {
3230c16b537SWarner Losh gz_statep state;
3240c16b537SWarner Losh
3250c16b537SWarner Losh /* get internal structure and check integrity */
3260c16b537SWarner Losh if (file == NULL)
3270c16b537SWarner Losh return -1;
328*9cbefe25SConrad Meyer state.file = file;
3290c16b537SWarner Losh if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
3300c16b537SWarner Losh return -1;
3310c16b537SWarner Losh
3320c16b537SWarner Losh /* make sure we haven't already allocated memory */
3330c16b537SWarner Losh if (state.state->size != 0)
3340c16b537SWarner Losh return -1;
3350c16b537SWarner Losh
3360c16b537SWarner Losh /* check and set requested size */
3370c16b537SWarner Losh if ((size << 1) < size)
3380c16b537SWarner Losh return -1; /* need to be able to double it */
3390c16b537SWarner Losh if (size < 2)
3400c16b537SWarner Losh size = 2; /* need two bytes to check magic header */
3410c16b537SWarner Losh state.state->want = size;
3420c16b537SWarner Losh return 0;
3430c16b537SWarner Losh }
3440c16b537SWarner Losh
3450c16b537SWarner Losh /* -- see zlib.h -- */
gzrewind(file)3460c16b537SWarner Losh int ZEXPORT gzrewind(file)
3470c16b537SWarner Losh gzFile file;
3480c16b537SWarner Losh {
3490c16b537SWarner Losh gz_statep state;
3500c16b537SWarner Losh
3510c16b537SWarner Losh /* get internal structure */
3520c16b537SWarner Losh if (file == NULL)
3530c16b537SWarner Losh return -1;
354*9cbefe25SConrad Meyer state.file = file;
3550c16b537SWarner Losh
3560c16b537SWarner Losh /* check that we're reading and that there's no error */
3570c16b537SWarner Losh if (state.state->mode != GZ_READ ||
3580c16b537SWarner Losh (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
3590c16b537SWarner Losh return -1;
3600c16b537SWarner Losh
3610c16b537SWarner Losh /* back up and start over */
3620c16b537SWarner Losh if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)
3630c16b537SWarner Losh return -1;
3640c16b537SWarner Losh gz_reset(state);
3650c16b537SWarner Losh return 0;
3660c16b537SWarner Losh }
3670c16b537SWarner Losh
3680c16b537SWarner Losh /* -- see zlib.h -- */
gzseek64(file,offset,whence)3690c16b537SWarner Losh z_off64_t ZEXPORT gzseek64(file, offset, whence)
3700c16b537SWarner Losh gzFile file;
3710c16b537SWarner Losh z_off64_t offset;
3720c16b537SWarner Losh int whence;
3730c16b537SWarner Losh {
3740c16b537SWarner Losh unsigned n;
3750c16b537SWarner Losh z_off64_t ret;
3760c16b537SWarner Losh gz_statep state;
3770c16b537SWarner Losh
3780c16b537SWarner Losh /* get internal structure and check integrity */
3790c16b537SWarner Losh if (file == NULL)
3800c16b537SWarner Losh return -1;
381*9cbefe25SConrad Meyer state.file = file;
3820c16b537SWarner Losh if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
3830c16b537SWarner Losh return -1;
3840c16b537SWarner Losh
3850c16b537SWarner Losh /* check that there's no error */
3860c16b537SWarner Losh if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
3870c16b537SWarner Losh return -1;
3880c16b537SWarner Losh
3890c16b537SWarner Losh /* can only seek from start or relative to current position */
3900c16b537SWarner Losh if (whence != SEEK_SET && whence != SEEK_CUR)
3910c16b537SWarner Losh return -1;
3920c16b537SWarner Losh
3930c16b537SWarner Losh /* normalize offset to a SEEK_CUR specification */
3940c16b537SWarner Losh if (whence == SEEK_SET)
3950c16b537SWarner Losh offset -= state.state->x.pos;
3960c16b537SWarner Losh else if (state.state->seek)
3970c16b537SWarner Losh offset += state.state->skip;
3980c16b537SWarner Losh state.state->seek = 0;
3990c16b537SWarner Losh
4000c16b537SWarner Losh /* if within raw area while reading, just go there */
4010c16b537SWarner Losh if (state.state->mode == GZ_READ && state.state->how == COPY &&
4020c16b537SWarner Losh state.state->x.pos + offset >= 0) {
4030c16b537SWarner Losh ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);
4040c16b537SWarner Losh if (ret == -1)
4050c16b537SWarner Losh return -1;
4060c16b537SWarner Losh state.state->x.have = 0;
4070c16b537SWarner Losh state.state->eof = 0;
4080c16b537SWarner Losh state.state->past = 0;
4090c16b537SWarner Losh state.state->seek = 0;
4100c16b537SWarner Losh gz_error(state, Z_OK, NULL);
4110c16b537SWarner Losh state.state->strm.avail_in = 0;
4120c16b537SWarner Losh state.state->x.pos += offset;
4130c16b537SWarner Losh return state.state->x.pos;
4140c16b537SWarner Losh }
4150c16b537SWarner Losh
4160c16b537SWarner Losh /* calculate skip amount, rewinding if needed for back seek when reading */
4170c16b537SWarner Losh if (offset < 0) {
4180c16b537SWarner Losh if (state.state->mode != GZ_READ) /* writing -- can't go backwards */
4190c16b537SWarner Losh return -1;
4200c16b537SWarner Losh offset += state.state->x.pos;
4210c16b537SWarner Losh if (offset < 0) /* before start of file! */
4220c16b537SWarner Losh return -1;
4230c16b537SWarner Losh if (gzrewind(file) == -1) /* rewind, then skip to offset */
4240c16b537SWarner Losh return -1;
4250c16b537SWarner Losh }
4260c16b537SWarner Losh
4270c16b537SWarner Losh /* if reading, skip what's in output buffer (one less gzgetc() check) */
4280c16b537SWarner Losh if (state.state->mode == GZ_READ) {
4290c16b537SWarner Losh n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?
4300c16b537SWarner Losh (unsigned)offset : state.state->x.have;
4310c16b537SWarner Losh state.state->x.have -= n;
4320c16b537SWarner Losh state.state->x.next += n;
4330c16b537SWarner Losh state.state->x.pos += n;
4340c16b537SWarner Losh offset -= n;
4350c16b537SWarner Losh }
4360c16b537SWarner Losh
4370c16b537SWarner Losh /* request skip (if not zero) */
4380c16b537SWarner Losh if (offset) {
4390c16b537SWarner Losh state.state->seek = 1;
4400c16b537SWarner Losh state.state->skip = offset;
4410c16b537SWarner Losh }
4420c16b537SWarner Losh return state.state->x.pos + offset;
4430c16b537SWarner Losh }
4440c16b537SWarner Losh
4450c16b537SWarner Losh /* -- see zlib.h -- */
gzseek(file,offset,whence)4460c16b537SWarner Losh z_off_t ZEXPORT gzseek(file, offset, whence)
4470c16b537SWarner Losh gzFile file;
4480c16b537SWarner Losh z_off_t offset;
4490c16b537SWarner Losh int whence;
4500c16b537SWarner Losh {
4510c16b537SWarner Losh z_off64_t ret;
4520c16b537SWarner Losh
4530c16b537SWarner Losh ret = gzseek64(file, (z_off64_t)offset, whence);
4540c16b537SWarner Losh return ret == (z_off_t)ret ? (z_off_t)ret : -1;
4550c16b537SWarner Losh }
4560c16b537SWarner Losh
4570c16b537SWarner Losh /* -- see zlib.h -- */
gztell64(file)4580c16b537SWarner Losh z_off64_t ZEXPORT gztell64(file)
4590c16b537SWarner Losh gzFile file;
4600c16b537SWarner Losh {
4610c16b537SWarner Losh gz_statep state;
4620c16b537SWarner Losh
4630c16b537SWarner Losh /* get internal structure and check integrity */
4640c16b537SWarner Losh if (file == NULL)
4650c16b537SWarner Losh return -1;
466*9cbefe25SConrad Meyer state.file = file;
4670c16b537SWarner Losh if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
4680c16b537SWarner Losh return -1;
4690c16b537SWarner Losh
4700c16b537SWarner Losh /* return position */
4710c16b537SWarner Losh return state.state->x.pos + (state.state->seek ? state.state->skip : 0);
4720c16b537SWarner Losh }
4730c16b537SWarner Losh
4740c16b537SWarner Losh /* -- see zlib.h -- */
gztell(file)4750c16b537SWarner Losh z_off_t ZEXPORT gztell(file)
4760c16b537SWarner Losh gzFile file;
4770c16b537SWarner Losh {
4780c16b537SWarner Losh z_off64_t ret;
4790c16b537SWarner Losh
4800c16b537SWarner Losh ret = gztell64(file);
4810c16b537SWarner Losh return ret == (z_off_t)ret ? (z_off_t)ret : -1;
4820c16b537SWarner Losh }
4830c16b537SWarner Losh
4840c16b537SWarner Losh /* -- see zlib.h -- */
gzoffset64(file)4850c16b537SWarner Losh z_off64_t ZEXPORT gzoffset64(file)
4860c16b537SWarner Losh gzFile file;
4870c16b537SWarner Losh {
4880c16b537SWarner Losh z_off64_t offset;
4890c16b537SWarner Losh gz_statep state;
4900c16b537SWarner Losh
4910c16b537SWarner Losh /* get internal structure and check integrity */
4920c16b537SWarner Losh if (file == NULL)
4930c16b537SWarner Losh return -1;
494*9cbefe25SConrad Meyer state.file = file;
4950c16b537SWarner Losh if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
4960c16b537SWarner Losh return -1;
4970c16b537SWarner Losh
4980c16b537SWarner Losh /* compute and return effective offset in file */
4990c16b537SWarner Losh offset = LSEEK(state.state->fd, 0, SEEK_CUR);
5000c16b537SWarner Losh if (offset == -1)
5010c16b537SWarner Losh return -1;
5020c16b537SWarner Losh if (state.state->mode == GZ_READ) /* reading */
5030c16b537SWarner Losh offset -= state.state->strm.avail_in; /* don't count buffered input */
5040c16b537SWarner Losh return offset;
5050c16b537SWarner Losh }
5060c16b537SWarner Losh
5070c16b537SWarner Losh /* -- see zlib.h -- */
gzoffset(file)5080c16b537SWarner Losh z_off_t ZEXPORT gzoffset(file)
5090c16b537SWarner Losh gzFile file;
5100c16b537SWarner Losh {
5110c16b537SWarner Losh z_off64_t ret;
5120c16b537SWarner Losh
5130c16b537SWarner Losh ret = gzoffset64(file);
5140c16b537SWarner Losh return ret == (z_off_t)ret ? (z_off_t)ret : -1;
5150c16b537SWarner Losh }
5160c16b537SWarner Losh
5170c16b537SWarner Losh /* -- see zlib.h -- */
gzeof(file)5180c16b537SWarner Losh int ZEXPORT gzeof(file)
5190c16b537SWarner Losh gzFile file;
5200c16b537SWarner Losh {
5210c16b537SWarner Losh gz_statep state;
5220c16b537SWarner Losh
5230c16b537SWarner Losh /* get internal structure and check integrity */
5240c16b537SWarner Losh if (file == NULL)
5250c16b537SWarner Losh return 0;
526*9cbefe25SConrad Meyer state.file = file;
5270c16b537SWarner Losh if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
5280c16b537SWarner Losh return 0;
5290c16b537SWarner Losh
5300c16b537SWarner Losh /* return end-of-file state */
5310c16b537SWarner Losh return state.state->mode == GZ_READ ? state.state->past : 0;
5320c16b537SWarner Losh }
5330c16b537SWarner Losh
5340c16b537SWarner Losh /* -- see zlib.h -- */
gzerror(file,errnum)5350c16b537SWarner Losh const char * ZEXPORT gzerror(file, errnum)
5360c16b537SWarner Losh gzFile file;
5370c16b537SWarner Losh int *errnum;
5380c16b537SWarner Losh {
5390c16b537SWarner Losh gz_statep state;
5400c16b537SWarner Losh
5410c16b537SWarner Losh /* get internal structure and check integrity */
5420c16b537SWarner Losh if (file == NULL)
5430c16b537SWarner Losh return NULL;
544*9cbefe25SConrad Meyer state.file = file;
5450c16b537SWarner Losh if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
5460c16b537SWarner Losh return NULL;
5470c16b537SWarner Losh
5480c16b537SWarner Losh /* return error information */
5490c16b537SWarner Losh if (errnum != NULL)
5500c16b537SWarner Losh *errnum = state.state->err;
5510c16b537SWarner Losh return state.state->err == Z_MEM_ERROR ? "out of memory" :
5520c16b537SWarner Losh (state.state->msg == NULL ? "" : state.state->msg);
5530c16b537SWarner Losh }
5540c16b537SWarner Losh
5550c16b537SWarner Losh /* -- see zlib.h -- */
gzclearerr(file)5560c16b537SWarner Losh void ZEXPORT gzclearerr(file)
5570c16b537SWarner Losh gzFile file;
5580c16b537SWarner Losh {
5590c16b537SWarner Losh gz_statep state;
5600c16b537SWarner Losh
5610c16b537SWarner Losh /* get internal structure and check integrity */
5620c16b537SWarner Losh if (file == NULL)
5630c16b537SWarner Losh return;
564*9cbefe25SConrad Meyer state.file = file;
5650c16b537SWarner Losh if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
5660c16b537SWarner Losh return;
5670c16b537SWarner Losh
5680c16b537SWarner Losh /* clear error and end-of-file */
5690c16b537SWarner Losh if (state.state->mode == GZ_READ) {
5700c16b537SWarner Losh state.state->eof = 0;
5710c16b537SWarner Losh state.state->past = 0;
5720c16b537SWarner Losh }
5730c16b537SWarner Losh gz_error(state, Z_OK, NULL);
5740c16b537SWarner Losh }
5750c16b537SWarner Losh
5760c16b537SWarner Losh /* Create an error message in allocated memory and set state.state->err and
5770c16b537SWarner Losh state.state->msg accordingly. Free any previous error message already there. Do
5780c16b537SWarner Losh not try to free or allocate space if the error is Z_MEM_ERROR (out of
5790c16b537SWarner Losh memory). Simply save the error message as a static string. If there is an
5800c16b537SWarner Losh allocation failure constructing the error message, then convert the error to
5810c16b537SWarner Losh out of memory. */
gz_error(state,err,msg)5820c16b537SWarner Losh void ZLIB_INTERNAL gz_error(state, err, msg)
5830c16b537SWarner Losh gz_statep state;
5840c16b537SWarner Losh int err;
5850c16b537SWarner Losh const char *msg;
5860c16b537SWarner Losh {
5870c16b537SWarner Losh /* free previously allocated message and clear */
5880c16b537SWarner Losh if (state.state->msg != NULL) {
5890c16b537SWarner Losh if (state.state->err != Z_MEM_ERROR)
5900c16b537SWarner Losh free(state.state->msg);
5910c16b537SWarner Losh state.state->msg = NULL;
5920c16b537SWarner Losh }
5930c16b537SWarner Losh
5940c16b537SWarner Losh /* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
5950c16b537SWarner Losh if (err != Z_OK && err != Z_BUF_ERROR)
5960c16b537SWarner Losh state.state->x.have = 0;
5970c16b537SWarner Losh
5980c16b537SWarner Losh /* set error code, and if no message, then done */
5990c16b537SWarner Losh state.state->err = err;
6000c16b537SWarner Losh if (msg == NULL)
6010c16b537SWarner Losh return;
6020c16b537SWarner Losh
6030c16b537SWarner Losh /* for an out of memory error, return literal string when requested */
6040c16b537SWarner Losh if (err == Z_MEM_ERROR)
6050c16b537SWarner Losh return;
6060c16b537SWarner Losh
6070c16b537SWarner Losh /* construct error message with path */
6080c16b537SWarner Losh if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==
6090c16b537SWarner Losh NULL) {
6100c16b537SWarner Losh state.state->err = Z_MEM_ERROR;
6110c16b537SWarner Losh return;
6120c16b537SWarner Losh }
6130c16b537SWarner Losh #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
6140c16b537SWarner Losh (void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
6150c16b537SWarner Losh "%s%s%s", state.state->path, ": ", msg);
6160c16b537SWarner Losh #else
6170c16b537SWarner Losh strcpy(state.state->msg, state.state->path);
6180c16b537SWarner Losh strcat(state.state->msg, ": ");
6190c16b537SWarner Losh strcat(state.state->msg, msg);
6200c16b537SWarner Losh #endif
6210c16b537SWarner Losh }
6220c16b537SWarner Losh
6230c16b537SWarner Losh #ifndef INT_MAX
6240c16b537SWarner Losh /* portably return maximum value for an int (when limits.h presumed not
6250c16b537SWarner Losh available) -- we need to do this to cover cases where 2's complement not
6260c16b537SWarner Losh used, since C standard permits 1's complement and sign-bit representations,
6270c16b537SWarner Losh otherwise we could just use ((unsigned)-1) >> 1 */
gz_intmax()6280c16b537SWarner Losh unsigned ZLIB_INTERNAL gz_intmax()
6290c16b537SWarner Losh {
6300c16b537SWarner Losh unsigned p, q;
6310c16b537SWarner Losh
6320c16b537SWarner Losh p = 1;
6330c16b537SWarner Losh do {
6340c16b537SWarner Losh q = p;
6350c16b537SWarner Losh p <<= 1;
6360c16b537SWarner Losh p++;
6370c16b537SWarner Losh } while (p > q);
6380c16b537SWarner Losh return q >> 1;
6390c16b537SWarner Losh }
6400c16b537SWarner Losh #endif
641