src/share/native/java/util/zip/zip_util.c

Print this page




 234     }
 235 
 236     if (zip != NULL) {
 237         free(zip->name);
 238         free(zip);
 239     }
 240     return NULL;
 241 }
 242 
 243 /*
 244  * Frees all native resources owned by the specified zip file object.
 245  */
 246 static void
 247 freeZip(jzfile *zip)
 248 {
 249     /* First free any cached jzentry */
 250     ZIP_FreeEntry(zip,0);
 251     if (zip->lock != NULL) MDESTROY(zip->lock);
 252     free(zip->name);
 253     freeCEN(zip);

 254 #ifdef USE_MMAP
 255     if (zip->maddr != NULL) munmap((char *)zip->maddr, zip->mlen);
 256 #else
 257     free(zip->cencache.data);

 258 #endif



 259     if (zip->comment != NULL)
 260         free(zip->comment);
 261     if (zip->zfd != -1) ZFILE_Close(zip->zfd);
 262     free(zip);
 263 }
 264 
 265 /* The END header is followed by a variable length comment of size < 64k. */
 266 static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
 267 
 268 #define READBLOCKSZ 128
 269 
 270 static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) {
 271     /* ENDSIG matched, however the size of file comment in it does not
 272        match the real size. One "common" cause for this problem is some
 273        "extra" bytes are padded at the end of the zipfile.
 274        Let's do some extra verification, we don't care about the performance
 275        in this situation.
 276      */
 277     jlong cenpos = endpos - ENDSIZ(endbuf);
 278     jlong locpos = cenpos - ENDOFF(endbuf);


 568         if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
 569             cenlen = ZIP64_ENDSIZ(end64buf);
 570             cenoff = ZIP64_ENDOFF(end64buf);
 571             total = (jint)ZIP64_ENDTOT(end64buf);
 572             endpos = end64pos;
 573             endhdrlen = ZIP64_ENDHDR;
 574         }
 575     }
 576 
 577     if (cenlen > endpos)
 578         ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
 579     cenpos = endpos - cenlen;
 580 
 581     /* Get position of first local file (LOC) header, taking into
 582      * account that there may be a stub prefixed to the zip file. */
 583     zip->locpos = cenpos - cenoff;
 584     if (zip->locpos < 0)
 585         ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
 586 
 587 #ifdef USE_MMAP

 588      /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to
 589       * read the jar file contents. However, this greatly increased the perceived
 590       * footprint numbers because the mmap'ed pages were adding into the totals shown
 591       * by 'ps' and 'top'. We switched to mmaping only the central directory of jar
 592       * file while calling 'read' to read the rest of jar file. Here are a list of
 593       * reasons apart from above of why we are doing so:
 594       * 1. Greatly reduces mmap overhead after startup complete;
 595       * 2. Avoids dual path code maintainance;
 596       * 3. Greatly reduces risk of address space (not virtual memory) exhaustion.
 597       */
 598     if (pagesize == 0) {
 599         pagesize = (jlong)sysconf(_SC_PAGESIZE);
 600         if (pagesize == 0) goto Catch;
 601     }
 602     if (cenpos > pagesize) {
 603         offset = cenpos & ~(pagesize - 1);
 604     } else {
 605         offset = 0;
 606     }
 607     /* When we are not calling recursively, knownTotal is -1. */
 608     if (knownTotal == -1) {
 609         void* mappedAddr;
 610         /* Mmap the CEN and END part only. We have to figure
 611            out the page size in order to make offset to be multiples of
 612            page size.
 613         */
 614         zip->mlen = cenpos - offset + cenlen + endhdrlen;
 615         zip->offset = offset;
 616         mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
 617         zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
 618             (unsigned char*)mappedAddr;
 619 
 620         if (zip->maddr == NULL) {
 621             jio_fprintf(stderr, "mmap failed for CEN and END part of zip file\n");
 622             goto Catch;
 623         }
 624     }
 625     cenbuf = zip->maddr + cenpos - offset;
 626 #else


 627     if ((cenbuf = malloc((size_t) cenlen)) == NULL ||
 628         (readFullyAt(zip->zfd, cenbuf, cenlen, cenpos) == -1))
 629         goto Catch;
 630 #endif

 631     cenend = cenbuf + cenlen;
 632 
 633     /* Initialize zip file data structures based on the total number
 634      * of central directory entries as stored in ENDTOT.  Since this
 635      * is a 2-byte field, but we (and other zip implementations)
 636      * support approx. 2**31 entries, we do not trust ENDTOT, but
 637      * treat it only as a strong hint.  When we call ourselves
 638      * recursively, knownTotal will have the "true" value.
 639      *
 640      * Keep this path alive even with the Zip64 END support added, just
 641      * for zip files that have more than 0xffff entries but don't have
 642      * the Zip64 enabled.
 643      */
 644     total = (knownTotal != -1) ? knownTotal : total;
 645     entries  = zip->entries  = calloc(total, sizeof(entries[0]));
 646     tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
 647     table    = zip->table    = malloc(tablelen * sizeof(table[0]));
 648     if (entries == NULL || table == NULL) goto Catch;
 649     for (j = 0; j < tablelen; j++)
 650         table[j] = ZIP_ENDCHAIN;


 683         /* Record the CEN offset and the name hash in our hash cell. */
 684         entries[i].cenpos = cenpos + (cp - cenbuf);
 685         entries[i].hash = hashN((char *)cp+CENHDR, nlen);
 686 
 687         /* Add the entry to the hash table */
 688         hsh = entries[i].hash % tablelen;
 689         entries[i].next = table[hsh];
 690         table[hsh] = i;
 691     }
 692     if (cp != cenend)
 693         ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
 694 
 695     zip->total = i;
 696     goto Finally;
 697 
 698  Catch:
 699     freeCEN(zip);
 700     cenpos = -1;
 701 
 702  Finally:
 703 #ifndef USE_MMAP
 704     free(cenbuf);
 705 #endif


 706     return cenpos;
 707 }
 708 
 709 /*
 710  * Opens a zip file with the specified mode. Returns the jzfile object
 711  * or NULL if an error occurred. If a zip error occurred then *pmsg will
 712  * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be
 713  * set to NULL.
 714  */
 715 jzfile *
 716 ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified)
 717 {
 718     jzfile *zip = NULL;
 719 
 720     /* Clear zip error message */
 721     if (pmsg != 0) {
 722         *pmsg = NULL;
 723     }
 724 
 725     zip = ZIP_Get_From_Cache(name, pmsg, lastModified);


 765 
 766     MLOCK(zfiles_lock);
 767     for (zip = zfiles; zip != NULL; zip = zip->next) {
 768         if (strcmp(name, zip->name) == 0
 769             && (zip->lastModified == lastModified || zip->lastModified == 0)
 770             && zip->refs < MAXREFS) {
 771             zip->refs++;
 772             break;
 773         }
 774     }
 775     MUNLOCK(zfiles_lock);
 776     return zip;
 777 }
 778 
 779 /*
 780  * Reads data from the given file descriptor to create a jzfile, puts the
 781  * jzfile in a cache, and returns that jzfile.  Returns NULL in case of error.
 782  * If a zip error occurs, then *pmsg will be set to the error message text if
 783  * pmsg != 0. Otherwise, *pmsg will be set to NULL.
 784  */

 785 jzfile *
 786 ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified)
 787 {







 788     static char errbuf[256];
 789     jlong len;
 790     jzfile *zip;
 791 
 792     if ((zip = allocZip(name)) == NULL) {
 793         return NULL;
 794     }
 795 



 796     zip->refs = 1;
 797     zip->lastModified = lastModified;
 798 
 799     if (zfd == -1) {
 800         if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
 801             *pmsg = errbuf;
 802         freeZip(zip);
 803         return NULL;
 804     }
 805 
 806     len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
 807     if (len <= 0) {
 808         if (len == 0) { /* zip file is empty */
 809             if (pmsg) {
 810                 *pmsg = "zip file is empty";
 811             }
 812         } else { /* error */
 813             if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
 814                 *pmsg = errbuf;
 815         }


 860         MUNLOCK(zfiles_lock);
 861         return;
 862     }
 863     /* No other references so close the file and remove from list */
 864     if (zfiles == zip) {
 865         zfiles = zfiles->next;
 866     } else {
 867         jzfile *zp;
 868         for (zp = zfiles; zp->next != 0; zp = zp->next) {
 869             if (zp->next == zip) {
 870                 zp->next = zip->next;
 871                 break;
 872             }
 873         }
 874     }
 875     MUNLOCK(zfiles_lock);
 876     freeZip(zip);
 877     return;
 878 }
 879 
 880 #ifndef USE_MMAP
 881 
 882 /* Empirically, most CEN headers are smaller than this. */
 883 #define AMPLE_CEN_HEADER_SIZE 160
 884 
 885 /* A good buffer size when we want to read CEN headers sequentially. */
 886 #define CENCACHE_PAGESIZE 8192
 887 
 888 static char *
 889 readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
 890 {
 891     jint censize;
 892     ZFILE zfd = zip->zfd;
 893     char *cen;
 894     if (bufsize > zip->len - cenpos)
 895         bufsize = zip->len - cenpos;
 896     if ((cen = malloc(bufsize)) == NULL)       goto Catch;
 897     if (readFullyAt(zfd, cen, bufsize, cenpos) == -1)     goto Catch;
 898     censize = CENSIZE(cen);
 899     if (censize <= bufsize) return cen;
 900     if ((cen = realloc(cen, censize)) == NULL)              goto Catch;
 901     if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;


 911 {
 912     cencache *cache = &zip->cencache;
 913     char *cen;
 914     if (cache->data != NULL
 915         && (cenpos >= cache->pos)
 916         && (cenpos + CENHDR <= cache->pos + CENCACHE_PAGESIZE))
 917     {
 918         cen = cache->data + cenpos - cache->pos;
 919         if (cenpos + CENSIZE(cen) <= cache->pos + CENCACHE_PAGESIZE)
 920             /* A cache hit */
 921             return cen;
 922     }
 923 
 924     if ((cen = readCENHeader(zip, cenpos, CENCACHE_PAGESIZE)) == NULL)
 925         return NULL;
 926     free(cache->data);
 927     cache->data = cen;
 928     cache->pos  = cenpos;
 929     return cen;
 930 }
 931 #endif /* not USE_MMAP */
 932 
 933 typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint;
 934 
 935 /*
 936  * Return a new initialized jzentry corresponding to a given hash cell.
 937  * In case of error, returns NULL.
 938  * We already sanity-checked all the CEN headers for ZIP format errors
 939  * in readCEN(), so we don't check them again here.
 940  * The ZIP lock should be held here.
 941  */
 942 static jzentry *
 943 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
 944 {
 945     jlong locoff;
 946     jint nlen, elen, clen;
 947     jzentry *ze;
 948     char *cen;
 949 
 950     if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL;
 951     ze->name    = NULL;
 952     ze->extra   = NULL;
 953     ze->comment = NULL;
 954 
 955 #ifdef USE_MMAP

 956     cen = (char*) zip->maddr + zc->cenpos - zip->offset;
 957 #else


 958     if (accessHint == ACCESS_RANDOM)
 959         cen = readCENHeader(zip, zc->cenpos, AMPLE_CEN_HEADER_SIZE);
 960     else
 961         cen = sequentialAccessReadCENHeader(zip, zc->cenpos);
 962     if (cen == NULL) goto Catch;
 963 #endif
 964 
 965     nlen      = CENNAM(cen);
 966     elen      = CENEXT(cen);
 967     clen      = CENCOM(cen);
 968     ze->time  = CENTIM(cen);
 969     ze->size  = CENLEN(cen);
 970     ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
 971     ze->crc   = CENCRC(cen);
 972     locoff    = CENOFF(cen);
 973     ze->pos   = -(zip->locpos + locoff);
 974     ze->flag  = CENFLG(cen);
 975 
 976     if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
 977     memcpy(ze->name, cen + CENHDR, nlen);
 978     ze->name[nlen] = '\0';
 979 
 980     if (elen > 0) {
 981         char *extra = cen + CENHDR + nlen;
 982 
 983         /* This entry has "extra" data */
 984         if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
 985         ze->extra[0] = (unsigned char) elen;
 986         ze->extra[1] = (unsigned char) (elen >> 8);
 987         memcpy(ze->extra+2, extra, elen);
 988         if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
 989             locoff == ZIP64_MAGICVAL) {
 990             jint off = 0;
 991             while ((off + 4) < elen) {    // spec: HeaderID+DataSize+Data
 992                 jint sz = SH(extra, off + 2);
 993                 if (SH(extra, off) == ZIP64_EXTID) {
 994                     off += 4;
 995                     if (ze->size == ZIP64_MAGICVAL) {
 996                         // if invalid zip64 extra fields, just skip
 997                         if (sz < 8 || (off + 8) > elen)
 998                             break;
 999                         ze->size = LL(extra, off);


1020             }
1021         }
1022     }
1023 
1024     if (clen > 0) {
1025         /* This entry has a comment */
1026         if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch;
1027         memcpy(ze->comment, cen + CENHDR + nlen + elen, clen);
1028         ze->comment[clen] = '\0';
1029     }
1030     goto Finally;
1031 
1032  Catch:
1033     free(ze->name);
1034     free(ze->extra);
1035     free(ze->comment);
1036     free(ze);
1037     ze = NULL;
1038 
1039  Finally:
1040 #ifndef USE_MMAP
1041     if (cen != NULL && accessHint == ACCESS_RANDOM) free(cen);
1042 #endif

1043     return ze;
1044 }
1045 
1046 /*
1047  * Free the given jzentry.
1048  * In fact we maintain a one-entry cache of the most recently used
1049  * jzentry for each zip.  This optimizes a common access pattern.
1050  */
1051 
1052 void
1053 ZIP_FreeEntry(jzfile *jz, jzentry *ze)
1054 {
1055     jzentry *last;
1056     ZIP_Lock(jz);
1057     last = jz->cache;
1058     jz->cache = ze;
1059     ZIP_Unlock(jz);
1060     if (last != NULL) {
1061         /* Free the previously cached jzentry */
1062         free(last->name);




 234     }
 235 
 236     if (zip != NULL) {
 237         free(zip->name);
 238         free(zip);
 239     }
 240     return NULL;
 241 }
 242 
 243 /*
 244  * Frees all native resources owned by the specified zip file object.
 245  */
 246 static void
 247 freeZip(jzfile *zip)
 248 {
 249     /* First free any cached jzentry */
 250     ZIP_FreeEntry(zip,0);
 251     if (zip->lock != NULL) MDESTROY(zip->lock);
 252     free(zip->name);
 253     freeCEN(zip);
 254 
 255 #ifdef USE_MMAP
 256     if (zip->usemmap) {
 257         if (zip->maddr != NULL)
 258             munmap((char *)zip->maddr, zip->mlen);
 259     } else
 260 #endif
 261     {
 262         free(zip->cencache.data);
 263     }
 264     if (zip->comment != NULL)
 265         free(zip->comment);
 266     if (zip->zfd != -1) ZFILE_Close(zip->zfd);
 267     free(zip);
 268 }
 269 
 270 /* The END header is followed by a variable length comment of size < 64k. */
 271 static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
 272 
 273 #define READBLOCKSZ 128
 274 
 275 static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) {
 276     /* ENDSIG matched, however the size of file comment in it does not
 277        match the real size. One "common" cause for this problem is some
 278        "extra" bytes are padded at the end of the zipfile.
 279        Let's do some extra verification, we don't care about the performance
 280        in this situation.
 281      */
 282     jlong cenpos = endpos - ENDSIZ(endbuf);
 283     jlong locpos = cenpos - ENDOFF(endbuf);


 573         if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
 574             cenlen = ZIP64_ENDSIZ(end64buf);
 575             cenoff = ZIP64_ENDOFF(end64buf);
 576             total = (jint)ZIP64_ENDTOT(end64buf);
 577             endpos = end64pos;
 578             endhdrlen = ZIP64_ENDHDR;
 579         }
 580     }
 581 
 582     if (cenlen > endpos)
 583         ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
 584     cenpos = endpos - cenlen;
 585 
 586     /* Get position of first local file (LOC) header, taking into
 587      * account that there may be a stub prefixed to the zip file. */
 588     zip->locpos = cenpos - cenoff;
 589     if (zip->locpos < 0)
 590         ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
 591 
 592 #ifdef USE_MMAP
 593     if (zip->usemmap) {
 594       /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to
 595        * read the jar file contents. However, this greatly increased the perceived
 596        * footprint numbers because the mmap'ed pages were adding into the totals shown
 597        * by 'ps' and 'top'. We switched to mmaping only the central directory of jar
 598        * file while calling 'read' to read the rest of jar file. Here are a list of
 599        * reasons apart from above of why we are doing so:
 600        * 1. Greatly reduces mmap overhead after startup complete;
 601        * 2. Avoids dual path code maintainance;
 602        * 3. Greatly reduces risk of address space (not virtual memory) exhaustion.
 603        */
 604         if (pagesize == 0) {
 605             pagesize = (jlong)sysconf(_SC_PAGESIZE);
 606             if (pagesize == 0) goto Catch;
 607         }
 608         if (cenpos > pagesize) {
 609             offset = cenpos & ~(pagesize - 1);
 610         } else {
 611             offset = 0;
 612         }
 613         /* When we are not calling recursively, knownTotal is -1. */
 614         if (knownTotal == -1) {
 615             void* mappedAddr;
 616             /* Mmap the CEN and END part only. We have to figure
 617                out the page size in order to make offset to be multiples of
 618                page size.
 619             */
 620             zip->mlen = cenpos - offset + cenlen + endhdrlen;
 621             zip->offset = offset;
 622             mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
 623             zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
 624                 (unsigned char*)mappedAddr;
 625 
 626             if (zip->maddr == NULL) {
 627                 jio_fprintf(stderr, "mmap failed for CEN and END part of zip file\n");
 628                 goto Catch;
 629             }
 630         }
 631         cenbuf = zip->maddr + cenpos - offset;
 632     } else
 633 #endif
 634     {
 635         if ((cenbuf = malloc((size_t) cenlen)) == NULL ||
 636             (readFullyAt(zip->zfd, cenbuf, cenlen, cenpos) == -1))
 637         goto Catch;
 638     }
 639 
 640     cenend = cenbuf + cenlen;
 641 
 642     /* Initialize zip file data structures based on the total number
 643      * of central directory entries as stored in ENDTOT.  Since this
 644      * is a 2-byte field, but we (and other zip implementations)
 645      * support approx. 2**31 entries, we do not trust ENDTOT, but
 646      * treat it only as a strong hint.  When we call ourselves
 647      * recursively, knownTotal will have the "true" value.
 648      *
 649      * Keep this path alive even with the Zip64 END support added, just
 650      * for zip files that have more than 0xffff entries but don't have
 651      * the Zip64 enabled.
 652      */
 653     total = (knownTotal != -1) ? knownTotal : total;
 654     entries  = zip->entries  = calloc(total, sizeof(entries[0]));
 655     tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
 656     table    = zip->table    = malloc(tablelen * sizeof(table[0]));
 657     if (entries == NULL || table == NULL) goto Catch;
 658     for (j = 0; j < tablelen; j++)
 659         table[j] = ZIP_ENDCHAIN;


 692         /* Record the CEN offset and the name hash in our hash cell. */
 693         entries[i].cenpos = cenpos + (cp - cenbuf);
 694         entries[i].hash = hashN((char *)cp+CENHDR, nlen);
 695 
 696         /* Add the entry to the hash table */
 697         hsh = entries[i].hash % tablelen;
 698         entries[i].next = table[hsh];
 699         table[hsh] = i;
 700     }
 701     if (cp != cenend)
 702         ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
 703 
 704     zip->total = i;
 705     goto Finally;
 706 
 707  Catch:
 708     freeCEN(zip);
 709     cenpos = -1;
 710 
 711  Finally:
 712 #ifdef USE_MMAP
 713     if (!zip->usemmap)
 714 #endif
 715         free(cenbuf);
 716 
 717     return cenpos;
 718 }
 719 
 720 /*
 721  * Opens a zip file with the specified mode. Returns the jzfile object
 722  * or NULL if an error occurred. If a zip error occurred then *pmsg will
 723  * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be
 724  * set to NULL.
 725  */
 726 jzfile *
 727 ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified)
 728 {
 729     jzfile *zip = NULL;
 730 
 731     /* Clear zip error message */
 732     if (pmsg != 0) {
 733         *pmsg = NULL;
 734     }
 735 
 736     zip = ZIP_Get_From_Cache(name, pmsg, lastModified);


 776 
 777     MLOCK(zfiles_lock);
 778     for (zip = zfiles; zip != NULL; zip = zip->next) {
 779         if (strcmp(name, zip->name) == 0
 780             && (zip->lastModified == lastModified || zip->lastModified == 0)
 781             && zip->refs < MAXREFS) {
 782             zip->refs++;
 783             break;
 784         }
 785     }
 786     MUNLOCK(zfiles_lock);
 787     return zip;
 788 }
 789 
 790 /*
 791  * Reads data from the given file descriptor to create a jzfile, puts the
 792  * jzfile in a cache, and returns that jzfile.  Returns NULL in case of error.
 793  * If a zip error occurs, then *pmsg will be set to the error message text if
 794  * pmsg != 0. Otherwise, *pmsg will be set to NULL.
 795  */
 796 
 797 jzfile *
 798 ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified)
 799 {
 800     return ZIP_Put_In_Cache0(name, zfd, pmsg, lastModified, JNI_TRUE);
 801 }
 802 
 803 jzfile *
 804 ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified,
 805                  jboolean usemmap)
 806 {
 807     static char errbuf[256];
 808     jlong len;
 809     jzfile *zip;
 810 
 811     if ((zip = allocZip(name)) == NULL) {
 812         return NULL;
 813     }
 814 
 815 #ifdef USE_MMAP
 816     zip->usemmap = usemmap;
 817 #endif
 818     zip->refs = 1;
 819     zip->lastModified = lastModified;
 820 
 821     if (zfd == -1) {
 822         if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
 823             *pmsg = errbuf;
 824         freeZip(zip);
 825         return NULL;
 826     }
 827 
 828     len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
 829     if (len <= 0) {
 830         if (len == 0) { /* zip file is empty */
 831             if (pmsg) {
 832                 *pmsg = "zip file is empty";
 833             }
 834         } else { /* error */
 835             if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
 836                 *pmsg = errbuf;
 837         }


 882         MUNLOCK(zfiles_lock);
 883         return;
 884     }
 885     /* No other references so close the file and remove from list */
 886     if (zfiles == zip) {
 887         zfiles = zfiles->next;
 888     } else {
 889         jzfile *zp;
 890         for (zp = zfiles; zp->next != 0; zp = zp->next) {
 891             if (zp->next == zip) {
 892                 zp->next = zip->next;
 893                 break;
 894             }
 895         }
 896     }
 897     MUNLOCK(zfiles_lock);
 898     freeZip(zip);
 899     return;
 900 }
 901 


 902 /* Empirically, most CEN headers are smaller than this. */
 903 #define AMPLE_CEN_HEADER_SIZE 160
 904 
 905 /* A good buffer size when we want to read CEN headers sequentially. */
 906 #define CENCACHE_PAGESIZE 8192
 907 
 908 static char *
 909 readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
 910 {
 911     jint censize;
 912     ZFILE zfd = zip->zfd;
 913     char *cen;
 914     if (bufsize > zip->len - cenpos)
 915         bufsize = zip->len - cenpos;
 916     if ((cen = malloc(bufsize)) == NULL)       goto Catch;
 917     if (readFullyAt(zfd, cen, bufsize, cenpos) == -1)     goto Catch;
 918     censize = CENSIZE(cen);
 919     if (censize <= bufsize) return cen;
 920     if ((cen = realloc(cen, censize)) == NULL)              goto Catch;
 921     if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;


 931 {
 932     cencache *cache = &zip->cencache;
 933     char *cen;
 934     if (cache->data != NULL
 935         && (cenpos >= cache->pos)
 936         && (cenpos + CENHDR <= cache->pos + CENCACHE_PAGESIZE))
 937     {
 938         cen = cache->data + cenpos - cache->pos;
 939         if (cenpos + CENSIZE(cen) <= cache->pos + CENCACHE_PAGESIZE)
 940             /* A cache hit */
 941             return cen;
 942     }
 943 
 944     if ((cen = readCENHeader(zip, cenpos, CENCACHE_PAGESIZE)) == NULL)
 945         return NULL;
 946     free(cache->data);
 947     cache->data = cen;
 948     cache->pos  = cenpos;
 949     return cen;
 950 }

 951 
 952 typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint;
 953 
 954 /*
 955  * Return a new initialized jzentry corresponding to a given hash cell.
 956  * In case of error, returns NULL.
 957  * We already sanity-checked all the CEN headers for ZIP format errors
 958  * in readCEN(), so we don't check them again here.
 959  * The ZIP lock should be held here.
 960  */
 961 static jzentry *
 962 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
 963 {
 964     jlong locoff;
 965     jint nlen, elen, clen;
 966     jzentry *ze;
 967     char *cen;
 968 
 969     if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL;
 970     ze->name    = NULL;
 971     ze->extra   = NULL;
 972     ze->comment = NULL;
 973 
 974 #ifdef USE_MMAP
 975     if (zip->usemmap) {
 976         cen = (char*) zip->maddr + zc->cenpos - zip->offset;
 977     } else
 978 #endif
 979     {
 980         if (accessHint == ACCESS_RANDOM)
 981             cen = readCENHeader(zip, zc->cenpos, AMPLE_CEN_HEADER_SIZE);
 982         else
 983             cen = sequentialAccessReadCENHeader(zip, zc->cenpos);
 984         if (cen == NULL) goto Catch;
 985     }
 986 
 987     nlen      = CENNAM(cen);
 988     elen      = CENEXT(cen);
 989     clen      = CENCOM(cen);
 990     ze->time  = CENTIM(cen);
 991     ze->size  = CENLEN(cen);
 992     ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
 993     ze->crc   = CENCRC(cen);
 994     locoff    = CENOFF(cen);
 995     ze->pos   = -(zip->locpos + locoff);
 996     ze->flag  = CENFLG(cen);
 997 
 998     if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
 999     memcpy(ze->name, cen + CENHDR, nlen);
1000     ze->name[nlen] = '\0';

1001     if (elen > 0) {
1002         char *extra = cen + CENHDR + nlen;
1003 
1004         /* This entry has "extra" data */
1005         if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
1006         ze->extra[0] = (unsigned char) elen;
1007         ze->extra[1] = (unsigned char) (elen >> 8);
1008         memcpy(ze->extra+2, extra, elen);
1009         if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
1010             locoff == ZIP64_MAGICVAL) {
1011             jint off = 0;
1012             while ((off + 4) < elen) {    // spec: HeaderID+DataSize+Data
1013                 jint sz = SH(extra, off + 2);
1014                 if (SH(extra, off) == ZIP64_EXTID) {
1015                     off += 4;
1016                     if (ze->size == ZIP64_MAGICVAL) {
1017                         // if invalid zip64 extra fields, just skip
1018                         if (sz < 8 || (off + 8) > elen)
1019                             break;
1020                         ze->size = LL(extra, off);


1041             }
1042         }
1043     }
1044 
1045     if (clen > 0) {
1046         /* This entry has a comment */
1047         if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch;
1048         memcpy(ze->comment, cen + CENHDR + nlen + elen, clen);
1049         ze->comment[clen] = '\0';
1050     }
1051     goto Finally;
1052 
1053  Catch:
1054     free(ze->name);
1055     free(ze->extra);
1056     free(ze->comment);
1057     free(ze);
1058     ze = NULL;
1059 
1060  Finally:
1061 #ifdef USE_MMAP
1062     if (!zip->usemmap)
1063 #endif
1064         if (cen != NULL && accessHint == ACCESS_RANDOM) free(cen);
1065     return ze;
1066 }
1067 
1068 /*
1069  * Free the given jzentry.
1070  * In fact we maintain a one-entry cache of the most recently used
1071  * jzentry for each zip.  This optimizes a common access pattern.
1072  */
1073 
1074 void
1075 ZIP_FreeEntry(jzfile *jz, jzentry *ze)
1076 {
1077     jzentry *last;
1078     ZIP_Lock(jz);
1079     last = jz->cache;
1080     jz->cache = ze;
1081     ZIP_Unlock(jz);
1082     if (last != NULL) {
1083         /* Free the previously cached jzentry */
1084         free(last->name);