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