jdk/src/java.base/share/native/libzip/zlib/gzlib.c
changeset 43810 a8fca792a14b
equal deleted inserted replaced
43809:c3669a70a7ab 43810:a8fca792a14b
       
     1 /*
       
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     3  *
       
     4  * This code is free software; you can redistribute it and/or modify it
       
     5  * under the terms of the GNU General Public License version 2 only, as
       
     6  * published by the Free Software Foundation.  Oracle designates this
       
     7  * particular file as subject to the "Classpath" exception as provided
       
     8  * by Oracle in the LICENSE file that accompanied this code.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  */
       
    24 
       
    25 /* gzlib.c -- zlib functions common to reading and writing gzip files
       
    26  * Copyright (C) 2004-2017 Mark Adler
       
    27  * For conditions of distribution and use, see copyright notice in zlib.h
       
    28  */
       
    29 
       
    30 #include "gzguts.h"
       
    31 
       
    32 #if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
       
    33 #  define LSEEK _lseeki64
       
    34 #else
       
    35 #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
       
    36 #  define LSEEK lseek64
       
    37 #else
       
    38 #  define LSEEK lseek
       
    39 #endif
       
    40 #endif
       
    41 
       
    42 /* Local functions */
       
    43 local void gz_reset OF((gz_statep));
       
    44 local gzFile gz_open OF((const void *, int, const char *));
       
    45 
       
    46 #if defined UNDER_CE
       
    47 
       
    48 /* Map the Windows error number in ERROR to a locale-dependent error message
       
    49    string and return a pointer to it.  Typically, the values for ERROR come
       
    50    from GetLastError.
       
    51 
       
    52    The string pointed to shall not be modified by the application, but may be
       
    53    overwritten by a subsequent call to gz_strwinerror
       
    54 
       
    55    The gz_strwinerror function does not change the current setting of
       
    56    GetLastError. */
       
    57 char ZLIB_INTERNAL *gz_strwinerror (error)
       
    58      DWORD error;
       
    59 {
       
    60     static char buf[1024];
       
    61 
       
    62     wchar_t *msgbuf;
       
    63     DWORD lasterr = GetLastError();
       
    64     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
       
    65         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
       
    66         NULL,
       
    67         error,
       
    68         0, /* Default language */
       
    69         (LPVOID)&msgbuf,
       
    70         0,
       
    71         NULL);
       
    72     if (chars != 0) {
       
    73         /* If there is an \r\n appended, zap it.  */
       
    74         if (chars >= 2
       
    75             && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
       
    76             chars -= 2;
       
    77             msgbuf[chars] = 0;
       
    78         }
       
    79 
       
    80         if (chars > sizeof (buf) - 1) {
       
    81             chars = sizeof (buf) - 1;
       
    82             msgbuf[chars] = 0;
       
    83         }
       
    84 
       
    85         wcstombs(buf, msgbuf, chars + 1);
       
    86         LocalFree(msgbuf);
       
    87     }
       
    88     else {
       
    89         sprintf(buf, "unknown win32 error (%ld)", error);
       
    90     }
       
    91 
       
    92     SetLastError(lasterr);
       
    93     return buf;
       
    94 }
       
    95 
       
    96 #endif /* UNDER_CE */
       
    97 
       
    98 /* Reset gzip file state */
       
    99 local void gz_reset(state)
       
   100     gz_statep state;
       
   101 {
       
   102     state->x.have = 0;              /* no output data available */
       
   103     if (state->mode == GZ_READ) {   /* for reading ... */
       
   104         state->eof = 0;             /* not at end of file */
       
   105         state->past = 0;            /* have not read past end yet */
       
   106         state->how = LOOK;          /* look for gzip header */
       
   107     }
       
   108     state->seek = 0;                /* no seek request pending */
       
   109     gz_error(state, Z_OK, NULL);    /* clear error */
       
   110     state->x.pos = 0;               /* no uncompressed data yet */
       
   111     state->strm.avail_in = 0;       /* no input data yet */
       
   112 }
       
   113 
       
   114 /* Open a gzip file either by name or file descriptor. */
       
   115 local gzFile gz_open(path, fd, mode)
       
   116     const void *path;
       
   117     int fd;
       
   118     const char *mode;
       
   119 {
       
   120     gz_statep state;
       
   121     z_size_t len;
       
   122     int oflag;
       
   123 #ifdef O_CLOEXEC
       
   124     int cloexec = 0;
       
   125 #endif
       
   126 #ifdef O_EXCL
       
   127     int exclusive = 0;
       
   128 #endif
       
   129 
       
   130     /* check input */
       
   131     if (path == NULL)
       
   132         return NULL;
       
   133 
       
   134     /* allocate gzFile structure to return */
       
   135     state = (gz_statep)malloc(sizeof(gz_state));
       
   136     if (state == NULL)
       
   137         return NULL;
       
   138     state->size = 0;            /* no buffers allocated yet */
       
   139     state->want = GZBUFSIZE;    /* requested buffer size */
       
   140     state->msg = NULL;          /* no error message yet */
       
   141 
       
   142     /* interpret mode */
       
   143     state->mode = GZ_NONE;
       
   144     state->level = Z_DEFAULT_COMPRESSION;
       
   145     state->strategy = Z_DEFAULT_STRATEGY;
       
   146     state->direct = 0;
       
   147     while (*mode) {
       
   148         if (*mode >= '0' && *mode <= '9')
       
   149             state->level = *mode - '0';
       
   150         else
       
   151             switch (*mode) {
       
   152             case 'r':
       
   153                 state->mode = GZ_READ;
       
   154                 break;
       
   155 #ifndef NO_GZCOMPRESS
       
   156             case 'w':
       
   157                 state->mode = GZ_WRITE;
       
   158                 break;
       
   159             case 'a':
       
   160                 state->mode = GZ_APPEND;
       
   161                 break;
       
   162 #endif
       
   163             case '+':       /* can't read and write at the same time */
       
   164                 free(state);
       
   165                 return NULL;
       
   166             case 'b':       /* ignore -- will request binary anyway */
       
   167                 break;
       
   168 #ifdef O_CLOEXEC
       
   169             case 'e':
       
   170                 cloexec = 1;
       
   171                 break;
       
   172 #endif
       
   173 #ifdef O_EXCL
       
   174             case 'x':
       
   175                 exclusive = 1;
       
   176                 break;
       
   177 #endif
       
   178             case 'f':
       
   179                 state->strategy = Z_FILTERED;
       
   180                 break;
       
   181             case 'h':
       
   182                 state->strategy = Z_HUFFMAN_ONLY;
       
   183                 break;
       
   184             case 'R':
       
   185                 state->strategy = Z_RLE;
       
   186                 break;
       
   187             case 'F':
       
   188                 state->strategy = Z_FIXED;
       
   189                 break;
       
   190             case 'T':
       
   191                 state->direct = 1;
       
   192                 break;
       
   193             default:        /* could consider as an error, but just ignore */
       
   194                 ;
       
   195             }
       
   196         mode++;
       
   197     }
       
   198 
       
   199     /* must provide an "r", "w", or "a" */
       
   200     if (state->mode == GZ_NONE) {
       
   201         free(state);
       
   202         return NULL;
       
   203     }
       
   204 
       
   205     /* can't force transparent read */
       
   206     if (state->mode == GZ_READ) {
       
   207         if (state->direct) {
       
   208             free(state);
       
   209             return NULL;
       
   210         }
       
   211         state->direct = 1;      /* for empty file */
       
   212     }
       
   213 
       
   214     /* save the path name for error messages */
       
   215 #ifdef WIDECHAR
       
   216     if (fd == -2) {
       
   217         len = wcstombs(NULL, path, 0);
       
   218         if (len == (z_size_t)-1)
       
   219             len = 0;
       
   220     }
       
   221     else
       
   222 #endif
       
   223         len = strlen((const char *)path);
       
   224     state->path = (char *)malloc(len + 1);
       
   225     if (state->path == NULL) {
       
   226         free(state);
       
   227         return NULL;
       
   228     }
       
   229 #ifdef WIDECHAR
       
   230     if (fd == -2)
       
   231         if (len)
       
   232             wcstombs(state->path, path, len + 1);
       
   233         else
       
   234             *(state->path) = 0;
       
   235     else
       
   236 #endif
       
   237 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
       
   238         (void)snprintf(state->path, len + 1, "%s", (const char *)path);
       
   239 #else
       
   240         strcpy(state->path, path);
       
   241 #endif
       
   242 
       
   243     /* compute the flags for open() */
       
   244     oflag =
       
   245 #ifdef O_LARGEFILE
       
   246         O_LARGEFILE |
       
   247 #endif
       
   248 #ifdef O_BINARY
       
   249         O_BINARY |
       
   250 #endif
       
   251 #ifdef O_CLOEXEC
       
   252         (cloexec ? O_CLOEXEC : 0) |
       
   253 #endif
       
   254         (state->mode == GZ_READ ?
       
   255          O_RDONLY :
       
   256          (O_WRONLY | O_CREAT |
       
   257 #ifdef O_EXCL
       
   258           (exclusive ? O_EXCL : 0) |
       
   259 #endif
       
   260           (state->mode == GZ_WRITE ?
       
   261            O_TRUNC :
       
   262            O_APPEND)));
       
   263 
       
   264     /* open the file with the appropriate flags (or just use fd) */
       
   265     state->fd = fd > -1 ? fd : (
       
   266 #ifdef WIDECHAR
       
   267         fd == -2 ? _wopen(path, oflag, 0666) :
       
   268 #endif
       
   269         open((const char *)path, oflag, 0666));
       
   270     if (state->fd == -1) {
       
   271         free(state->path);
       
   272         free(state);
       
   273         return NULL;
       
   274     }
       
   275     if (state->mode == GZ_APPEND) {
       
   276         LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */
       
   277         state->mode = GZ_WRITE;         /* simplify later checks */
       
   278     }
       
   279 
       
   280     /* save the current position for rewinding (only if reading) */
       
   281     if (state->mode == GZ_READ) {
       
   282         state->start = LSEEK(state->fd, 0, SEEK_CUR);
       
   283         if (state->start == -1) state->start = 0;
       
   284     }
       
   285 
       
   286     /* initialize stream */
       
   287     gz_reset(state);
       
   288 
       
   289     /* return stream */
       
   290     return (gzFile)state;
       
   291 }
       
   292 
       
   293 /* -- see zlib.h -- */
       
   294 gzFile ZEXPORT gzopen(path, mode)
       
   295     const char *path;
       
   296     const char *mode;
       
   297 {
       
   298     return gz_open(path, -1, mode);
       
   299 }
       
   300 
       
   301 /* -- see zlib.h -- */
       
   302 gzFile ZEXPORT gzopen64(path, mode)
       
   303     const char *path;
       
   304     const char *mode;
       
   305 {
       
   306     return gz_open(path, -1, mode);
       
   307 }
       
   308 
       
   309 /* -- see zlib.h -- */
       
   310 gzFile ZEXPORT gzdopen(fd, mode)
       
   311     int fd;
       
   312     const char *mode;
       
   313 {
       
   314     char *path;         /* identifier for error messages */
       
   315     gzFile gz;
       
   316 
       
   317     if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
       
   318         return NULL;
       
   319 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
       
   320     (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
       
   321 #else
       
   322     sprintf(path, "<fd:%d>", fd);   /* for debugging */
       
   323 #endif
       
   324     gz = gz_open(path, fd, mode);
       
   325     free(path);
       
   326     return gz;
       
   327 }
       
   328 
       
   329 /* -- see zlib.h -- */
       
   330 #ifdef WIDECHAR
       
   331 gzFile ZEXPORT gzopen_w(path, mode)
       
   332     const wchar_t *path;
       
   333     const char *mode;
       
   334 {
       
   335     return gz_open(path, -2, mode);
       
   336 }
       
   337 #endif
       
   338 
       
   339 /* -- see zlib.h -- */
       
   340 int ZEXPORT gzbuffer(file, size)
       
   341     gzFile file;
       
   342     unsigned size;
       
   343 {
       
   344     gz_statep state;
       
   345 
       
   346     /* get internal structure and check integrity */
       
   347     if (file == NULL)
       
   348         return -1;
       
   349     state = (gz_statep)file;
       
   350     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   351         return -1;
       
   352 
       
   353     /* make sure we haven't already allocated memory */
       
   354     if (state->size != 0)
       
   355         return -1;
       
   356 
       
   357     /* check and set requested size */
       
   358     if ((size << 1) < size)
       
   359         return -1;              /* need to be able to double it */
       
   360     if (size < 2)
       
   361         size = 2;               /* need two bytes to check magic header */
       
   362     state->want = size;
       
   363     return 0;
       
   364 }
       
   365 
       
   366 /* -- see zlib.h -- */
       
   367 int ZEXPORT gzrewind(file)
       
   368     gzFile file;
       
   369 {
       
   370     gz_statep state;
       
   371 
       
   372     /* get internal structure */
       
   373     if (file == NULL)
       
   374         return -1;
       
   375     state = (gz_statep)file;
       
   376 
       
   377     /* check that we're reading and that there's no error */
       
   378     if (state->mode != GZ_READ ||
       
   379             (state->err != Z_OK && state->err != Z_BUF_ERROR))
       
   380         return -1;
       
   381 
       
   382     /* back up and start over */
       
   383     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
       
   384         return -1;
       
   385     gz_reset(state);
       
   386     return 0;
       
   387 }
       
   388 
       
   389 /* -- see zlib.h -- */
       
   390 z_off64_t ZEXPORT gzseek64(file, offset, whence)
       
   391     gzFile file;
       
   392     z_off64_t offset;
       
   393     int whence;
       
   394 {
       
   395     unsigned n;
       
   396     z_off64_t ret;
       
   397     gz_statep state;
       
   398 
       
   399     /* get internal structure and check integrity */
       
   400     if (file == NULL)
       
   401         return -1;
       
   402     state = (gz_statep)file;
       
   403     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   404         return -1;
       
   405 
       
   406     /* check that there's no error */
       
   407     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
       
   408         return -1;
       
   409 
       
   410     /* can only seek from start or relative to current position */
       
   411     if (whence != SEEK_SET && whence != SEEK_CUR)
       
   412         return -1;
       
   413 
       
   414     /* normalize offset to a SEEK_CUR specification */
       
   415     if (whence == SEEK_SET)
       
   416         offset -= state->x.pos;
       
   417     else if (state->seek)
       
   418         offset += state->skip;
       
   419     state->seek = 0;
       
   420 
       
   421     /* if within raw area while reading, just go there */
       
   422     if (state->mode == GZ_READ && state->how == COPY &&
       
   423             state->x.pos + offset >= 0) {
       
   424         ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
       
   425         if (ret == -1)
       
   426             return -1;
       
   427         state->x.have = 0;
       
   428         state->eof = 0;
       
   429         state->past = 0;
       
   430         state->seek = 0;
       
   431         gz_error(state, Z_OK, NULL);
       
   432         state->strm.avail_in = 0;
       
   433         state->x.pos += offset;
       
   434         return state->x.pos;
       
   435     }
       
   436 
       
   437     /* calculate skip amount, rewinding if needed for back seek when reading */
       
   438     if (offset < 0) {
       
   439         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
       
   440             return -1;
       
   441         offset += state->x.pos;
       
   442         if (offset < 0)                     /* before start of file! */
       
   443             return -1;
       
   444         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
       
   445             return -1;
       
   446     }
       
   447 
       
   448     /* if reading, skip what's in output buffer (one less gzgetc() check) */
       
   449     if (state->mode == GZ_READ) {
       
   450         n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
       
   451             (unsigned)offset : state->x.have;
       
   452         state->x.have -= n;
       
   453         state->x.next += n;
       
   454         state->x.pos += n;
       
   455         offset -= n;
       
   456     }
       
   457 
       
   458     /* request skip (if not zero) */
       
   459     if (offset) {
       
   460         state->seek = 1;
       
   461         state->skip = offset;
       
   462     }
       
   463     return state->x.pos + offset;
       
   464 }
       
   465 
       
   466 /* -- see zlib.h -- */
       
   467 z_off_t ZEXPORT gzseek(file, offset, whence)
       
   468     gzFile file;
       
   469     z_off_t offset;
       
   470     int whence;
       
   471 {
       
   472     z_off64_t ret;
       
   473 
       
   474     ret = gzseek64(file, (z_off64_t)offset, whence);
       
   475     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
       
   476 }
       
   477 
       
   478 /* -- see zlib.h -- */
       
   479 z_off64_t ZEXPORT gztell64(file)
       
   480     gzFile file;
       
   481 {
       
   482     gz_statep state;
       
   483 
       
   484     /* get internal structure and check integrity */
       
   485     if (file == NULL)
       
   486         return -1;
       
   487     state = (gz_statep)file;
       
   488     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   489         return -1;
       
   490 
       
   491     /* return position */
       
   492     return state->x.pos + (state->seek ? state->skip : 0);
       
   493 }
       
   494 
       
   495 /* -- see zlib.h -- */
       
   496 z_off_t ZEXPORT gztell(file)
       
   497     gzFile file;
       
   498 {
       
   499     z_off64_t ret;
       
   500 
       
   501     ret = gztell64(file);
       
   502     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
       
   503 }
       
   504 
       
   505 /* -- see zlib.h -- */
       
   506 z_off64_t ZEXPORT gzoffset64(file)
       
   507     gzFile file;
       
   508 {
       
   509     z_off64_t offset;
       
   510     gz_statep state;
       
   511 
       
   512     /* get internal structure and check integrity */
       
   513     if (file == NULL)
       
   514         return -1;
       
   515     state = (gz_statep)file;
       
   516     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   517         return -1;
       
   518 
       
   519     /* compute and return effective offset in file */
       
   520     offset = LSEEK(state->fd, 0, SEEK_CUR);
       
   521     if (offset == -1)
       
   522         return -1;
       
   523     if (state->mode == GZ_READ)             /* reading */
       
   524         offset -= state->strm.avail_in;     /* don't count buffered input */
       
   525     return offset;
       
   526 }
       
   527 
       
   528 /* -- see zlib.h -- */
       
   529 z_off_t ZEXPORT gzoffset(file)
       
   530     gzFile file;
       
   531 {
       
   532     z_off64_t ret;
       
   533 
       
   534     ret = gzoffset64(file);
       
   535     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
       
   536 }
       
   537 
       
   538 /* -- see zlib.h -- */
       
   539 int ZEXPORT gzeof(file)
       
   540     gzFile file;
       
   541 {
       
   542     gz_statep state;
       
   543 
       
   544     /* get internal structure and check integrity */
       
   545     if (file == NULL)
       
   546         return 0;
       
   547     state = (gz_statep)file;
       
   548     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   549         return 0;
       
   550 
       
   551     /* return end-of-file state */
       
   552     return state->mode == GZ_READ ? state->past : 0;
       
   553 }
       
   554 
       
   555 /* -- see zlib.h -- */
       
   556 const char * ZEXPORT gzerror(file, errnum)
       
   557     gzFile file;
       
   558     int *errnum;
       
   559 {
       
   560     gz_statep state;
       
   561 
       
   562     /* get internal structure and check integrity */
       
   563     if (file == NULL)
       
   564         return NULL;
       
   565     state = (gz_statep)file;
       
   566     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   567         return NULL;
       
   568 
       
   569     /* return error information */
       
   570     if (errnum != NULL)
       
   571         *errnum = state->err;
       
   572     return state->err == Z_MEM_ERROR ? "out of memory" :
       
   573                                        (state->msg == NULL ? "" : state->msg);
       
   574 }
       
   575 
       
   576 /* -- see zlib.h -- */
       
   577 void ZEXPORT gzclearerr(file)
       
   578     gzFile file;
       
   579 {
       
   580     gz_statep state;
       
   581 
       
   582     /* get internal structure and check integrity */
       
   583     if (file == NULL)
       
   584         return;
       
   585     state = (gz_statep)file;
       
   586     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   587         return;
       
   588 
       
   589     /* clear error and end-of-file */
       
   590     if (state->mode == GZ_READ) {
       
   591         state->eof = 0;
       
   592         state->past = 0;
       
   593     }
       
   594     gz_error(state, Z_OK, NULL);
       
   595 }
       
   596 
       
   597 /* Create an error message in allocated memory and set state->err and
       
   598    state->msg accordingly.  Free any previous error message already there.  Do
       
   599    not try to free or allocate space if the error is Z_MEM_ERROR (out of
       
   600    memory).  Simply save the error message as a static string.  If there is an
       
   601    allocation failure constructing the error message, then convert the error to
       
   602    out of memory. */
       
   603 void ZLIB_INTERNAL gz_error(state, err, msg)
       
   604     gz_statep state;
       
   605     int err;
       
   606     const char *msg;
       
   607 {
       
   608     /* free previously allocated message and clear */
       
   609     if (state->msg != NULL) {
       
   610         if (state->err != Z_MEM_ERROR)
       
   611             free(state->msg);
       
   612         state->msg = NULL;
       
   613     }
       
   614 
       
   615     /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
       
   616     if (err != Z_OK && err != Z_BUF_ERROR)
       
   617         state->x.have = 0;
       
   618 
       
   619     /* set error code, and if no message, then done */
       
   620     state->err = err;
       
   621     if (msg == NULL)
       
   622         return;
       
   623 
       
   624     /* for an out of memory error, return literal string when requested */
       
   625     if (err == Z_MEM_ERROR)
       
   626         return;
       
   627 
       
   628     /* construct error message with path */
       
   629     if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
       
   630             NULL) {
       
   631         state->err = Z_MEM_ERROR;
       
   632         return;
       
   633     }
       
   634 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
       
   635     (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
       
   636                    "%s%s%s", state->path, ": ", msg);
       
   637 #else
       
   638     strcpy(state->msg, state->path);
       
   639     strcat(state->msg, ": ");
       
   640     strcat(state->msg, msg);
       
   641 #endif
       
   642 }
       
   643 
       
   644 #ifndef INT_MAX
       
   645 /* portably return maximum value for an int (when limits.h presumed not
       
   646    available) -- we need to do this to cover cases where 2's complement not
       
   647    used, since C standard permits 1's complement and sign-bit representations,
       
   648    otherwise we could just use ((unsigned)-1) >> 1 */
       
   649 unsigned ZLIB_INTERNAL gz_intmax()
       
   650 {
       
   651     unsigned p, q;
       
   652 
       
   653     p = 1;
       
   654     do {
       
   655         q = p;
       
   656         p <<= 1;
       
   657         p++;
       
   658     } while (p > q);
       
   659     return q >> 1;
       
   660 }
       
   661 #endif