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