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