diff options
Diffstat (limited to 'gzlib.c')
| -rw-r--r-- | gzlib.c | 103 |
1 files changed, 65 insertions, 38 deletions
@@ -1,19 +1,19 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004-2024 Mark Adler + * Copyright (C) 2004-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -#if defined(_WIN32) && !defined(__BORLANDC__) +#if defined(__DJGPP__) +# define LSEEK llseek +#elif defined(_WIN32) && !defined(__BORLANDC__) && !defined(UNDER_CE) # define LSEEK _lseeki64 -#else -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#elif defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif -#endif #if defined UNDER_CE @@ -52,7 +52,7 @@ char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { msgbuf[chars] = 0; } - wcstombs(buf, msgbuf, chars + 1); + wcstombs(buf, msgbuf, chars + 1); /* assumes buf is big enough */ LocalFree(msgbuf); } else { @@ -72,10 +72,12 @@ local void gz_reset(gz_statep state) { state->eof = 0; /* not at end of file */ state->past = 0; /* have not read past end yet */ state->how = LOOK; /* look for gzip header */ + state->junk = -1; /* mark first member */ } else /* for writing ... */ state->reset = 0; /* no deflateReset pending */ - state->seek = 0; /* no seek request pending */ + state->again = 0; /* no stalled i/o yet */ + state->skip = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ @@ -85,16 +87,13 @@ local void gz_reset(gz_statep state) { local gzFile gz_open(const void *path, int fd, const char *mode) { gz_statep state; z_size_t len; - int oflag; -#ifdef O_CLOEXEC - int cloexec = 0; -#endif + int oflag = 0; #ifdef O_EXCL int exclusive = 0; #endif /* check input */ - if (path == NULL) + if (path == NULL || mode == NULL) return NULL; /* allocate gzFile structure to return */ @@ -103,6 +102,7 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { return NULL; state->size = 0; /* no buffers allocated yet */ state->want = GZBUFSIZE; /* requested buffer size */ + state->err = Z_OK; /* no error yet */ state->msg = NULL; /* no error message yet */ /* interpret mode */ @@ -133,7 +133,7 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { break; #ifdef O_CLOEXEC case 'e': - cloexec = 1; + oflag |= O_CLOEXEC; break; #endif #ifdef O_EXCL @@ -153,6 +153,14 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { case 'F': state->strategy = Z_FIXED; break; + case 'G': + state->direct = -1; + break; +#ifdef O_NONBLOCK + case 'N': + oflag |= O_NONBLOCK; + break; +#endif case 'T': state->direct = 1; break; @@ -168,22 +176,30 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { return NULL; } - /* can't force transparent read */ + /* direct is 0, 1 if "T", or -1 if "G" (last "G" or "T" wins) */ if (state->mode == GZ_READ) { - if (state->direct) { + if (state->direct == 1) { + /* can't force a transparent read */ free(state); return NULL; } - state->direct = 1; /* for empty file */ + if (state->direct == 0) + /* default when reading is auto-detect of gzip vs. transparent -- + start with a transparent assumption in case of an empty file */ + state->direct = 1; } + else if (state->direct == -1) { + /* "G" has no meaning when writing -- disallow it */ + free(state); + return NULL; + } + /* if reading, direct == 1 for auto-detect, -1 for gzip only; if writing or + appending, direct == 0 for gzip, 1 for transparent (copy in to out) */ /* save the path name for error messages */ #ifdef WIDECHAR - if (fd == -2) { + if (fd == -2) len = wcstombs(NULL, path, 0); - if (len == (z_size_t)-1) - len = 0; - } else #endif len = strlen((const char *)path); @@ -193,30 +209,30 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { return NULL; } #ifdef WIDECHAR - if (fd == -2) + if (fd == -2) { if (len) wcstombs(state->path, path, len + 1); else *(state->path) = 0; + } else #endif + { #if !defined(NO_snprintf) && !defined(NO_vsnprintf) (void)snprintf(state->path, len + 1, "%s", (const char *)path); #else strcpy(state->path, path); #endif + } /* compute the flags for open() */ - oflag = + oflag |= #ifdef O_LARGEFILE O_LARGEFILE | #endif #ifdef O_BINARY O_BINARY | #endif -#ifdef O_CLOEXEC - (cloexec ? O_CLOEXEC : 0) | -#endif (state->mode == GZ_READ ? O_RDONLY : (O_WRONLY | O_CREAT | @@ -228,11 +244,23 @@ local gzFile gz_open(const void *path, int fd, const char *mode) { O_APPEND))); /* open the file with the appropriate flags (or just use fd) */ - state->fd = fd > -1 ? fd : ( + if (fd == -1) + state->fd = open((const char *)path, oflag, 0666); #ifdef WIDECHAR - fd == -2 ? _wopen(path, oflag, 0666) : + else if (fd == -2) + state->fd = _wopen(path, oflag, _S_IREAD | _S_IWRITE); +#endif + else { +#ifdef O_NONBLOCK + if (oflag & O_NONBLOCK) + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); #endif - open((const char *)path, oflag, 0666)); +#ifdef O_CLOEXEC + if (oflag & O_CLOEXEC) + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | O_CLOEXEC); +#endif + state->fd = fd; + } if (state->fd == -1) { free(state->path); free(state); @@ -359,9 +387,10 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) offset -= state->x.pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; + else { + offset += state->past ? 0 : state->skip; + state->skip = 0; + } /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && @@ -372,7 +401,7 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { state->x.have = 0; state->eof = 0; state->past = 0; - state->seek = 0; + state->skip = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; state->x.pos += offset; @@ -401,10 +430,7 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { } /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } + state->skip = offset; return state->x.pos + offset; } @@ -428,7 +454,7 @@ z_off64_t ZEXPORT gztell64(gzFile file) { return -1; /* return position */ - return state->x.pos + (state->seek ? state->skip : 0); + return state->x.pos + (state->past ? 0 : state->skip); } /* -- see zlib.h -- */ @@ -535,7 +561,7 @@ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { } /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ - if (err != Z_OK && err != Z_BUF_ERROR) + if (err != Z_OK && err != Z_BUF_ERROR && !state->again) state->x.have = 0; /* set error code, and if no message, then done */ @@ -572,6 +598,7 @@ unsigned ZLIB_INTERNAL gz_intmax(void) { return INT_MAX; #else unsigned p = 1, q; + do { q = p; p <<= 1; |
