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