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