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 (method != STORED && method != DEFLATED)
 680             ZIP_FORMAT_ERROR("invalid CEN header (bad compression method)");
 681         if (cp + CENHDR + nlen > cenend)
 682             ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
 683 
 684         /* if the entry is metadata add it to our metadata names */
 685         if (isMetaName((char *)cp+CENHDR, nlen))
 686             if (addMetaName(zip, (char *)cp+CENHDR, nlen) != 0)
 687                 goto Catch;
 688 
 689         /* Record the CEN offset and the name hash in our hash cell. */
 690         entries[i].cenpos = cenpos + (cp - cenbuf);
 691         entries[i].hash = hashN((char *)cp+CENHDR, nlen);
 692 
 693         /* Add the entry to the hash table */
 694         hsh = entries[i].hash % tablelen;
 695         entries[i].next = table[hsh];
 696         table[hsh] = i;
 697     }
 698     if (cp != cenend)
 699         ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
 700 
 701     zip->total = i;
 702     goto Finally;
 703 
 704  Catch:
 705     freeCEN(zip);
 706     cenpos = -1;
 707 
 708  Finally:
 709 #ifdef USE_MMAP
 710     if (!zip->usemmap)
 711 #endif
 712         free(cenbuf);
 713 
 714     return cenpos;
 715 }
 716 
 717 /*
 718  * Opens a zip file with the specified mode. Returns the jzfile object
 719  * or NULL if an error occurred. If a zip error occurred then *pmsg will
 720  * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be
 721  * set to NULL. Caller is responsible to free the error message.
 722  */
 723 jzfile *
 724 ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified)
 725 {
 726     jzfile *zip = NULL;
 727 
 728     /* Clear zip error message */
 729     if (pmsg != 0) {
 730         *pmsg = NULL;
 731     }
 732 
 733     zip = ZIP_Get_From_Cache(name, pmsg, lastModified);
 734 
 735     if (zip == NULL && *pmsg == NULL) {
 736         ZFILE zfd = ZFILE_Open(name, mode);
 737         zip = ZIP_Put_In_Cache(name, zfd, pmsg, lastModified);
 738     }
 739     return zip;
 740 }
 741 
 742 /*
 743  * Returns the jzfile corresponding to the given file name from the cache of
 744  * zip files, or NULL if the file is not in the cache.  If the name is longer
 745  * than PATH_MAX or a zip error occurred then *pmsg will be set to the error
 746  * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller
 747  * is responsible to free the error message.
 748  */
 749 jzfile *
 750 ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified)
 751 {
 752     char buf[PATH_MAX];
 753     jzfile *zip;
 754 
 755     if (InitializeZip()) {
 756         return NULL;
 757     }
 758 
 759     /* Clear zip error message */
 760     if (pmsg != 0) {
 761         *pmsg = NULL;
 762     }
 763 
 764     if (strlen(name) >= PATH_MAX) {
 765         if (pmsg) {
 766             *pmsg = strdup("zip file name too long");
 767         }
 768         return NULL;
 769     }
 770     strcpy(buf, name);
 771     JVM_NativePath(buf);
 772     name = buf;
 773 
 774     MLOCK(zfiles_lock);
 775     for (zip = zfiles; zip != NULL; zip = zip->next) {
 776         if (strcmp(name, zip->name) == 0
 777             && (zip->lastModified == lastModified || zip->lastModified == 0)
 778             && zip->refs < MAXREFS) {
 779             zip->refs++;
 780             break;
 781         }
 782     }
 783     MUNLOCK(zfiles_lock);
 784     return zip;
 785 }
 786 
 787 /*
 788  * Reads data from the given file descriptor to create a jzfile, puts the
 789  * jzfile in a cache, and returns that jzfile.  Returns NULL in case of error.
 790  * If a zip error occurs, then *pmsg will be set to the error message text if
 791  * pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller is responsible to
 792  * free the error message.
 793  */
 794 
 795 jzfile *
 796 ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified)
 797 {
 798     return ZIP_Put_In_Cache0(name, zfd, pmsg, lastModified, JNI_TRUE);
 799 }
 800 
 801 jzfile *
 802 ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified,
 803                  jboolean usemmap)
 804 {
 805     char errbuf[256];
 806     jlong len;
 807     jzfile *zip;
 808 
 809     if ((zip = allocZip(name)) == NULL) {
 810         return NULL;
 811     }
 812 
 813 #ifdef USE_MMAP
 814     zip->usemmap = usemmap;
 815 #endif
 816     zip->refs = 1;
 817     zip->lastModified = lastModified;
 818 
 819     if (zfd == -1) {
 820         if (pmsg && getLastErrorString(errbuf, sizeof(errbuf)) > 0)
 821             *pmsg = strdup(errbuf);
 822         freeZip(zip);
 823         return NULL;
 824     }
 825 
 826     // Assumption, zfd refers to start of file. Trivially, reuse errbuf.
 827     if (readFully(zfd, errbuf, 4) != -1) {  // errors will be handled later
 828         zip->locsig = LOCSIG_AT(errbuf) ? JNI_TRUE : JNI_FALSE;
 829     }
 830 
 831     len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
 832     if (len <= 0) {
 833         if (len == 0) { /* zip file is empty */
 834             if (pmsg) {
 835                 *pmsg = strdup("zip file is empty");
 836             }
 837         } else { /* error */
 838             if (pmsg && getLastErrorString(errbuf, sizeof(errbuf)) > 0)
 839                 *pmsg = strdup(errbuf);
 840         }
 841         ZFILE_Close(zfd);
 842         freeZip(zip);
 843         return NULL;
 844     }
 845 
 846     zip->zfd = zfd;
 847     if (readCEN(zip, -1) < 0) {
 848         /* An error occurred while trying to read the zip file */
 849         if (pmsg != 0) {
 850             /* Set the zip error message */
 851             if (zip->msg != NULL)
 852                 *pmsg = strdup(zip->msg);
 853         }
 854         freeZip(zip);
 855         return NULL;
 856     }
 857     MLOCK(zfiles_lock);
 858     zip->next = zfiles;
 859     zfiles = zip;
 860     MUNLOCK(zfiles_lock);
 861 
 862     return zip;
 863 }
 864 
 865 /*
 866  * Opens a zip file for reading. Returns the jzfile object or NULL
 867  * if an error occurred. If a zip error occurred then *msg will be
 868  * set to the error message text if msg != 0. Otherwise, *msg will be
 869  * set to NULL. Caller doesn't need to free the error message.
 870  */
 871 jzfile * JNICALL
 872 ZIP_Open(const char *name, char **pmsg)
 873 {
 874     jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0);
 875     if (file == NULL && pmsg != NULL && *pmsg != NULL) {
 876         free(*pmsg);
 877         *pmsg = "Zip file open error";
 878     }
 879     return file;
 880 }
 881 
 882 /*
 883  * Closes the specified zip file object.
 884  */
 885 void JNICALL
 886 ZIP_Close(jzfile *zip)
 887 {
 888     MLOCK(zfiles_lock);
 889     if (--zip->refs > 0) {
 890         /* Still more references so just return */
 891         MUNLOCK(zfiles_lock);
 892         return;
 893     }
 894     /* No other references so close the file and remove from list */
 895     if (zfiles == zip) {
 896         zfiles = zfiles->next;
 897     } else {
 898         jzfile *zp;
 899         for (zp = zfiles; zp->next != 0; zp = zp->next) {
 900             if (zp->next == zip) {
 901                 zp->next = zip->next;
 902                 break;
 903             }
 904         }
 905     }
 906     MUNLOCK(zfiles_lock);
 907     freeZip(zip);
 908     return;
 909 }
 910 
 911 /* Empirically, most CEN headers are smaller than this. */
 912 #define AMPLE_CEN_HEADER_SIZE 160
 913 
 914 /* A good buffer size when we want to read CEN headers sequentially. */
 915 #define CENCACHE_PAGESIZE 8192
 916 
 917 static char *
 918 readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
 919 {
 920     jint censize;
 921     ZFILE zfd = zip->zfd;
 922     char *cen;
 923     if (bufsize > zip->len - cenpos)
 924         bufsize = (jint)(zip->len - cenpos);
 925     if ((cen = malloc(bufsize)) == NULL)       goto Catch;
 926     if (readFullyAt(zfd, cen, bufsize, cenpos) == -1)     goto Catch;
 927     censize = CENSIZE(cen);
 928     if (censize <= bufsize) return cen;
 929     if ((cen = realloc(cen, censize)) == NULL)              goto Catch;
 930     if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;
 931     return cen;
 932 
 933  Catch:
 934     free(cen);
 935     return NULL;
 936 }
 937 
 938 static char *
 939 sequentialAccessReadCENHeader(jzfile *zip, jlong cenpos)
 940 {
 941     cencache *cache = &zip->cencache;
 942     char *cen;
 943     if (cache->data != NULL
 944         && (cenpos >= cache->pos)
 945         && (cenpos + CENHDR <= cache->pos + CENCACHE_PAGESIZE))
 946     {
 947         cen = cache->data + cenpos - cache->pos;
 948         if (cenpos + CENSIZE(cen) <= cache->pos + CENCACHE_PAGESIZE)
 949             /* A cache hit */
 950             return cen;
 951     }
 952 
 953     if ((cen = readCENHeader(zip, cenpos, CENCACHE_PAGESIZE)) == NULL)
 954         return NULL;
 955     free(cache->data);
 956     cache->data = cen;
 957     cache->pos  = cenpos;
 958     return cen;
 959 }
 960 
 961 typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint;
 962 
 963 /*
 964  * Return a new initialized jzentry corresponding to a given hash cell.
 965  * In case of error, returns NULL.
 966  * We already sanity-checked all the CEN headers for ZIP format errors
 967  * in readCEN(), so we don't check them again here.
 968  * The ZIP lock should be held here.
 969  */
 970 static jzentry *
 971 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
 972 {
 973     jlong locoff;
 974     jint nlen, elen, clen;
 975     jzentry *ze;
 976     char *cen;
 977 
 978     if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL;
 979     ze->name    = NULL;
 980     ze->extra   = NULL;
 981     ze->comment = NULL;
 982 
 983 #ifdef USE_MMAP
 984     if (zip->usemmap) {
 985         cen = (char*) zip->maddr + zc->cenpos - zip->offset;
 986     } else
 987 #endif
 988     {
 989         if (accessHint == ACCESS_RANDOM)
 990             cen = readCENHeader(zip, zc->cenpos, AMPLE_CEN_HEADER_SIZE);
 991         else
 992             cen = sequentialAccessReadCENHeader(zip, zc->cenpos);
 993         if (cen == NULL) goto Catch;
 994     }
 995 
 996     nlen      = CENNAM(cen);
 997     elen      = CENEXT(cen);
 998     clen      = CENCOM(cen);
 999     ze->method = CENHOW(cen);
1000     ze->time  = CENTIM(cen);
1001     ze->size  = CENLEN(cen);
1002     ze->csize = CENSIZ(cen);
1003     ze->crc   = CENCRC(cen);
1004     locoff    = CENOFF(cen);
1005     ze->pos   = -(zip->locpos + locoff);
1006     ze->flag  = CENFLG(cen);
1007 
1008     if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
1009     memcpy(ze->name, cen + CENHDR, nlen);
1010     ze->name[nlen] = '\0';
1011     ze->nlen = nlen;
1012     if (elen > 0) {
1013         char *extra = cen + CENHDR + nlen;
1014 
1015         /* This entry has "extra" data */
1016         if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
1017         ze->extra[0] = (unsigned char) elen;
1018         ze->extra[1] = (unsigned char) (elen >> 8);
1019         memcpy(ze->extra+2, extra, elen);
1020         if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
1021             locoff == ZIP64_MAGICVAL) {
1022             jint off = 0;
1023             while ((off + 4) < elen) {    // spec: HeaderID+DataSize+Data
1024                 jint sz = SH(extra, off + 2);
1025                 if (SH(extra, off) == ZIP64_EXTID) {
1026                     off += 4;
1027                     if (ze->size == ZIP64_MAGICVAL) {
1028                         // if invalid zip64 extra fields, just skip
1029                         if (sz < 8 || (off + 8) > elen)
1030                             break;
1031                         ze->size = LL(extra, off);
1032                         sz -= 8;
1033                         off += 8;
1034                     }
1035                     if (ze->csize == ZIP64_MAGICVAL) {
1036                         if (sz < 8 || (off + 8) > elen)
1037                             break;
1038                         ze->csize = LL(extra, off);
1039                         sz -= 8;
1040                         off += 8;
1041                     }
1042                     if (locoff == ZIP64_MAGICVAL) {
1043                         if (sz < 8 || (off + 8) > elen)
1044                             break;
1045                         ze->pos = -(zip->locpos +  LL(extra, off));
1046                         sz -= 8;
1047                         off += 8;
1048                     }
1049                     break;
1050                 }
1051                 off += (sz + 4);
1052             }
1053         }
1054     }
1055 
1056     if (clen > 0) {
1057         /* This entry has a comment */
1058         if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch;
1059         memcpy(ze->comment, cen + CENHDR + nlen + elen, clen);
1060         ze->comment[clen] = '\0';
1061     }
1062     goto Finally;
1063 
1064  Catch:
1065     free(ze->name);
1066     free(ze->extra);
1067     free(ze->comment);
1068     free(ze);
1069     ze = NULL;
1070 
1071  Finally:
1072 #ifdef USE_MMAP
1073     if (!zip->usemmap)
1074 #endif
1075         if (cen != NULL && accessHint == ACCESS_RANDOM) free(cen);
1076     return ze;
1077 }
1078 
1079 /*
1080  * Free the given jzentry.
1081  * In fact we maintain a one-entry cache of the most recently used
1082  * jzentry for each zip.  This optimizes a common access pattern.
1083  */
1084 
1085 void
1086 ZIP_FreeEntry(jzfile *jz, jzentry *ze)
1087 {
1088     jzentry *last;
1089     ZIP_Lock(jz);
1090     last = jz->cache;
1091     jz->cache = ze;
1092     ZIP_Unlock(jz);
1093     if (last != NULL) {
1094         /* Free the previously cached jzentry */
1095         free(last->name);
1096         if (last->extra)   free(last->extra);
1097         if (last->comment) free(last->comment);
1098         free(last);
1099     }
1100 }
1101 
1102 /*
1103  * Returns the zip entry corresponding to the specified name, or
1104  * NULL if not found.
1105  */
1106 jzentry *
1107 ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
1108 {
1109     if (ulen == 0) {
1110         return ZIP_GetEntry2(zip, name, strlen(name), JNI_FALSE);
1111     }
1112     return ZIP_GetEntry2(zip, name, ulen, JNI_TRUE);
1113 }
1114 
1115 jboolean equals(char* name1, int len1, char* name2, int len2) {
1116     if (len1 != len2) {
1117         return JNI_FALSE;
1118     }
1119     while (len1-- > 0) {
1120         if (*name1++ != *name2++) {
1121             return JNI_FALSE;
1122         }
1123     }
1124     return JNI_TRUE;
1125 }
1126 
1127 /*
1128  * Returns the zip entry corresponding to the specified name, or
1129  * NULL if not found.
1130  * This method supports embedded null character in "name", use ulen
1131  * for the length of "name".
1132  */
1133 jzentry *
1134 ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash)
1135 {
1136     unsigned int hsh = hashN(name, ulen);
1137     jint idx;
1138     jzentry *ze = 0;
1139 
1140     ZIP_Lock(zip);
1141     if (zip->total == 0) {
1142         goto Finally;
1143     }
1144 
1145     idx = zip->table[hsh % zip->tablelen];
1146 
1147     /*
1148      * This while loop is an optimization where a double lookup
1149      * for name and name+/ is being performed. The name char
1150      * array has enough room at the end to try again with a
1151      * slash appended if the first table lookup does not succeed.
1152      */
1153     while(1) {
1154 
1155         /* Check the cached entry first */
1156         ze = zip->cache;
1157         if (ze && equals(ze->name, ze->nlen, name, ulen)) {
1158             /* Cache hit!  Remove and return the cached entry. */
1159             zip->cache = 0;
1160             ZIP_Unlock(zip);
1161             return ze;
1162         }
1163         ze = 0;
1164 
1165         /*
1166          * Search down the target hash chain for a cell whose
1167          * 32 bit hash matches the hashed name.
1168          */
1169         while (idx != ZIP_ENDCHAIN) {
1170             jzcell *zc = &zip->entries[idx];
1171 
1172             if (zc->hash == hsh) {
1173                 /*
1174                  * OK, we've found a ZIP entry whose 32 bit hashcode
1175                  * matches the name we're looking for.  Try to read
1176                  * its entry information from the CEN.  If the CEN
1177                  * name matches the name we're looking for, we're
1178                  * done.
1179                  * If the names don't match (which should be very rare)
1180                  * we keep searching.
1181                  */
1182                 ze = newEntry(zip, zc, ACCESS_RANDOM);
1183                 if (ze && equals(ze->name, ze->nlen, name, ulen)) {
1184                     break;
1185                 }
1186                 if (ze != 0) {
1187                     /* We need to release the lock across the free call */
1188                     ZIP_Unlock(zip);
1189                     ZIP_FreeEntry(zip, ze);
1190                     ZIP_Lock(zip);
1191                 }
1192                 ze = 0;
1193             }
1194             idx = zc->next;
1195         }
1196 
1197         /* Entry found, return it */
1198         if (ze != 0) {
1199             break;
1200         }
1201 
1202         /* If no need to try appending slash, we are done */
1203         if (!addSlash) {
1204             break;
1205         }
1206 
1207         /* Slash is already there? */
1208         if (ulen > 0 && name[ulen - 1] == '/') {
1209             break;
1210         }
1211 
1212         /* Add slash and try once more */
1213         name[ulen++] = '/';
1214         name[ulen] = '\0';
1215         hsh = hash_append(hsh, '/');
1216         idx = zip->table[hsh % zip->tablelen];
1217         addSlash = JNI_FALSE;
1218     }
1219 
1220 Finally:
1221     ZIP_Unlock(zip);
1222     return ze;
1223 }
1224 
1225 /*
1226  * Returns the n'th (starting at zero) zip file entry, or NULL if the
1227  * specified index was out of range.
1228  */
1229 jzentry * JNICALL
1230 ZIP_GetNextEntry(jzfile *zip, jint n)
1231 {
1232     jzentry *result;
1233     if (n < 0 || n >= zip->total) {
1234         return 0;
1235     }
1236     ZIP_Lock(zip);
1237     result = newEntry(zip, &zip->entries[n], ACCESS_SEQUENTIAL);
1238     ZIP_Unlock(zip);
1239     return result;
1240 }
1241 
1242 /*
1243  * Locks the specified zip file for reading.
1244  */
1245 void
1246 ZIP_Lock(jzfile *zip)
1247 {
1248     MLOCK(zip->lock);
1249 }
1250 
1251 /*
1252  * Unlocks the specified zip file.
1253  */
1254 void
1255 ZIP_Unlock(jzfile *zip)
1256 {
1257     MUNLOCK(zip->lock);
1258 }
1259 
1260 /*
1261  * Returns the offset of the entry data within the zip file.
1262  * Returns -1 if an error occurred, in which case zip->msg will
1263  * contain the error text.
1264  */
1265 jlong
1266 ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry)
1267 {
1268     /* The Zip file spec explicitly allows the LOC extra data size to
1269      * be different from the CEN extra data size, although the JDK
1270      * never creates such zip files.  Since we cannot trust the CEN
1271      * extra data size, we need to read the LOC to determine the entry
1272      * data offset.  We do this lazily to avoid touching the virtual
1273      * memory page containing the LOC when initializing jzentry
1274      * objects.  (This speeds up javac by a factor of 10 when the JDK
1275      * is installed on a very slow filesystem.)
1276      */
1277     if (entry->pos <= 0) {
1278         unsigned char loc[LOCHDR];
1279         if (readFullyAt(zip->zfd, loc, LOCHDR, -(entry->pos)) == -1) {
1280             zip->msg = "error reading zip file";
1281             return -1;
1282         }
1283         if (!LOCSIG_AT(loc)) {
1284             zip->msg = "invalid LOC header (bad signature)";
1285             return -1;
1286         }
1287         entry->pos = (- entry->pos) + LOCHDR + LOCNAM(loc) + LOCEXT(loc);
1288     }
1289     return entry->pos;
1290 }
1291 
1292 /*
1293  * Reads bytes from the specified zip entry. Assumes that the zip
1294  * file had been previously locked with ZIP_Lock(). Returns the
1295  * number of bytes read, or -1 if an error occurred. If zip->msg != 0
1296  * then a zip error occurred and zip->msg contains the error text.
1297  *
1298  * The current implementation does not support reading an entry that
1299  * has the size bigger than 2**32 bytes in ONE invocation.
1300  */
1301 jint
1302 ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
1303 {
1304     jlong entry_size;
1305     jlong start;
1306 
1307     if (zip == 0) {
1308         return -1;
1309     }
1310 
1311     /* Clear previous zip error */
1312     zip->msg = NULL;
1313 
1314     if (entry == 0) {
1315         zip->msg = "ZIP_Read: jzentry is NULL";
1316         return -1;
1317     }
1318 
1319     entry_size = (entry->csize != 0) ? entry->csize : entry->size;
1320 
1321     /* Check specified position */
1322     if (pos < 0 || pos > entry_size - 1) {
1323         zip->msg = "ZIP_Read: specified offset out of range";
1324         return -1;
1325     }
1326 
1327     /* Check specified length */
1328     if (len <= 0)
1329         return 0;
1330     if (len > entry_size - pos)
1331         len = (jint)(entry_size - pos);
1332 
1333     /* Get file offset to start reading data */
1334     start = ZIP_GetEntryDataOffset(zip, entry);
1335     if (start < 0)
1336         return -1;
1337     start += pos;
1338 
1339     if (start + len > zip->len) {
1340         zip->msg = "ZIP_Read: corrupt zip file: invalid entry size";
1341         return -1;
1342     }
1343 
1344     if (readFullyAt(zip->zfd, buf, len, start) == -1) {
1345         zip->msg = "ZIP_Read: error reading zip file";
1346         return -1;
1347     }
1348     return len;
1349 }
1350 
1351 
1352 /* The maximum size of a stack-allocated buffer.
1353  */
1354 #define BUF_SIZE 4096
1355 
1356 /*
1357  * This function is used by the runtime system to load compressed entries
1358  * from ZIP/JAR files specified in the class path. It is defined here
1359  * so that it can be dynamically loaded by the runtime if the zip library
1360  * is found.
1361  *
1362  * The current implementation does not support reading an entry that
1363  * has the size bigger than 2**32 bytes in ONE invocation.
1364  */
1365 jboolean
1366 InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
1367 {
1368     z_stream strm;
1369     char tmp[BUF_SIZE];
1370     jlong pos = 0;
1371     jlong count = entry->csize;
1372 
1373     *msg = 0; /* Reset error message */
1374 
1375     if (count == 0) {
1376         *msg = "inflateFully: entry not compressed";
1377         return JNI_FALSE;
1378     }
1379 
1380     memset(&strm, 0, sizeof(z_stream));
1381     if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
1382         *msg = strm.msg;
1383         return JNI_FALSE;
1384     }
1385 
1386     strm.next_out = buf;
1387     strm.avail_out = (uInt)entry->size;
1388 
1389     while (count > 0) {
1390         jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : (jint)count;
1391         ZIP_Lock(zip);
1392         n = ZIP_Read(zip, entry, pos, tmp, n);
1393         ZIP_Unlock(zip);
1394         if (n <= 0) {
1395             if (n == 0) {
1396                 *msg = "inflateFully: Unexpected end of file";
1397             }
1398             inflateEnd(&strm);
1399             return JNI_FALSE;
1400         }
1401         pos += n;
1402         count -= n;
1403         strm.next_in = (Bytef *)tmp;
1404         strm.avail_in = n;
1405         do {
1406             switch (inflate(&strm, Z_PARTIAL_FLUSH)) {
1407             case Z_OK:
1408                 break;
1409             case Z_STREAM_END:
1410                 if (count != 0 || strm.total_out != entry->size) {
1411                     *msg = "inflateFully: Unexpected end of stream";
1412                     inflateEnd(&strm);
1413                     return JNI_FALSE;
1414                 }
1415                 break;
1416             default:
1417                 break;
1418             }
1419         } while (strm.avail_in > 0);
1420     }
1421 
1422     inflateEnd(&strm);
1423     return JNI_TRUE;
1424 }
1425 
1426 /*
1427  * The current implementation does not support reading an entry that
1428  * has the size bigger than 2**32 bytes in ONE invocation.
1429  */
1430 jzentry * JNICALL
1431 ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
1432 {
1433     jzentry *entry = ZIP_GetEntry(zip, name, 0);
1434     if (entry) {
1435         *sizeP = (jint)entry->size;
1436         *nameLenP = strlen(entry->name);
1437     }
1438     return entry;
1439 }
1440 
1441 /*
1442  * Reads a zip file entry into the specified byte array
1443  * When the method completes, it releases the jzentry.
1444  * Note: this is called from the separately delivered VM (hotspot/classic)
1445  * so we have to be careful to maintain the expected behaviour.
1446  */
1447 jboolean JNICALL
1448 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
1449 {
1450     char *msg;
1451     char tmpbuf[1024];
1452 
1453     if (entry == 0) {
1454         jio_fprintf(stderr, "jzentry was invalid");
1455         return JNI_FALSE;
1456     }
1457 
1458     strcpy(entryname, entry->name);
1459     if (entry->csize == 0) {
1460         /* Entry is stored */
1461         jlong pos = 0;
1462         jlong size = entry->size;
1463         while (pos < size) {
1464             jint n;
1465             jlong limit = ((((jlong) 1) << 31) - 1);
1466             jint count = (size - pos < limit) ?
1467                 /* These casts suppress a VC++ Internal Compiler Error */
1468                 (jint) (size - pos) :
1469                 (jint) limit;
1470             ZIP_Lock(zip);
1471             n = ZIP_Read(zip, entry, pos, buf, count);
1472             msg = zip->msg;
1473             ZIP_Unlock(zip);
1474             if (n == -1) {
1475                 if (msg == 0) {
1476                     getErrorString(errno, tmpbuf, sizeof(tmpbuf));
1477                     msg = tmpbuf;
1478                 }
1479                 jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
1480                 return JNI_FALSE;
1481             }
1482             buf += n;
1483             pos += n;
1484         }
1485     } else {
1486         /* Entry is compressed */
1487         int ok = InflateFully(zip, entry, buf, &msg);
1488         if (!ok) {
1489             if ((msg == NULL) || (*msg == 0)) {
1490                 msg = zip->msg;
1491             }
1492             if (msg == 0) {
1493                 getErrorString(errno, tmpbuf, sizeof(tmpbuf));
1494                 msg = tmpbuf;
1495             }
1496             jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
1497             return JNI_FALSE;
1498         }
1499     }
1500 
1501     ZIP_FreeEntry(zip, entry);
1502 
1503     return JNI_TRUE;
1504 }
1505 
1506 jboolean JNICALL
1507 ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg)
1508 {
1509     z_stream strm;
1510     int i = 0;
1511     memset(&strm, 0, sizeof(z_stream));
1512 
1513     *pmsg = 0; /* Reset error message */
1514 
1515     if (inflateInit2(&strm, MAX_WBITS) != Z_OK) {
1516         *pmsg = strm.msg;
1517         return JNI_FALSE;
1518     }
1519 
1520     strm.next_out = (Bytef *) outBuf;
1521     strm.avail_out = (uInt)outLen;
1522     strm.next_in = (Bytef *) inBuf;
1523     strm.avail_in = (uInt)inLen;
1524 
1525     do {
1526         switch (inflate(&strm, Z_PARTIAL_FLUSH)) {
1527             case Z_OK:
1528                 break;
1529             case Z_STREAM_END:
1530                 if (strm.total_out != outLen) {
1531                     *pmsg = "INFLATER_inflateFully: Unexpected end of stream";
1532                     inflateEnd(&strm);
1533                     return JNI_FALSE;
1534                 }
1535                 break;
1536             case Z_DATA_ERROR:
1537                 *pmsg = "INFLATER_inflateFully: Compressed data corrupted";
1538                 inflateEnd(&strm);
1539                 return JNI_FALSE;
1540             case Z_MEM_ERROR:
1541                 *pmsg = "INFLATER_inflateFully: out of memory";
1542                 inflateEnd(&strm);
1543                 return JNI_FALSE;
1544             default:
1545                 *pmsg = "INFLATER_inflateFully: internal error";
1546                 inflateEnd(&strm);
1547                 return JNI_FALSE;
1548         }
1549     } while (strm.avail_in > 0);
1550 
1551     inflateEnd(&strm);
1552     return JNI_TRUE;
1553 }