1 /*
   2  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * Support for reading ZIP/JAR files.
  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <stddef.h>
  33 #include <string.h>
  34 #include <fcntl.h>
  35 #include <limits.h>
  36 #include <time.h>
  37 #include <ctype.h>
  38 #include <assert.h>
  39 
  40 #include "jni.h"
  41 #include "jni_util.h"
  42 #include "jlong.h"
  43 #include "jvm.h"
  44 #include "io_util.h"
  45 #include "io_util_md.h"
  46 #include "zip_util.h"
  47 #include <zlib.h>
  48 
  49 #ifdef _ALLBSD_SOURCE
  50 #define off64_t off_t
  51 #define mmap64 mmap
  52 #endif
  53 
  54 /* USE_MMAP means mmap the CEN & ENDHDR part of the zip file. */
  55 #ifdef USE_MMAP
  56 #include <sys/mman.h>
  57 #endif
  58 
  59 #define MAXREFS 0xFFFF  /* max number of open zip file references */
  60 
  61 #define MCREATE()      JVM_RawMonitorCreate()
  62 #define MLOCK(lock)    JVM_RawMonitorEnter(lock)
  63 #define MUNLOCK(lock)  JVM_RawMonitorExit(lock)
  64 #define MDESTROY(lock) JVM_RawMonitorDestroy(lock)
  65 
  66 #define CENSIZE(cen) (CENHDR + CENNAM(cen) + CENEXT(cen) + CENCOM(cen))
  67 
  68 static jzfile *zfiles = 0;      /* currently open zip files */
  69 static void *zfiles_lock = 0;
  70 
  71 static void freeCEN(jzfile *);
  72 
  73 #ifndef PATH_MAX
  74 #define PATH_MAX 1024
  75 #endif
  76 
  77 static jint INITIAL_META_COUNT = 2;   /* initial number of entries in meta name array */
  78 
  79 /*
  80  * The ZFILE_* functions exist to provide some platform-independence with
  81  * respect to file access needs.
  82  */
  83 
  84 /*
  85  * Opens the named file for reading, returning a ZFILE.
  86  *
  87  * Compare this with winFileHandleOpen in windows/native/java/io/io_util_md.c.
  88  * This function does not take JNIEnv* and uses CreateFile (instead of
  89  * CreateFileW).  The expectation is that this function will be called only
  90  * from ZIP_Open_Generic, which in turn is used by the JVM, where we do not
  91  * need to concern ourselves with wide chars.
  92  */
  93 static ZFILE
  94 ZFILE_Open(const char *fname, int flags) {
  95 #ifdef WIN32
  96     const DWORD access =
  97         (flags & O_RDWR)   ? (GENERIC_WRITE | GENERIC_READ) :
  98         (flags & O_WRONLY) ?  GENERIC_WRITE :
  99         GENERIC_READ;
 100     const DWORD sharing =
 101         FILE_SHARE_READ | FILE_SHARE_WRITE;
 102     const DWORD disposition =
 103         /* Note: O_TRUNC overrides O_CREAT */
 104         (flags & O_TRUNC) ? CREATE_ALWAYS :
 105         (flags & O_CREAT) ? OPEN_ALWAYS   :
 106         OPEN_EXISTING;
 107     const DWORD  maybeWriteThrough =
 108         (flags & (O_SYNC | O_DSYNC)) ?
 109         FILE_FLAG_WRITE_THROUGH :
 110         FILE_ATTRIBUTE_NORMAL;
 111     const DWORD maybeDeleteOnClose =
 112         (flags & O_TEMPORARY) ?
 113         FILE_FLAG_DELETE_ON_CLOSE :
 114         FILE_ATTRIBUTE_NORMAL;
 115     const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;
 116 
 117     return (jlong) CreateFile(
 118         fname,          /* Wide char path name */
 119         access,         /* Read and/or write permission */
 120         sharing,        /* File sharing flags */
 121         NULL,           /* Security attributes */
 122         disposition,        /* creation disposition */
 123         flagsAndAttributes, /* flags and attributes */
 124         NULL);
 125 #else
 126     return JVM_Open(fname, flags, 0);
 127 #endif
 128 }
 129 
 130 /*
 131  * The io_util_md.h files do not provide IO_CLOSE, hence we use platform
 132  * specifics.
 133  */
 134 static void
 135 ZFILE_Close(ZFILE zfd) {
 136 #ifdef WIN32
 137     CloseHandle((HANDLE) zfd);
 138 #else
 139     JVM_Close(zfd);
 140 #endif
 141 }
 142 
 143 static int
 144 ZFILE_read(ZFILE zfd, char *buf, jint nbytes) {
 145 #ifdef WIN32
 146     return (int) IO_Read(zfd, buf, nbytes);
 147 #else
 148     /*
 149      * Calling JVM_Read will return JVM_IO_INTR when Thread.interrupt is called
 150      * only on Solaris. Continue reading jar file in this case is the best
 151      * thing to do since zip file reading is relatively fast and it is very onerous
 152      * for a interrupted thread to deal with this kind of hidden I/O. However, handling
 153      * JVM_IO_INTR is tricky and could cause undesired side effect. So we decided
 154      * to simply call "read" on Solaris/Linux. See details in bug 6304463.
 155      */
 156     return read(zfd, buf, nbytes);
 157 #endif
 158 }
 159 
 160 /*
 161  * Initialize zip file support. Return 0 if successful otherwise -1
 162  * if could not be initialized.
 163  */
 164 static jint
 165 InitializeZip()
 166 {
 167     static jboolean inited = JNI_FALSE;
 168 
 169     // Initialize errno to 0.  It may be set later (e.g. during memory
 170     // allocation) but we can disregard previous values.
 171     errno = 0;
 172 
 173     if (inited)
 174         return 0;
 175     zfiles_lock = MCREATE();
 176     if (zfiles_lock == 0) {
 177         return -1;
 178     }
 179     inited = JNI_TRUE;
 180 
 181     return 0;
 182 }
 183 
 184 /*
 185  * Reads len bytes of data into buf.
 186  * Returns 0 if all bytes could be read, otherwise returns -1.
 187  */
 188 static int
 189 readFully(ZFILE zfd, void *buf, jlong len) {
 190   char *bp = (char *) buf;
 191 
 192   while (len > 0) {
 193         jlong limit = ((((jlong) 1) << 31) - 1);
 194         jint count = (len < limit) ?
 195             (jint) len :
 196             (jint) limit;
 197         jint n = ZFILE_read(zfd, bp, count);
 198         if (n > 0) {
 199             bp += n;
 200             len -= n;
 201         } else if (n == JVM_IO_ERR && errno == EINTR) {
 202           /* Retry after EINTR (interrupted by signal).
 203              We depend on the fact that JVM_IO_ERR == -1. */
 204             continue;
 205         } else { /* EOF or IO error */
 206             return -1;
 207         }
 208     }
 209     return 0;
 210 }
 211 
 212 /*
 213  * Reads len bytes of data from the specified offset into buf.
 214  * Returns 0 if all bytes could be read, otherwise returns -1.
 215  */
 216 static int
 217 readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset)
 218 {
 219     if (IO_Lseek(zfd, offset, SEEK_SET) == -1) {
 220         return -1; /* lseek failure. */
 221     }
 222 
 223     return readFully(zfd, buf, len);
 224 }
 225 
 226 /*
 227  * Allocates a new zip file object for the specified file name.
 228  * Returns the zip file object or NULL if not enough memory.
 229  */
 230 static jzfile *
 231 allocZip(const char *name)
 232 {
 233     jzfile *zip;
 234     if (((zip = calloc(1, sizeof(jzfile))) != NULL) &&
 235         ((zip->name = strdup(name))        != NULL) &&
 236         ((zip->lock = MCREATE())           != NULL)) {
 237         zip->zfd = -1;
 238         return zip;
 239     }
 240 
 241     if (zip != NULL) {
 242         free(zip->name);
 243         free(zip);
 244     }
 245     return NULL;
 246 }
 247 
 248 /*
 249  * Frees all native resources owned by the specified zip file object.
 250  */
 251 static void
 252 freeZip(jzfile *zip)
 253 {
 254     /* First free any cached jzentry */
 255     ZIP_FreeEntry(zip,0);
 256     if (zip->lock != NULL) MDESTROY(zip->lock);
 257     free(zip->name);
 258     freeCEN(zip);
 259 
 260 #ifdef USE_MMAP
 261     if (zip->usemmap) {
 262         if (zip->maddr != NULL)
 263             munmap((char *)zip->maddr, zip->mlen);
 264     } else
 265 #endif
 266     {
 267         free(zip->cencache.data);
 268     }
 269     if (zip->comment != NULL)
 270         free(zip->comment);
 271     if (zip->zfd != -1) ZFILE_Close(zip->zfd);
 272     free(zip);
 273 }
 274 
 275 /* The END header is followed by a variable length comment of size < 64k. */
 276 static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
 277 
 278 #define READBLOCKSZ 128
 279 
 280 static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) {
 281     /* ENDSIG matched, however the size of file comment in it does not
 282        match the real size. One "common" cause for this problem is some
 283        "extra" bytes are padded at the end of the zipfile.
 284        Let's do some extra verification, we don't care about the performance
 285        in this situation.
 286      */
 287     jlong cenpos = endpos - ENDSIZ(endbuf);
 288     jlong locpos = cenpos - ENDOFF(endbuf);
 289     char buf[4];
 290     return (cenpos >= 0 &&
 291             locpos >= 0 &&
 292             readFullyAt(zip->zfd, buf, sizeof(buf), cenpos) != -1 &&
 293             GETSIG(buf) == CENSIG &&
 294             readFullyAt(zip->zfd, buf, sizeof(buf), locpos) != -1 &&
 295             GETSIG(buf) == LOCSIG);
 296 }
 297 
 298 /*
 299  * Searches for end of central directory (END) header. The contents of
 300  * the END header will be read and placed in endbuf. Returns the file
 301  * position of the END header, otherwise returns -1 if the END header
 302  * was not found or an error occurred.
 303  */
 304 static jlong
 305 findEND(jzfile *zip, void *endbuf)
 306 {
 307     char buf[READBLOCKSZ];
 308     jlong pos;
 309     const jlong len = zip->len;
 310     const ZFILE zfd = zip->zfd;
 311     const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0;
 312     const jlong minPos = minHDR - (sizeof(buf)-ENDHDR);
 313     jint clen;
 314 
 315     for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) {
 316 
 317         int i;
 318         jlong off = 0;
 319         if (pos < 0) {
 320             /* Pretend there are some NUL bytes before start of file */
 321             off = -pos;
 322             memset(buf, '\0', (size_t)off);
 323         }
 324 
 325         if (readFullyAt(zfd, buf + off, sizeof(buf) - off,
 326                         pos + off) == -1) {
 327             return -1;  /* System error */
 328         }
 329 
 330         /* Now scan the block backwards for END header signature */
 331         for (i = sizeof(buf) - ENDHDR; i >= 0; i--) {
 332             if (buf[i+0] == 'P'    &&
 333                 buf[i+1] == 'K'    &&
 334                 buf[i+2] == '\005' &&
 335                 buf[i+3] == '\006' &&
 336                 ((pos + i + ENDHDR + ENDCOM(buf + i) == len)
 337                  || verifyEND(zip, pos + i, buf + i))) {
 338                 /* Found END header */
 339                 memcpy(endbuf, buf + i, ENDHDR);
 340 
 341                 clen = ENDCOM(endbuf);
 342                 if (clen != 0) {
 343                     zip->comment = malloc(clen + 1);
 344                     if (zip->comment == NULL) {
 345                         return -1;
 346                     }
 347                     if (readFullyAt(zfd, zip->comment, clen, pos + i + ENDHDR)
 348                         == -1) {
 349                         free(zip->comment);
 350                         zip->comment = NULL;
 351                         return -1;
 352                     }
 353                     zip->comment[clen] = '\0';
 354                     zip->clen = clen;
 355                 }
 356                 return pos + i;
 357             }
 358         }
 359     }
 360 
 361     return -1; /* END header not found */
 362 }
 363 
 364 /*
 365  * Searches for the ZIP64 end of central directory (END) header. The
 366  * contents of the ZIP64 END header will be read and placed in end64buf.
 367  * Returns the file position of the ZIP64 END header, otherwise returns
 368  * -1 if the END header was not found or an error occurred.
 369  *
 370  * The ZIP format specifies the "position" of each related record as
 371  *   ...
 372  *   [central directory]
 373  *   [zip64 end of central directory record]
 374  *   [zip64 end of central directory locator]
 375  *   [end of central directory record]
 376  *
 377  * The offset of zip64 end locator can be calculated from endpos as
 378  * "endpos - ZIP64_LOCHDR".
 379  * The "offset" of zip64 end record is stored in zip64 end locator.
 380  */
 381 static jlong
 382 findEND64(jzfile *zip, void *end64buf, jlong endpos)
 383 {
 384     char loc64[ZIP64_LOCHDR];
 385     jlong end64pos;
 386     if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) {
 387         return -1;    // end64 locator not found
 388     }
 389     end64pos = ZIP64_LOCOFF(loc64);
 390     if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR, end64pos) == -1) {
 391         return -1;    // end64 record not found
 392     }
 393     return end64pos;
 394 }
 395 
 396 /*
 397  * Returns a hash code value for a C-style NUL-terminated string.
 398  */
 399 static unsigned int
 400 hash(const char *s)
 401 {
 402     int h = 0;
 403     while (*s != '\0')
 404         h = 31*h + *s++;
 405     return h;
 406 }
 407 
 408 /*
 409  * Returns a hash code value for a string of a specified length.
 410  */
 411 static unsigned int
 412 hashN(const char *s, int length)
 413 {
 414     int h = 0;
 415     while (length-- > 0)
 416         h = 31*h + *s++;
 417     return h;
 418 }
 419 
 420 static unsigned int
 421 hash_append(unsigned int hash, char c)
 422 {
 423     return ((int)hash)*31 + c;
 424 }
 425 
 426 /*
 427  * Returns true if the specified entry's name begins with the string
 428  * "META-INF/" irrespective of case.
 429  */
 430 static int
 431 isMetaName(const char *name, int length)
 432 {
 433     const char *s;
 434     if (length < (int)sizeof("META-INF/") - 1)
 435         return 0;
 436     for (s = "META-INF/"; *s != '\0'; s++) {
 437         char c = *name++;
 438         // Avoid toupper; it's locale-dependent
 439         if (c >= 'a' && c <= 'z') c += 'A' - 'a';
 440         if (*s != c)
 441             return 0;
 442     }
 443     return 1;
 444 }
 445 
 446 /*
 447  * Increases the capacity of zip->metanames.
 448  * Returns non-zero in case of allocation error.
 449  */
 450 static int
 451 growMetaNames(jzfile *zip)
 452 {
 453     jint i;
 454     /* double the meta names array */
 455     const jint new_metacount = zip->metacount << 1;
 456     zip->metanames =
 457         realloc(zip->metanames, new_metacount * sizeof(zip->metanames[0]));
 458     if (zip->metanames == NULL) return -1;
 459     for (i = zip->metacount; i < new_metacount; i++)
 460         zip->metanames[i] = NULL;
 461     zip->metacurrent = zip->metacount;
 462     zip->metacount = new_metacount;
 463     return 0;
 464 }
 465 
 466 /*
 467  * Adds name to zip->metanames.
 468  * Returns non-zero in case of allocation error.
 469  */
 470 static int
 471 addMetaName(jzfile *zip, const char *name, int length)
 472 {
 473     jint i;
 474     if (zip->metanames == NULL) {
 475       zip->metacount = INITIAL_META_COUNT;
 476       zip->metanames = calloc(zip->metacount, sizeof(zip->metanames[0]));
 477       if (zip->metanames == NULL) return -1;
 478       zip->metacurrent = 0;
 479     }
 480 
 481     i = zip->metacurrent;
 482 
 483     /* current meta name array isn't full yet. */
 484     if (i < zip->metacount) {
 485       zip->metanames[i] = (char *) malloc(length+1);
 486       if (zip->metanames[i] == NULL) return -1;
 487       memcpy(zip->metanames[i], name, length);
 488       zip->metanames[i][length] = '\0';
 489       zip->metacurrent++;
 490       return 0;
 491     }
 492 
 493     /* No free entries in zip->metanames? */
 494     if (growMetaNames(zip) != 0) return -1;
 495     return addMetaName(zip, name, length);
 496 }
 497 
 498 static void
 499 freeMetaNames(jzfile *zip)
 500 {
 501     if (zip->metanames) {
 502         jint i;
 503         for (i = 0; i < zip->metacount; i++)
 504             free(zip->metanames[i]);
 505         free(zip->metanames);
 506         zip->metanames = NULL;
 507     }
 508 }
 509 
 510 /* Free Zip data allocated by readCEN() */
 511 static void
 512 freeCEN(jzfile *zip)
 513 {
 514     free(zip->entries); zip->entries = NULL;
 515     free(zip->table);   zip->table   = NULL;
 516     freeMetaNames(zip);
 517 }
 518 
 519 /*
 520  * Counts the number of CEN headers in a central directory extending
 521  * from BEG to END.  Might return a bogus answer if the zip file is
 522  * corrupt, but will not crash.
 523  */
 524 static jint
 525 countCENHeaders(unsigned char *beg, unsigned char *end)
 526 {
 527     jint count = 0;
 528     ptrdiff_t i;
 529     for (i = 0; i + CENHDR <= end - beg; i += CENSIZE(beg + i))
 530         count++;
 531     return count;
 532 }
 533 
 534 #define ZIP_FORMAT_ERROR(message) \
 535 if (1) { zip->msg = message; goto Catch; } else ((void)0)
 536 
 537 /*
 538  * Reads zip file central directory. Returns the file position of first
 539  * CEN header, otherwise returns -1 if an error occured. If zip->msg != NULL
 540  * then the error was a zip format error and zip->msg has the error text.
 541  * Always pass in -1 for knownTotal; it's used for a recursive call.
 542  */
 543 static jlong
 544 readCEN(jzfile *zip, jint knownTotal)
 545 {
 546     /* Following are unsigned 32-bit */
 547     jlong endpos, end64pos, cenpos, cenlen, cenoff;
 548     /* Following are unsigned 16-bit */
 549     jint total, tablelen, i, j;
 550     unsigned char *cenbuf = NULL;
 551     unsigned char *cenend;
 552     unsigned char *cp;
 553 #ifdef USE_MMAP
 554     static jlong pagesize;
 555     jlong offset;
 556 #endif
 557     unsigned char endbuf[ENDHDR];
 558     jint endhdrlen = ENDHDR;
 559     jzcell *entries;
 560     jint *table;
 561 
 562     /* Clear previous zip error */
 563     zip->msg = NULL;
 564     /* Get position of END header */
 565     if ((endpos = findEND(zip, endbuf)) == -1)
 566         return -1; /* no END header or system error */
 567 
 568     if (endpos == 0) return 0;  /* only END header present */
 569 
 570     freeCEN(zip);
 571    /* Get position and length of central directory */
 572     cenlen = ENDSIZ(endbuf);
 573     cenoff = ENDOFF(endbuf);
 574     total  = ENDTOT(endbuf);
 575     if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL ||
 576         total == ZIP64_MAGICCOUNT) {
 577         unsigned char end64buf[ZIP64_ENDHDR];
 578         if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
 579             cenlen = ZIP64_ENDSIZ(end64buf);
 580             cenoff = ZIP64_ENDOFF(end64buf);
 581             total = (jint)ZIP64_ENDTOT(end64buf);
 582             endpos = end64pos;
 583             endhdrlen = ZIP64_ENDHDR;
 584         }
 585     }
 586 
 587     if (cenlen > endpos)
 588         ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
 589     cenpos = endpos - cenlen;
 590 
 591     /* Get position of first local file (LOC) header, taking into
 592      * account that there may be a stub prefixed to the zip file. */
 593     zip->locpos = cenpos - cenoff;
 594     if (zip->locpos < 0)
 595         ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
 596 
 597 #ifdef USE_MMAP
 598     if (zip->usemmap) {
 599       /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to
 600        * read the jar file contents. However, this greatly increased the perceived
 601        * footprint numbers because the mmap'ed pages were adding into the totals shown
 602        * by 'ps' and 'top'. We switched to mmaping only the central directory of jar
 603        * file while calling 'read' to read the rest of jar file. Here are a list of
 604        * reasons apart from above of why we are doing so:
 605        * 1. Greatly reduces mmap overhead after startup complete;
 606        * 2. Avoids dual path code maintainance;
 607        * 3. Greatly reduces risk of address space (not virtual memory) exhaustion.
 608        */
 609         if (pagesize == 0) {
 610             pagesize = (jlong)sysconf(_SC_PAGESIZE);
 611             if (pagesize == 0) goto Catch;
 612         }
 613         if (cenpos > pagesize) {
 614             offset = cenpos & ~(pagesize - 1);
 615         } else {
 616             offset = 0;
 617         }
 618         /* When we are not calling recursively, knownTotal is -1. */
 619         if (knownTotal == -1) {
 620             void* mappedAddr;
 621             /* Mmap the CEN and END part only. We have to figure
 622                out the page size in order to make offset to be multiples of
 623                page size.
 624             */
 625             zip->mlen = cenpos - offset + cenlen + endhdrlen;
 626             zip->offset = offset;
 627             mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
 628             zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
 629                 (unsigned char*)mappedAddr;
 630 
 631             if (zip->maddr == NULL) {
 632                 jio_fprintf(stderr, "mmap failed for CEN and END part of zip file\n");
 633                 goto Catch;
 634             }
 635         }
 636         cenbuf = zip->maddr + cenpos - offset;
 637     } else
 638 #endif
 639     {
 640         if ((cenbuf = malloc((size_t) cenlen)) == NULL ||
 641             (readFullyAt(zip->zfd, cenbuf, cenlen, cenpos) == -1))
 642         goto Catch;
 643     }
 644 
 645     cenend = cenbuf + cenlen;
 646 
 647     /* Initialize zip file data structures based on the total number
 648      * of central directory entries as stored in ENDTOT.  Since this
 649      * is a 2-byte field, but we (and other zip implementations)
 650      * support approx. 2**31 entries, we do not trust ENDTOT, but
 651      * treat it only as a strong hint.  When we call ourselves
 652      * recursively, knownTotal will have the "true" value.
 653      *
 654      * Keep this path alive even with the Zip64 END support added, just
 655      * for zip files that have more than 0xffff entries but don't have
 656      * the Zip64 enabled.
 657      */
 658     total = (knownTotal != -1) ? knownTotal : total;
 659     entries  = zip->entries  = calloc(total, sizeof(entries[0]));
 660     tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
 661     table    = zip->table    = malloc(tablelen * sizeof(table[0]));
 662     if (entries == NULL || table == NULL) goto Catch;
 663     for (j = 0; j < tablelen; j++)
 664         table[j] = ZIP_ENDCHAIN;
 665 
 666     /* Iterate through the entries in the central directory */
 667     for (i = 0, cp = cenbuf; cp <= cenend - CENHDR; i++, cp += CENSIZE(cp)) {
 668         /* Following are unsigned 16-bit */
 669         jint method, nlen;
 670         unsigned int hsh;
 671 
 672         if (i >= total) {
 673             /* This will only happen if the zip file has an incorrect
 674              * ENDTOT field, which usually means it contains more than
 675              * 65535 entries. */
 676             cenpos = readCEN(zip, countCENHeaders(cenbuf, cenend));
 677             goto Finally;
 678         }
 679 
 680         method = CENHOW(cp);
 681         nlen   = CENNAM(cp);
 682 
 683         if (GETSIG(cp) != CENSIG)
 684             ZIP_FORMAT_ERROR("invalid CEN header (bad signature)");
 685         if (CENFLG(cp) & 1)
 686             ZIP_FORMAT_ERROR("invalid CEN header (encrypted entry)");
 687         if (method != STORED && method != DEFLATED)
 688             ZIP_FORMAT_ERROR("invalid CEN header (bad compression method)");
 689         if (cp + CENHDR + nlen > cenend)
 690             ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
 691 
 692         /* if the entry is metadata add it to our metadata names */
 693         if (isMetaName((char *)cp+CENHDR, nlen))
 694             if (addMetaName(zip, (char *)cp+CENHDR, nlen) != 0)
 695                 goto Catch;
 696 
 697         /* Record the CEN offset and the name hash in our hash cell. */
 698         entries[i].cenpos = cenpos + (cp - cenbuf);
 699         entries[i].hash = hashN((char *)cp+CENHDR, nlen);
 700 
 701         /* Add the entry to the hash table */
 702         hsh = entries[i].hash % tablelen;
 703         entries[i].next = table[hsh];
 704         table[hsh] = i;
 705     }
 706     if (cp != cenend)
 707         ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
 708 
 709     zip->total = i;
 710     goto Finally;
 711 
 712  Catch:
 713     freeCEN(zip);
 714     cenpos = -1;
 715 
 716  Finally:
 717 #ifdef USE_MMAP
 718     if (!zip->usemmap)
 719 #endif
 720         free(cenbuf);
 721 
 722     return cenpos;
 723 }
 724 
 725 /*
 726  * Opens a zip file with the specified mode. Returns the jzfile object
 727  * or NULL if an error occurred. If a zip error occurred then *pmsg will
 728  * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be
 729  * set to NULL. Caller is responsible to free the error message.
 730  */
 731 jzfile *
 732 ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified)
 733 {
 734     jzfile *zip = NULL;
 735 
 736     /* Clear zip error message */
 737     if (pmsg != 0) {
 738         *pmsg = NULL;
 739     }
 740 
 741     zip = ZIP_Get_From_Cache(name, pmsg, lastModified);
 742 
 743     if (zip == NULL && *pmsg == NULL) {
 744         ZFILE zfd = ZFILE_Open(name, mode);
 745         zip = ZIP_Put_In_Cache(name, zfd, pmsg, lastModified);
 746     }
 747     return zip;
 748 }
 749 
 750 /*
 751  * Returns the jzfile corresponding to the given file name from the cache of
 752  * zip files, or NULL if the file is not in the cache.  If the name is longer
 753  * than PATH_MAX or a zip error occurred then *pmsg will be set to the error
 754  * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller
 755  * is responsible to free the error message.
 756  */
 757 jzfile *
 758 ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified)
 759 {
 760     char buf[PATH_MAX];
 761     jzfile *zip;
 762 
 763     if (InitializeZip()) {
 764         return NULL;
 765     }
 766 
 767     /* Clear zip error message */
 768     if (pmsg != 0) {
 769         *pmsg = NULL;
 770     }
 771 
 772     if (strlen(name) >= PATH_MAX) {
 773         if (pmsg) {
 774             *pmsg = strdup("zip file name too long");
 775         }
 776         return NULL;
 777     }
 778     strcpy(buf, name);
 779     JVM_NativePath(buf);
 780     name = buf;
 781 
 782     MLOCK(zfiles_lock);
 783     for (zip = zfiles; zip != NULL; zip = zip->next) {
 784         if (strcmp(name, zip->name) == 0
 785             && (zip->lastModified == lastModified || zip->lastModified == 0)
 786             && zip->refs < MAXREFS) {
 787             zip->refs++;
 788             break;
 789         }
 790     }
 791     MUNLOCK(zfiles_lock);
 792     return zip;
 793 }
 794 
 795 /*
 796  * Reads data from the given file descriptor to create a jzfile, puts the
 797  * jzfile in a cache, and returns that jzfile.  Returns NULL in case of error.
 798  * If a zip error occurs, then *pmsg will be set to the error message text if
 799  * pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller is responsible to
 800  * free the error message.
 801  */
 802 
 803 jzfile *
 804 ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified)
 805 {
 806     return ZIP_Put_In_Cache0(name, zfd, pmsg, lastModified, JNI_TRUE);
 807 }
 808 
 809 jzfile *
 810 ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified,
 811                  jboolean usemmap)
 812 {
 813     char errbuf[256];
 814     jlong len;
 815     jzfile *zip;
 816 
 817     if ((zip = allocZip(name)) == NULL) {
 818         return NULL;
 819     }
 820 
 821 #ifdef USE_MMAP
 822     zip->usemmap = usemmap;
 823 #endif
 824     zip->refs = 1;
 825     zip->lastModified = lastModified;
 826 
 827     if (zfd == -1) {
 828         if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
 829             *pmsg = strdup(errbuf);
 830         freeZip(zip);
 831         return NULL;
 832     }
 833 
 834     len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
 835     if (len <= 0) {
 836         if (len == 0) { /* zip file is empty */
 837             if (pmsg) {
 838                 *pmsg = strdup("zip file is empty");
 839             }
 840         } else { /* error */
 841             if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
 842                 *pmsg = strdup(errbuf);
 843         }
 844         ZFILE_Close(zfd);
 845         freeZip(zip);
 846         return NULL;
 847     }
 848 
 849     zip->zfd = zfd;
 850     if (readCEN(zip, -1) < 0) {
 851         /* An error occurred while trying to read the zip file */
 852         if (pmsg != 0) {
 853             /* Set the zip error message */
 854             if (zip->msg != NULL)
 855                 *pmsg = strdup(zip->msg);
 856         }
 857         freeZip(zip);
 858         return NULL;
 859     }
 860     MLOCK(zfiles_lock);
 861     zip->next = zfiles;
 862     zfiles = zip;
 863     MUNLOCK(zfiles_lock);
 864 
 865     return zip;
 866 }
 867 
 868 /*
 869  * Opens a zip file for reading. Returns the jzfile object or NULL
 870  * if an error occurred. If a zip error occurred then *msg will be
 871  * set to the error message text if msg != 0. Otherwise, *msg will be
 872  * set to NULL. Caller doesn't need to free the error message.
 873  */
 874 jzfile * JNICALL
 875 ZIP_Open(const char *name, char **pmsg)
 876 {
 877     jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0);
 878     if (file == NULL && pmsg != NULL && *pmsg != NULL) {
 879         free(*pmsg);
 880         *pmsg = "Zip file open error";
 881     }
 882     return file;
 883 }
 884 
 885 /*
 886  * Closes the specified zip file object.
 887  */
 888 void JNICALL
 889 ZIP_Close(jzfile *zip)
 890 {
 891     MLOCK(zfiles_lock);
 892     if (--zip->refs > 0) {
 893         /* Still more references so just return */
 894         MUNLOCK(zfiles_lock);
 895         return;
 896     }
 897     /* No other references so close the file and remove from list */
 898     if (zfiles == zip) {
 899         zfiles = zfiles->next;
 900     } else {
 901         jzfile *zp;
 902         for (zp = zfiles; zp->next != 0; zp = zp->next) {
 903             if (zp->next == zip) {
 904                 zp->next = zip->next;
 905                 break;
 906             }
 907         }
 908     }
 909     MUNLOCK(zfiles_lock);
 910     freeZip(zip);
 911     return;
 912 }
 913 
 914 /* Empirically, most CEN headers are smaller than this. */
 915 #define AMPLE_CEN_HEADER_SIZE 160
 916 
 917 /* A good buffer size when we want to read CEN headers sequentially. */
 918 #define CENCACHE_PAGESIZE 8192
 919 
 920 static char *
 921 readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
 922 {
 923     jint censize;
 924     ZFILE zfd = zip->zfd;
 925     char *cen;
 926     if (bufsize > zip->len - cenpos)
 927         bufsize = (jint)(zip->len - cenpos);
 928     if ((cen = malloc(bufsize)) == NULL)       goto Catch;
 929     if (readFullyAt(zfd, cen, bufsize, cenpos) == -1)     goto Catch;
 930     censize = CENSIZE(cen);
 931     if (censize <= bufsize) return cen;
 932     if ((cen = realloc(cen, censize)) == NULL)              goto Catch;
 933     if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;
 934     return cen;
 935 
 936  Catch:
 937     free(cen);
 938     return NULL;
 939 }
 940 
 941 static char *
 942 sequentialAccessReadCENHeader(jzfile *zip, jlong cenpos)
 943 {
 944     cencache *cache = &zip->cencache;
 945     char *cen;
 946     if (cache->data != NULL
 947         && (cenpos >= cache->pos)
 948         && (cenpos + CENHDR <= cache->pos + CENCACHE_PAGESIZE))
 949     {
 950         cen = cache->data + cenpos - cache->pos;
 951         if (cenpos + CENSIZE(cen) <= cache->pos + CENCACHE_PAGESIZE)
 952             /* A cache hit */
 953             return cen;
 954     }
 955 
 956     if ((cen = readCENHeader(zip, cenpos, CENCACHE_PAGESIZE)) == NULL)
 957         return NULL;
 958     free(cache->data);
 959     cache->data = cen;
 960     cache->pos  = cenpos;
 961     return cen;
 962 }
 963 
 964 typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint;
 965 
 966 /*
 967  * Return a new initialized jzentry corresponding to a given hash cell.
 968  * In case of error, returns NULL.
 969  * We already sanity-checked all the CEN headers for ZIP format errors
 970  * in readCEN(), so we don't check them again here.
 971  * The ZIP lock should be held here.
 972  */
 973 static jzentry *
 974 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
 975 {
 976     jlong locoff;
 977     jint nlen, elen, clen;
 978     jzentry *ze;
 979     char *cen;
 980 
 981     if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL;
 982     ze->name    = NULL;
 983     ze->extra   = NULL;
 984     ze->comment = NULL;
 985 
 986 #ifdef USE_MMAP
 987     if (zip->usemmap) {
 988         cen = (char*) zip->maddr + zc->cenpos - zip->offset;
 989     } else
 990 #endif
 991     {
 992         if (accessHint == ACCESS_RANDOM)
 993             cen = readCENHeader(zip, zc->cenpos, AMPLE_CEN_HEADER_SIZE);
 994         else
 995             cen = sequentialAccessReadCENHeader(zip, zc->cenpos);
 996         if (cen == NULL) goto Catch;
 997     }
 998 
 999     nlen      = CENNAM(cen);
1000     elen      = CENEXT(cen);
1001     clen      = CENCOM(cen);
1002     ze->time  = CENTIM(cen);
1003     ze->size  = CENLEN(cen);
1004     ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
1005     ze->crc   = CENCRC(cen);
1006     locoff    = CENOFF(cen);
1007     ze->pos   = -(zip->locpos + locoff);
1008     ze->flag  = CENFLG(cen);
1009 
1010     if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
1011     memcpy(ze->name, cen + CENHDR, nlen);
1012     ze->name[nlen] = '\0';
1013     if (elen > 0) {
1014         char *extra = cen + CENHDR + nlen;
1015 
1016         /* This entry has "extra" data */
1017         if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
1018         ze->extra[0] = (unsigned char) elen;
1019         ze->extra[1] = (unsigned char) (elen >> 8);
1020         memcpy(ze->extra+2, extra, elen);
1021         if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
1022             locoff == ZIP64_MAGICVAL) {
1023             jint off = 0;
1024             while ((off + 4) < elen) {    // spec: HeaderID+DataSize+Data
1025                 jint sz = SH(extra, off + 2);
1026                 if (SH(extra, off) == ZIP64_EXTID) {
1027                     off += 4;
1028                     if (ze->size == ZIP64_MAGICVAL) {
1029                         // if invalid zip64 extra fields, just skip
1030                         if (sz < 8 || (off + 8) > elen)
1031                             break;
1032                         ze->size = LL(extra, off);
1033                         sz -= 8;
1034                         off += 8;
1035                     }
1036                     if (ze->csize == ZIP64_MAGICVAL) {
1037                         if (sz < 8 || (off + 8) > elen)
1038                             break;
1039                         ze->csize = LL(extra, off);
1040                         sz -= 8;
1041                         off += 8;
1042                     }
1043                     if (locoff == ZIP64_MAGICVAL) {
1044                         if (sz < 8 || (off + 8) > elen)
1045                             break;
1046                         ze->pos = -(zip->locpos +  LL(extra, off));
1047                         sz -= 8;
1048                         off += 8;
1049                     }
1050                     break;
1051                 }
1052                 off += (sz + 4);
1053             }
1054         }
1055     }
1056 
1057     if (clen > 0) {
1058         /* This entry has a comment */
1059         if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch;
1060         memcpy(ze->comment, cen + CENHDR + nlen + elen, clen);
1061         ze->comment[clen] = '\0';
1062     }
1063     goto Finally;
1064 
1065  Catch:
1066     free(ze->name);
1067     free(ze->extra);
1068     free(ze->comment);
1069     free(ze);
1070     ze = NULL;
1071 
1072  Finally:
1073 #ifdef USE_MMAP
1074     if (!zip->usemmap)
1075 #endif
1076         if (cen != NULL && accessHint == ACCESS_RANDOM) free(cen);
1077     return ze;
1078 }
1079 
1080 /*
1081  * Free the given jzentry.
1082  * In fact we maintain a one-entry cache of the most recently used
1083  * jzentry for each zip.  This optimizes a common access pattern.
1084  */
1085 
1086 void
1087 ZIP_FreeEntry(jzfile *jz, jzentry *ze)
1088 {
1089     jzentry *last;
1090     ZIP_Lock(jz);
1091     last = jz->cache;
1092     jz->cache = ze;
1093     ZIP_Unlock(jz);
1094     if (last != NULL) {
1095         /* Free the previously cached jzentry */
1096         free(last->name);
1097         if (last->extra)   free(last->extra);
1098         if (last->comment) free(last->comment);
1099         free(last);
1100     }
1101 }
1102 
1103 /*
1104  * Returns the zip entry corresponding to the specified name, or
1105  * NULL if not found.
1106  */
1107 jzentry *
1108 ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
1109 {
1110     unsigned int hsh = hash(name);
1111     jint idx;
1112     jzentry *ze = 0;
1113 
1114     ZIP_Lock(zip);
1115     if (zip->total == 0) {
1116         goto Finally;
1117     }
1118 
1119     idx = zip->table[hsh % zip->tablelen];
1120 
1121     /*
1122      * This while loop is an optimization where a double lookup
1123      * for name and name+/ is being performed. The name char
1124      * array has enough room at the end to try again with a
1125      * slash appended if the first table lookup does not succeed.
1126      */
1127     while(1) {
1128 
1129         /* Check the cached entry first */
1130         ze = zip->cache;
1131         if (ze && strcmp(ze->name,name) == 0) {
1132             /* Cache hit!  Remove and return the cached entry. */
1133             zip->cache = 0;
1134             ZIP_Unlock(zip);
1135             return ze;
1136         }
1137         ze = 0;
1138 
1139         /*
1140          * Search down the target hash chain for a cell whose
1141          * 32 bit hash matches the hashed name.
1142          */
1143         while (idx != ZIP_ENDCHAIN) {
1144             jzcell *zc = &zip->entries[idx];
1145 
1146             if (zc->hash == hsh) {
1147                 /*
1148                  * OK, we've found a ZIP entry whose 32 bit hashcode
1149                  * matches the name we're looking for.  Try to read
1150                  * its entry information from the CEN.  If the CEN
1151                  * name matches the name we're looking for, we're
1152                  * done.
1153                  * If the names don't match (which should be very rare)
1154                  * we keep searching.
1155                  */
1156                 ze = newEntry(zip, zc, ACCESS_RANDOM);
1157                 if (ze && strcmp(ze->name, name)==0) {
1158                     break;
1159                 }
1160                 if (ze != 0) {
1161                     /* We need to release the lock across the free call */
1162                     ZIP_Unlock(zip);
1163                     ZIP_FreeEntry(zip, ze);
1164                     ZIP_Lock(zip);
1165                 }
1166                 ze = 0;
1167             }
1168             idx = zc->next;
1169         }
1170 
1171         /* Entry found, return it */
1172         if (ze != 0) {
1173             break;
1174         }
1175 
1176         /* If no real length was passed in, we are done */
1177         if (ulen == 0) {
1178             break;
1179         }
1180 
1181         /* Slash is already there? */
1182         if (name[ulen-1] == '/') {
1183             break;
1184         }
1185 
1186         /* Add slash and try once more */
1187         name[ulen] = '/';
1188         name[ulen+1] = '\0';
1189         hsh = hash_append(hsh, '/');
1190         idx = zip->table[hsh % zip->tablelen];
1191         ulen = 0;
1192     }
1193 
1194 Finally:
1195     ZIP_Unlock(zip);
1196     return ze;
1197 }
1198 
1199 /*
1200  * Returns the n'th (starting at zero) zip file entry, or NULL if the
1201  * specified index was out of range.
1202  */
1203 jzentry * JNICALL
1204 ZIP_GetNextEntry(jzfile *zip, jint n)
1205 {
1206     jzentry *result;
1207     if (n < 0 || n >= zip->total) {
1208         return 0;
1209     }
1210     ZIP_Lock(zip);
1211     result = newEntry(zip, &zip->entries[n], ACCESS_SEQUENTIAL);
1212     ZIP_Unlock(zip);
1213     return result;
1214 }
1215 
1216 /*
1217  * Locks the specified zip file for reading.
1218  */
1219 void
1220 ZIP_Lock(jzfile *zip)
1221 {
1222     MLOCK(zip->lock);
1223 }
1224 
1225 /*
1226  * Unlocks the specified zip file.
1227  */
1228 void
1229 ZIP_Unlock(jzfile *zip)
1230 {
1231     MUNLOCK(zip->lock);
1232 }
1233 
1234 /*
1235  * Returns the offset of the entry data within the zip file.
1236  * Returns -1 if an error occurred, in which case zip->msg will
1237  * contain the error text.
1238  */
1239 jlong
1240 ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry)
1241 {
1242     /* The Zip file spec explicitly allows the LOC extra data size to
1243      * be different from the CEN extra data size, although the JDK
1244      * never creates such zip files.  Since we cannot trust the CEN
1245      * extra data size, we need to read the LOC to determine the entry
1246      * data offset.  We do this lazily to avoid touching the virtual
1247      * memory page containing the LOC when initializing jzentry
1248      * objects.  (This speeds up javac by a factor of 10 when the JDK
1249      * is installed on a very slow filesystem.)
1250      */
1251     if (entry->pos <= 0) {
1252         unsigned char loc[LOCHDR];
1253         if (readFullyAt(zip->zfd, loc, LOCHDR, -(entry->pos)) == -1) {
1254             zip->msg = "error reading zip file";
1255             return -1;
1256         }
1257         if (GETSIG(loc) != LOCSIG) {
1258             zip->msg = "invalid LOC header (bad signature)";
1259             return -1;
1260         }
1261         entry->pos = (- entry->pos) + LOCHDR + LOCNAM(loc) + LOCEXT(loc);
1262     }
1263     return entry->pos;
1264 }
1265 
1266 /*
1267  * Reads bytes from the specified zip entry. Assumes that the zip
1268  * file had been previously locked with ZIP_Lock(). Returns the
1269  * number of bytes read, or -1 if an error occurred. If zip->msg != 0
1270  * then a zip error occurred and zip->msg contains the error text.
1271  *
1272  * The current implementation does not support reading an entry that
1273  * has the size bigger than 2**32 bytes in ONE invocation.
1274  */
1275 jint
1276 ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
1277 {
1278     jlong entry_size = (entry->csize != 0) ? entry->csize : entry->size;
1279     jlong start;
1280 
1281     /* Clear previous zip error */
1282     zip->msg = NULL;
1283 
1284     /* Check specified position */
1285     if (pos < 0 || pos > entry_size - 1) {
1286         zip->msg = "ZIP_Read: specified offset out of range";
1287         return -1;
1288     }
1289 
1290     /* Check specified length */
1291     if (len <= 0)
1292         return 0;
1293     if (len > entry_size - pos)
1294         len = (jint)(entry_size - pos);
1295 
1296     /* Get file offset to start reading data */
1297     start = ZIP_GetEntryDataOffset(zip, entry);
1298     if (start < 0)
1299         return -1;
1300     start += pos;
1301 
1302     if (start + len > zip->len) {
1303         zip->msg = "ZIP_Read: corrupt zip file: invalid entry size";
1304         return -1;
1305     }
1306 
1307     if (readFullyAt(zip->zfd, buf, len, start) == -1) {
1308         zip->msg = "ZIP_Read: error reading zip file";
1309         return -1;
1310     }
1311     return len;
1312 }
1313 
1314 
1315 /* The maximum size of a stack-allocated buffer.
1316  */
1317 #define BUF_SIZE 4096
1318 
1319 /*
1320  * This function is used by the runtime system to load compressed entries
1321  * from ZIP/JAR files specified in the class path. It is defined here
1322  * so that it can be dynamically loaded by the runtime if the zip library
1323  * is found.
1324  *
1325  * The current implementation does not support reading an entry that
1326  * has the size bigger than 2**32 bytes in ONE invocation.
1327  */
1328 jboolean
1329 InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
1330 {
1331     z_stream strm;
1332     char tmp[BUF_SIZE];
1333     jlong pos = 0;
1334     jlong count = entry->csize;
1335 
1336     *msg = 0; /* Reset error message */
1337 
1338     if (count == 0) {
1339         *msg = "inflateFully: entry not compressed";
1340         return JNI_FALSE;
1341     }
1342 
1343     memset(&strm, 0, sizeof(z_stream));
1344     if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
1345         *msg = strm.msg;
1346         return JNI_FALSE;
1347     }
1348 
1349     strm.next_out = buf;
1350     strm.avail_out = (uInt)entry->size;
1351 
1352     while (count > 0) {
1353         jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : (jint)count;
1354         ZIP_Lock(zip);
1355         n = ZIP_Read(zip, entry, pos, tmp, n);
1356         ZIP_Unlock(zip);
1357         if (n <= 0) {
1358             if (n == 0) {
1359                 *msg = "inflateFully: Unexpected end of file";
1360             }
1361             inflateEnd(&strm);
1362             return JNI_FALSE;
1363         }
1364         pos += n;
1365         count -= n;
1366         strm.next_in = (Bytef *)tmp;
1367         strm.avail_in = n;
1368         do {
1369             switch (inflate(&strm, Z_PARTIAL_FLUSH)) {
1370             case Z_OK:
1371                 break;
1372             case Z_STREAM_END:
1373                 if (count != 0 || strm.total_out != entry->size) {
1374                     *msg = "inflateFully: Unexpected end of stream";
1375                     inflateEnd(&strm);
1376                     return JNI_FALSE;
1377                 }
1378                 break;
1379             default:
1380                 break;
1381             }
1382         } while (strm.avail_in > 0);
1383     }
1384     inflateEnd(&strm);
1385     return JNI_TRUE;
1386 }
1387 
1388 /*
1389  * The current implementation does not support reading an entry that
1390  * has the size bigger than 2**32 bytes in ONE invocation.
1391  */
1392 jzentry * JNICALL
1393 ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
1394 {
1395     jzentry *entry = ZIP_GetEntry(zip, name, 0);
1396     if (entry) {
1397         *sizeP = (jint)entry->size;
1398         *nameLenP = strlen(entry->name);
1399     }
1400     return entry;
1401 }
1402 
1403 /*
1404  * Reads a zip file entry into the specified byte array
1405  * When the method completes, it releases the jzentry.
1406  * Note: this is called from the separately delivered VM (hotspot/classic)
1407  * so we have to be careful to maintain the expected behaviour.
1408  */
1409 jboolean JNICALL
1410 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
1411 {
1412     char *msg;
1413 
1414     strcpy(entryname, entry->name);
1415     if (entry->csize == 0) {
1416         /* Entry is stored */
1417         jlong pos = 0;
1418         jlong size = entry->size;
1419         while (pos < size) {
1420             jint n;
1421             jlong limit = ((((jlong) 1) << 31) - 1);
1422             jint count = (size - pos < limit) ?
1423                 /* These casts suppress a VC++ Internal Compiler Error */
1424                 (jint) (size - pos) :
1425                 (jint) limit;
1426             ZIP_Lock(zip);
1427             n = ZIP_Read(zip, entry, pos, buf, count);
1428             msg = zip->msg;
1429             ZIP_Unlock(zip);
1430             if (n == -1) {
1431                 jio_fprintf(stderr, "%s: %s\n", zip->name,
1432                             msg != 0 ? msg : strerror(errno));
1433                 return JNI_FALSE;
1434             }
1435             buf += n;
1436             pos += n;
1437         }
1438     } else {
1439         /* Entry is compressed */
1440         int ok = InflateFully(zip, entry, buf, &msg);
1441         if (!ok) {
1442             if ((msg == NULL) || (*msg == 0)) {
1443                 msg = zip->msg;
1444             }
1445             jio_fprintf(stderr, "%s: %s\n", zip->name,
1446                         msg != 0 ? msg : strerror(errno));
1447             return JNI_FALSE;
1448         }
1449     }
1450 
1451     ZIP_FreeEntry(zip, entry);
1452 
1453     return JNI_TRUE;
1454 }