jdk/src/share/native/java/util/zip/zip_util.c
changeset 2438 21c111b51aa8
parent 2163 1586577d5107
child 2592 ef26f663a2ba
equal deleted inserted replaced
2436:ae4667371301 2438:21c111b51aa8
   311     }
   311     }
   312     return -1; /* END header not found */
   312     return -1; /* END header not found */
   313 }
   313 }
   314 
   314 
   315 /*
   315 /*
       
   316  * Searches for the ZIP64 end of central directory (END) header. The
       
   317  * contents of the ZIP64 END header will be read and placed in end64buf.
       
   318  * Returns the file position of the ZIP64 END header, otherwise returns
       
   319  * -1 if the END header was not found or an error occurred.
       
   320  *
       
   321  * The ZIP format specifies the "position" of each related record as
       
   322  *   ...
       
   323  *   [central directory]
       
   324  *   [zip64 end of central directory record]
       
   325  *   [zip64 end of central directory locator]
       
   326  *   [end of central directory record]
       
   327  *
       
   328  * The offset of zip64 end locator can be calculated from endpos as
       
   329  * "endpos - ZIP64_LOCHDR".
       
   330  * The "offset" of zip64 end record is stored in zip64 end locator.
       
   331  */
       
   332 static jlong
       
   333 findEND64(jzfile *zip, void *end64buf, jlong endpos)
       
   334 {
       
   335     char loc64[ZIP64_LOCHDR];
       
   336     jlong end64pos;
       
   337     if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) {
       
   338         return -1;    // end64 locator not found
       
   339     }
       
   340     end64pos = ZIP64_LOCOFF(loc64);
       
   341     if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR, end64pos) == -1) {
       
   342         return -1;    // end64 record not found
       
   343     }
       
   344     return end64pos;
       
   345 }
       
   346 
       
   347 /*
   316  * Returns a hash code value for a C-style NUL-terminated string.
   348  * Returns a hash code value for a C-style NUL-terminated string.
   317  */
   349  */
   318 static unsigned int
   350 static unsigned int
   319 hash(const char *s)
   351 hash(const char *s)
   320 {
   352 {
   461  */
   493  */
   462 static jlong
   494 static jlong
   463 readCEN(jzfile *zip, jint knownTotal)
   495 readCEN(jzfile *zip, jint knownTotal)
   464 {
   496 {
   465     /* Following are unsigned 32-bit */
   497     /* Following are unsigned 32-bit */
   466     jlong endpos, cenpos, cenlen;
   498     jlong endpos, end64pos, cenpos, cenlen, cenoff;
   467     /* Following are unsigned 16-bit */
   499     /* Following are unsigned 16-bit */
   468     jint total, tablelen, i, j;
   500     jint total, tablelen, i, j;
   469     unsigned char *cenbuf = NULL;
   501     unsigned char *cenbuf = NULL;
   470     unsigned char *cenend;
   502     unsigned char *cenend;
   471     unsigned char *cp;
   503     unsigned char *cp;
   472 #ifdef USE_MMAP
   504 #ifdef USE_MMAP
   473     static jlong pagesize;
   505     static jlong pagesize;
   474     jlong offset;
   506     jlong offset;
   475 #endif
   507 #endif
   476     unsigned char endbuf[ENDHDR];
   508     unsigned char endbuf[ENDHDR];
       
   509     jint endhdrlen = ENDHDR;
   477     jzcell *entries;
   510     jzcell *entries;
   478     jint *table;
   511     jint *table;
   479 
   512 
   480     /* Clear previous zip error */
   513     /* Clear previous zip error */
   481     zip->msg = NULL;
   514     zip->msg = NULL;
   488 
   521 
   489     freeCEN(zip);
   522     freeCEN(zip);
   490 
   523 
   491    /* Get position and length of central directory */
   524    /* Get position and length of central directory */
   492     cenlen = ENDSIZ(endbuf);
   525     cenlen = ENDSIZ(endbuf);
       
   526     cenoff = ENDOFF(endbuf);
       
   527     total  = ENDTOT(endbuf);
       
   528     if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL ||
       
   529         total == ZIP64_MAGICCOUNT) {
       
   530         unsigned char end64buf[ZIP64_ENDHDR];
       
   531         if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
       
   532             cenlen = ZIP64_ENDSIZ(end64buf);
       
   533             cenoff = ZIP64_ENDOFF(end64buf);
       
   534             total = (jint)ZIP64_ENDTOT(end64buf);
       
   535             endpos = end64pos;
       
   536             endhdrlen = ZIP64_ENDHDR;
       
   537         }
       
   538     }
       
   539 
   493     if (cenlen > endpos)
   540     if (cenlen > endpos)
   494         ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
   541         ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
   495     cenpos = endpos - cenlen;
   542     cenpos = endpos - cenlen;
   496 
   543 
   497     /* Get position of first local file (LOC) header, taking into
   544     /* Get position of first local file (LOC) header, taking into
   498      * account that there may be a stub prefixed to the zip file. */
   545      * account that there may be a stub prefixed to the zip file. */
   499     zip->locpos = cenpos - ENDOFF(endbuf);
   546     zip->locpos = cenpos - cenoff;
   500     if (zip->locpos < 0)
   547     if (zip->locpos < 0)
   501         ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
   548         ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
   502 
   549 
   503 #ifdef USE_MMAP
   550 #ifdef USE_MMAP
   504      /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to
   551      /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to
   525         void* mappedAddr;
   572         void* mappedAddr;
   526         /* Mmap the CEN and END part only. We have to figure
   573         /* Mmap the CEN and END part only. We have to figure
   527            out the page size in order to make offset to be multiples of
   574            out the page size in order to make offset to be multiples of
   528            page size.
   575            page size.
   529         */
   576         */
   530         zip->mlen = cenpos - offset + cenlen + ENDHDR;
   577         zip->mlen = cenpos - offset + cenlen + endhdrlen;
   531         zip->offset = offset;
   578         zip->offset = offset;
   532         mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
   579         mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
   533         zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
   580         zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
   534             (unsigned char*)mappedAddr;
   581             (unsigned char*)mappedAddr;
   535 
   582 
   549     /* Initialize zip file data structures based on the total number
   596     /* Initialize zip file data structures based on the total number
   550      * of central directory entries as stored in ENDTOT.  Since this
   597      * of central directory entries as stored in ENDTOT.  Since this
   551      * is a 2-byte field, but we (and other zip implementations)
   598      * is a 2-byte field, but we (and other zip implementations)
   552      * support approx. 2**31 entries, we do not trust ENDTOT, but
   599      * support approx. 2**31 entries, we do not trust ENDTOT, but
   553      * treat it only as a strong hint.  When we call ourselves
   600      * treat it only as a strong hint.  When we call ourselves
   554      * recursively, knownTotal will have the "true" value. */
   601      * recursively, knownTotal will have the "true" value.
   555     total = (knownTotal != -1) ? knownTotal : ENDTOT(endbuf);
   602      *
       
   603      * Keep this path alive even with the Zip64 END support added, just
       
   604      * for zip files that have more than 0xffff entries but don't have
       
   605      * the Zip64 enabled.
       
   606      */
       
   607     total = (knownTotal != -1) ? knownTotal : total;
   556     entries  = zip->entries  = calloc(total, sizeof(entries[0]));
   608     entries  = zip->entries  = calloc(total, sizeof(entries[0]));
   557     tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
   609     tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
   558     table    = zip->table    = malloc(tablelen * sizeof(table[0]));
   610     table    = zip->table    = malloc(tablelen * sizeof(table[0]));
   559     if (entries == NULL || table == NULL) goto Catch;
   611     if (entries == NULL || table == NULL) goto Catch;
   560     for (j = 0; j < tablelen; j++)
   612     for (j = 0; j < tablelen; j++)
   852  * The ZIP lock should be held here.
   904  * The ZIP lock should be held here.
   853  */
   905  */
   854 static jzentry *
   906 static jzentry *
   855 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
   907 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
   856 {
   908 {
       
   909     jlong locoff;
   857     jint nlen, elen, clen;
   910     jint nlen, elen, clen;
   858     jzentry *ze;
   911     jzentry *ze;
   859     char *cen;
   912     char *cen;
   860 
   913 
   861     if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL;
   914     if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL;
   878     clen      = CENCOM(cen);
   931     clen      = CENCOM(cen);
   879     ze->time  = CENTIM(cen);
   932     ze->time  = CENTIM(cen);
   880     ze->size  = CENLEN(cen);
   933     ze->size  = CENLEN(cen);
   881     ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
   934     ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
   882     ze->crc   = CENCRC(cen);
   935     ze->crc   = CENCRC(cen);
   883     ze->pos   = -(zip->locpos + CENOFF(cen));
   936     locoff    = CENOFF(cen);
       
   937     ze->pos   = -(zip->locpos + locoff);
   884 
   938 
   885     if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
   939     if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
   886     memcpy(ze->name, cen + CENHDR, nlen);
   940     memcpy(ze->name, cen + CENHDR, nlen);
   887     ze->name[nlen] = '\0';
   941     ze->name[nlen] = '\0';
   888 
   942 
   889     if (elen > 0) {
   943     if (elen > 0) {
       
   944         char *extra = cen + CENHDR + nlen;
       
   945 
   890         /* This entry has "extra" data */
   946         /* This entry has "extra" data */
   891         if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
   947         if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
   892         ze->extra[0] = (unsigned char) elen;
   948         ze->extra[0] = (unsigned char) elen;
   893         ze->extra[1] = (unsigned char) (elen >> 8);
   949         ze->extra[1] = (unsigned char) (elen >> 8);
   894         memcpy(ze->extra+2, cen + CENHDR + nlen, elen);
   950         memcpy(ze->extra+2, extra, elen);
       
   951         if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
       
   952             locoff == ZIP64_MAGICVAL) {
       
   953             jint off = 0;
       
   954             while ((off + 4) < elen) {    // spec: HeaderID+DataSize+Data
       
   955                 jint sz = SH(extra, off + 2);
       
   956                 if (SH(extra, off) == ZIP64_EXTID) {
       
   957                     off += 4;
       
   958                     if (ze->size == ZIP64_MAGICVAL) {
       
   959                         // if invalid zip64 extra fields, just skip
       
   960                         if (sz < 8 || (off + 8) > elen)
       
   961                             break;
       
   962                         ze->size = LL(extra, off);
       
   963                         sz -= 8;
       
   964                         off += 8;
       
   965                     }
       
   966                     if (ze->csize == ZIP64_MAGICVAL) {
       
   967                         if (sz < 8 || (off + 8) > elen)
       
   968                             break;
       
   969                         ze->csize = LL(extra, off);
       
   970                         sz -= 8;
       
   971                         off += 8;
       
   972                     }
       
   973                     if (locoff == ZIP64_MAGICVAL) {
       
   974                         if (sz < 8 || (off + 8) > elen)
       
   975                             break;
       
   976                         ze->pos = -(zip->locpos +  LL(extra, off));
       
   977                         sz -= 8;
       
   978                         off += 8;
       
   979                     }
       
   980                     break;
       
   981                 }
       
   982                 off += (sz + 4);
       
   983             }
       
   984         }
   895     }
   985     }
   896 
   986 
   897     if (clen > 0) {
   987     if (clen > 0) {
   898         /* This entry has a comment */
   988         /* This entry has a comment */
   899         if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch;
   989         if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch;