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