jdk/src/java.base/share/native/libzip/zlib-1.2.8/gzlib.c
changeset 43880 b5015f742ba6
parent 43879 a6dc784b18a8
parent 43854 76c52ad1e6c7
child 43881 4d99ca794b88
equal deleted inserted replaced
43879:a6dc784b18a8 43880:b5015f742ba6
     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, 2010, 2011, 2012, 2013 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__)
       
    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     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 _WIN32
       
   216     if (fd == -2) {
       
   217         len = wcstombs(NULL, path, 0);
       
   218         if (len == (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 _WIN32
       
   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         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 _WIN32
       
   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         state->mode = GZ_WRITE;         /* simplify later checks */
       
   277 
       
   278     /* save the current position for rewinding (only if reading) */
       
   279     if (state->mode == GZ_READ) {
       
   280         state->start = LSEEK(state->fd, 0, SEEK_CUR);
       
   281         if (state->start == -1) state->start = 0;
       
   282     }
       
   283 
       
   284     /* initialize stream */
       
   285     gz_reset(state);
       
   286 
       
   287     /* return stream */
       
   288     return (gzFile)state;
       
   289 }
       
   290 
       
   291 /* -- see zlib.h -- */
       
   292 gzFile ZEXPORT gzopen(path, mode)
       
   293     const char *path;
       
   294     const char *mode;
       
   295 {
       
   296     return gz_open(path, -1, mode);
       
   297 }
       
   298 
       
   299 /* -- see zlib.h -- */
       
   300 gzFile ZEXPORT gzopen64(path, mode)
       
   301     const char *path;
       
   302     const char *mode;
       
   303 {
       
   304     return gz_open(path, -1, mode);
       
   305 }
       
   306 
       
   307 /* -- see zlib.h -- */
       
   308 gzFile ZEXPORT gzdopen(fd, mode)
       
   309     int fd;
       
   310     const char *mode;
       
   311 {
       
   312     char *path;         /* identifier for error messages */
       
   313     gzFile gz;
       
   314 
       
   315     if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
       
   316         return NULL;
       
   317 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
       
   318     snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
       
   319 #else
       
   320     sprintf(path, "<fd:%d>", fd);   /* for debugging */
       
   321 #endif
       
   322     gz = gz_open(path, fd, mode);
       
   323     free(path);
       
   324     return gz;
       
   325 }
       
   326 
       
   327 /* -- see zlib.h -- */
       
   328 #ifdef _WIN32
       
   329 gzFile ZEXPORT gzopen_w(path, mode)
       
   330     const wchar_t *path;
       
   331     const char *mode;
       
   332 {
       
   333     return gz_open(path, -2, mode);
       
   334 }
       
   335 #endif
       
   336 
       
   337 /* -- see zlib.h -- */
       
   338 int ZEXPORT gzbuffer(file, size)
       
   339     gzFile file;
       
   340     unsigned size;
       
   341 {
       
   342     gz_statep state;
       
   343 
       
   344     /* get internal structure and check integrity */
       
   345     if (file == NULL)
       
   346         return -1;
       
   347     state = (gz_statep)file;
       
   348     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   349         return -1;
       
   350 
       
   351     /* make sure we haven't already allocated memory */
       
   352     if (state->size != 0)
       
   353         return -1;
       
   354 
       
   355     /* check and set requested size */
       
   356     if (size < 2)
       
   357         size = 2;               /* need two bytes to check magic header */
       
   358     state->want = size;
       
   359     return 0;
       
   360 }
       
   361 
       
   362 /* -- see zlib.h -- */
       
   363 int ZEXPORT gzrewind(file)
       
   364     gzFile file;
       
   365 {
       
   366     gz_statep state;
       
   367 
       
   368     /* get internal structure */
       
   369     if (file == NULL)
       
   370         return -1;
       
   371     state = (gz_statep)file;
       
   372 
       
   373     /* check that we're reading and that there's no error */
       
   374     if (state->mode != GZ_READ ||
       
   375             (state->err != Z_OK && state->err != Z_BUF_ERROR))
       
   376         return -1;
       
   377 
       
   378     /* back up and start over */
       
   379     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
       
   380         return -1;
       
   381     gz_reset(state);
       
   382     return 0;
       
   383 }
       
   384 
       
   385 /* -- see zlib.h -- */
       
   386 z_off64_t ZEXPORT gzseek64(file, offset, whence)
       
   387     gzFile file;
       
   388     z_off64_t offset;
       
   389     int whence;
       
   390 {
       
   391     unsigned n;
       
   392     z_off64_t ret;
       
   393     gz_statep state;
       
   394 
       
   395     /* get internal structure and check integrity */
       
   396     if (file == NULL)
       
   397         return -1;
       
   398     state = (gz_statep)file;
       
   399     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   400         return -1;
       
   401 
       
   402     /* check that there's no error */
       
   403     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
       
   404         return -1;
       
   405 
       
   406     /* can only seek from start or relative to current position */
       
   407     if (whence != SEEK_SET && whence != SEEK_CUR)
       
   408         return -1;
       
   409 
       
   410     /* normalize offset to a SEEK_CUR specification */
       
   411     if (whence == SEEK_SET)
       
   412         offset -= state->x.pos;
       
   413     else if (state->seek)
       
   414         offset += state->skip;
       
   415     state->seek = 0;
       
   416 
       
   417     /* if within raw area while reading, just go there */
       
   418     if (state->mode == GZ_READ && state->how == COPY &&
       
   419             state->x.pos + offset >= 0) {
       
   420         ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
       
   421         if (ret == -1)
       
   422             return -1;
       
   423         state->x.have = 0;
       
   424         state->eof = 0;
       
   425         state->past = 0;
       
   426         state->seek = 0;
       
   427         gz_error(state, Z_OK, NULL);
       
   428         state->strm.avail_in = 0;
       
   429         state->x.pos += offset;
       
   430         return state->x.pos;
       
   431     }
       
   432 
       
   433     /* calculate skip amount, rewinding if needed for back seek when reading */
       
   434     if (offset < 0) {
       
   435         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
       
   436             return -1;
       
   437         offset += state->x.pos;
       
   438         if (offset < 0)                     /* before start of file! */
       
   439             return -1;
       
   440         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
       
   441             return -1;
       
   442     }
       
   443 
       
   444     /* if reading, skip what's in output buffer (one less gzgetc() check) */
       
   445     if (state->mode == GZ_READ) {
       
   446         n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
       
   447             (unsigned)offset : state->x.have;
       
   448         state->x.have -= n;
       
   449         state->x.next += n;
       
   450         state->x.pos += n;
       
   451         offset -= n;
       
   452     }
       
   453 
       
   454     /* request skip (if not zero) */
       
   455     if (offset) {
       
   456         state->seek = 1;
       
   457         state->skip = offset;
       
   458     }
       
   459     return state->x.pos + offset;
       
   460 }
       
   461 
       
   462 /* -- see zlib.h -- */
       
   463 z_off_t ZEXPORT gzseek(file, offset, whence)
       
   464     gzFile file;
       
   465     z_off_t offset;
       
   466     int whence;
       
   467 {
       
   468     z_off64_t ret;
       
   469 
       
   470     ret = gzseek64(file, (z_off64_t)offset, whence);
       
   471     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
       
   472 }
       
   473 
       
   474 /* -- see zlib.h -- */
       
   475 z_off64_t ZEXPORT gztell64(file)
       
   476     gzFile file;
       
   477 {
       
   478     gz_statep state;
       
   479 
       
   480     /* get internal structure and check integrity */
       
   481     if (file == NULL)
       
   482         return -1;
       
   483     state = (gz_statep)file;
       
   484     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   485         return -1;
       
   486 
       
   487     /* return position */
       
   488     return state->x.pos + (state->seek ? state->skip : 0);
       
   489 }
       
   490 
       
   491 /* -- see zlib.h -- */
       
   492 z_off_t ZEXPORT gztell(file)
       
   493     gzFile file;
       
   494 {
       
   495     z_off64_t ret;
       
   496 
       
   497     ret = gztell64(file);
       
   498     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
       
   499 }
       
   500 
       
   501 /* -- see zlib.h -- */
       
   502 z_off64_t ZEXPORT gzoffset64(file)
       
   503     gzFile file;
       
   504 {
       
   505     z_off64_t offset;
       
   506     gz_statep state;
       
   507 
       
   508     /* get internal structure and check integrity */
       
   509     if (file == NULL)
       
   510         return -1;
       
   511     state = (gz_statep)file;
       
   512     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   513         return -1;
       
   514 
       
   515     /* compute and return effective offset in file */
       
   516     offset = LSEEK(state->fd, 0, SEEK_CUR);
       
   517     if (offset == -1)
       
   518         return -1;
       
   519     if (state->mode == GZ_READ)             /* reading */
       
   520         offset -= state->strm.avail_in;     /* don't count buffered input */
       
   521     return offset;
       
   522 }
       
   523 
       
   524 /* -- see zlib.h -- */
       
   525 z_off_t ZEXPORT gzoffset(file)
       
   526     gzFile file;
       
   527 {
       
   528     z_off64_t ret;
       
   529 
       
   530     ret = gzoffset64(file);
       
   531     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
       
   532 }
       
   533 
       
   534 /* -- see zlib.h -- */
       
   535 int ZEXPORT gzeof(file)
       
   536     gzFile file;
       
   537 {
       
   538     gz_statep state;
       
   539 
       
   540     /* get internal structure and check integrity */
       
   541     if (file == NULL)
       
   542         return 0;
       
   543     state = (gz_statep)file;
       
   544     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   545         return 0;
       
   546 
       
   547     /* return end-of-file state */
       
   548     return state->mode == GZ_READ ? state->past : 0;
       
   549 }
       
   550 
       
   551 /* -- see zlib.h -- */
       
   552 const char * ZEXPORT gzerror(file, errnum)
       
   553     gzFile file;
       
   554     int *errnum;
       
   555 {
       
   556     gz_statep state;
       
   557 
       
   558     /* get internal structure and check integrity */
       
   559     if (file == NULL)
       
   560         return NULL;
       
   561     state = (gz_statep)file;
       
   562     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   563         return NULL;
       
   564 
       
   565     /* return error information */
       
   566     if (errnum != NULL)
       
   567         *errnum = state->err;
       
   568     return state->err == Z_MEM_ERROR ? "out of memory" :
       
   569                                        (state->msg == NULL ? "" : state->msg);
       
   570 }
       
   571 
       
   572 /* -- see zlib.h -- */
       
   573 void ZEXPORT gzclearerr(file)
       
   574     gzFile file;
       
   575 {
       
   576     gz_statep state;
       
   577 
       
   578     /* get internal structure and check integrity */
       
   579     if (file == NULL)
       
   580         return;
       
   581     state = (gz_statep)file;
       
   582     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
       
   583         return;
       
   584 
       
   585     /* clear error and end-of-file */
       
   586     if (state->mode == GZ_READ) {
       
   587         state->eof = 0;
       
   588         state->past = 0;
       
   589     }
       
   590     gz_error(state, Z_OK, NULL);
       
   591 }
       
   592 
       
   593 /* Create an error message in allocated memory and set state->err and
       
   594    state->msg accordingly.  Free any previous error message already there.  Do
       
   595    not try to free or allocate space if the error is Z_MEM_ERROR (out of
       
   596    memory).  Simply save the error message as a static string.  If there is an
       
   597    allocation failure constructing the error message, then convert the error to
       
   598    out of memory. */
       
   599 void ZLIB_INTERNAL gz_error(state, err, msg)
       
   600     gz_statep state;
       
   601     int err;
       
   602     const char *msg;
       
   603 {
       
   604     /* free previously allocated message and clear */
       
   605     if (state->msg != NULL) {
       
   606         if (state->err != Z_MEM_ERROR)
       
   607             free(state->msg);
       
   608         state->msg = NULL;
       
   609     }
       
   610 
       
   611     /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
       
   612     if (err != Z_OK && err != Z_BUF_ERROR)
       
   613         state->x.have = 0;
       
   614 
       
   615     /* set error code, and if no message, then done */
       
   616     state->err = err;
       
   617     if (msg == NULL)
       
   618         return;
       
   619 
       
   620     /* for an out of memory error, return literal string when requested */
       
   621     if (err == Z_MEM_ERROR)
       
   622         return;
       
   623 
       
   624     /* construct error message with path */
       
   625     if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
       
   626             NULL) {
       
   627         state->err = Z_MEM_ERROR;
       
   628         return;
       
   629     }
       
   630 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
       
   631     snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
       
   632              "%s%s%s", state->path, ": ", msg);
       
   633 #else
       
   634     strcpy(state->msg, state->path);
       
   635     strcat(state->msg, ": ");
       
   636     strcat(state->msg, msg);
       
   637 #endif
       
   638     return;
       
   639 }
       
   640 
       
   641 #ifndef INT_MAX
       
   642 /* portably return maximum value for an int (when limits.h presumed not
       
   643    available) -- we need to do this to cover cases where 2's complement not
       
   644    used, since C standard permits 1's complement and sign-bit representations,
       
   645    otherwise we could just use ((unsigned)-1) >> 1 */
       
   646 unsigned ZLIB_INTERNAL gz_intmax()
       
   647 {
       
   648     unsigned p, q;
       
   649 
       
   650     p = 1;
       
   651     do {
       
   652         q = p;
       
   653         p <<= 1;
       
   654         p++;
       
   655     } while (p > q);
       
   656     return q >> 1;
       
   657 }
       
   658 #endif