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