Commit 1ab1026 for zlib

commit 1ab1026a20282383d9cd2282f81461655bea4028
Author: Mark Adler <madler@alumni.caltech.edu>
Date:   Sun May 11 14:49:04 2025 -0700

    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.

diff --git a/gzlib.c b/gzlib.c
index 2f9cdd4..4c1aa83 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 5edecbf..6fefe89 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 85d7999..a2db7b2 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