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; |