From 1ab1026a20282383d9cd2282f81461655bea4028 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Sun, 11 May 2025 14:49:04 -0700 Subject: Add a "G" option to force gzip, disabling transparency in gzread(). If the input is not a gzip stream with this option, an error will be returned. --- gzlib.c | 20 +++++++++++++++++--- gzread.c | 10 +++++++++- zlib.h | 6 +++++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/gzlib.c b/gzlib.c index 2f9cdd4e..4c1aa83a 100644 --- a/gzlib.c +++ b/gzlib.c @@ -153,6 +153,9 @@ 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; case 'T': state->direct = 1; break; @@ -168,14 +171,25 @@ 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 diff --git a/gzread.c b/gzread.c index 5edecbfc..6fefe89d 100644 --- a/gzread.c +++ b/gzread.c @@ -106,6 +106,14 @@ local int gz_look(gz_statep state) { } } + /* if transparent reading is disabled, simply read as gzip */ + if (state->direct == -1) { + inflateReset(strm); + state->how = GZIP; + state->direct = 0; + return 0; + } + /* get at least the magic bytes in the input buffer */ if (strm->avail_in < 2) { if (gz_avail(state) == -1) @@ -567,7 +575,7 @@ int ZEXPORT gzdirect(gzFile file) { (void)gz_look(state); /* return 1 if transparent, 0 if processing a gzip stream */ - return state->direct; + return state->direct == 1; } /* -- see zlib.h -- */ diff --git a/zlib.h b/zlib.h index 85d79998..a2db7b2b 100644 --- a/zlib.h +++ b/zlib.h @@ -1343,7 +1343,11 @@ ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) 'T' will request transparent writing or - appending with no compression and not using the gzip format. + appending with no compression and not using the gzip format. 'T' cannot be + used to force transparent reading. Transparent reading is automatically + performed if there is no gzip header at the start. Transparent reading can + be disabled with the 'G' option, which will instead return an error if there + is no gzip header. "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since -- cgit v1.2.3-55-g6feb