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