X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=gzlib.c;h=4838bf04745beb5722fa4c69436ccc9d3fae68fb;hb=0e96d8e7c7079ab9f07cc7b57ae3ca9de8c80742;hp=e53b6abca16fd78066d1f8f2d91bed16fcf06595;hpb=26a99cd8957db86bdc75d9d1ebf00146cb20c87c;p=zlib.git diff --git a/gzlib.c b/gzlib.c index e53b6ab..4838bf0 100644 --- a/gzlib.c +++ b/gzlib.c @@ -1,11 +1,11 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010, 2011 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -#if defined(_WIN32) +#if defined(_WIN32) && !defined(__BORLANDC__) # define LSEEK _lseeki64 #else #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 @@ -17,7 +17,7 @@ /* Local functions */ local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const char *, int, const char *)); +local gzFile gz_open OF((const void *, int, const char *)); #if defined UNDER_CE @@ -78,6 +78,7 @@ local void gz_reset(state) state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ 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->seek = 0; /* no seek request pending */ @@ -88,18 +89,26 @@ local void gz_reset(state) /* Open a gzip file either by name or file descriptor. */ local gzFile gz_open(path, fd, mode) - const char *path; + const void *path; int fd; const char *mode; { gz_statep state; + z_size_t len; + int oflag; +#ifdef O_CLOEXEC + int cloexec = 0; +#endif +#ifdef O_EXCL + int exclusive = 0; +#endif /* check input */ if (path == NULL) return NULL; /* allocate gzFile structure to return */ - state = malloc(sizeof(gz_state)); + state = (gz_statep)malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ @@ -132,6 +141,16 @@ local gzFile gz_open(path, fd, mode) return NULL; case 'b': /* ignore -- will request binary anyway */ break; +#ifdef O_CLOEXEC + case 'e': + cloexec = 1; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif case 'f': state->strategy = Z_FILTERED; break; @@ -143,8 +162,10 @@ local gzFile gz_open(path, fd, mode) break; case 'F': state->strategy = Z_FIXED; + break; case 'T': state->direct = 1; + break; default: /* could consider as an error, but just ignore */ ; } @@ -167,36 +188,70 @@ local gzFile gz_open(path, fd, mode) } /* save the path name for error messages */ - state->path = malloc(strlen(path) + 1); +#ifdef WIDECHAR + if (fd == -2) { + len = wcstombs(NULL, path, 0); + if (len == (z_size_t)-1) + len = 0; + } + else +#endif + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } - strcpy(state->path, path); +#ifdef WIDECHAR + 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 - /* open the file with the appropriate mode (or just use fd) */ - state->fd = fd != -1 ? fd : - open(path, + /* compute the flags for open() */ + oflag = #ifdef O_LARGEFILE - O_LARGEFILE | + O_LARGEFILE | #endif #ifdef O_BINARY - O_BINARY | + O_BINARY | +#endif +#ifdef O_CLOEXEC + (cloexec ? O_CLOEXEC : 0) | #endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | ( - state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))), - 0666); + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + state->fd = fd > -1 ? fd : ( +#ifdef WIDECHAR + fd == -2 ? _wopen(path, oflag, 0666) : +#endif + open((const char *)path, oflag, 0666)); if (state->fd == -1) { free(state->path); free(state); return NULL; } - if (state->mode == GZ_APPEND) + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ state->mode = GZ_WRITE; /* simplify later checks */ + } /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { @@ -235,14 +290,28 @@ gzFile ZEXPORT gzdopen(fd, mode) char *path; /* identifier for error messages */ gzFile gz; - if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); +#else sprintf(path, "", fd); /* for debugging */ +#endif gz = gz_open(path, fd, mode); free(path); return gz; } +/* -- see zlib.h -- */ +#ifdef WIDECHAR +gzFile ZEXPORT gzopen_w(path, mode) + const wchar_t *path; + const char *mode; +{ + return gz_open(path, -2, mode); +} +#endif + /* -- see zlib.h -- */ int ZEXPORT gzbuffer(file, size) gzFile file; @@ -262,6 +331,8 @@ int ZEXPORT gzbuffer(file, size) return -1; /* check and set requested size */ + if ((size << 1) < size) + return -1; /* need to be able to double it */ if (size < 2) size = 2; /* need two bytes to check magic header */ state->want = size; @@ -326,11 +397,12 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); + ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); if (ret == -1) return -1; state->x.have = 0; state->eof = 0; + state->past = 0; state->seek = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; @@ -453,8 +525,7 @@ int ZEXPORT gzeof(file) return 0; /* return end-of-file state */ - return state->mode == GZ_READ ? - (state->eof && state->strm.avail_in == 0 && state->x.have == 0) : 0; + return state->mode == GZ_READ ? state->past : 0; } /* -- see zlib.h -- */ @@ -474,7 +545,8 @@ const char * ZEXPORT gzerror(file, errnum) /* return error information */ if (errnum != NULL) *errnum = state->err; - return state->msg == NULL ? "" : state->msg; + return state->err == Z_MEM_ERROR ? "out of memory" : + (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ @@ -491,8 +563,10 @@ void ZEXPORT gzclearerr(file) return; /* clear error and end-of-file */ - if (state->mode == GZ_READ) + if (state->mode == GZ_READ) { state->eof = 0; + state->past = 0; + } gz_error(state, Z_OK, NULL); } @@ -523,22 +597,24 @@ void ZLIB_INTERNAL gz_error(state, err, msg) if (msg == NULL) return; - /* for an out of memory error, save as static string */ - if (err == Z_MEM_ERROR) { - state->msg = (char *)msg; + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) return; - } /* construct error message with path */ - if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == + NULL) { state->err = Z_MEM_ERROR; - state->msg = (char *)"out of memory"; return; } +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); +#else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); - return; +#endif } #ifndef INT_MAX