1 /* 2 * Copyright (c) 1995, 2009, 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 "jni.h" 41 #include "jni_util.h" 42 #include "jlong.h" 43 #include "jvm.h" 44 #include "io_util.h" 45 #include "io_util_md.h" 46 #include "zip_util.h" 47 #include "zlib.h" 48 49 /* USE_MMAP means mmap the CEN & ENDHDR part of the zip file. */ 50 #ifdef USE_MMAP 51 #include <sys/mman.h> 52 #endif 53 54 #define MAXREFS 0xFFFF /* max number of open zip file references */ 55 56 #define MCREATE() JVM_RawMonitorCreate() 57 #define MLOCK(lock) JVM_RawMonitorEnter(lock) 58 #define MUNLOCK(lock) JVM_RawMonitorExit(lock) 59 #define MDESTROY(lock) JVM_RawMonitorDestroy(lock) 60 61 #define CENSIZE(cen) (CENHDR + CENNAM(cen) + CENEXT(cen) + CENCOM(cen)) 62 63 static jzfile *zfiles = 0; /* currently open zip files */ 64 static void *zfiles_lock = 0; 65 66 static void freeCEN(jzfile *); 67 68 #ifndef PATH_MAX 69 #define PATH_MAX 1024 70 #endif 71 72 static jint INITIAL_META_COUNT = 2; /* initial number of entries in meta name array */ 73 74 /* 75 * The ZFILE_* functions exist to provide some platform-independence with 76 * respect to file access needs. 77 */ 78 79 /* 80 * Opens the named file for reading, returning a ZFILE. 81 * 82 * Compare this with winFileHandleOpen in windows/native/java/io/io_util_md.c. 83 * This function does not take JNIEnv* and uses CreateFile (instead of 84 * CreateFileW). The expectation is that this function will be called only 85 * from ZIP_Open_Generic, which in turn is used by the JVM, where we do not 86 * need to concern ourselves with wide chars. 87 */ 88 static ZFILE 89 ZFILE_Open(const char *fname, int flags) { 90 #ifdef WIN32 91 const DWORD access = 92 (flags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) : 93 (flags & O_WRONLY) ? GENERIC_WRITE : 94 GENERIC_READ; 95 const DWORD sharing = 96 FILE_SHARE_READ | FILE_SHARE_WRITE; 97 const DWORD disposition = 98 /* Note: O_TRUNC overrides O_CREAT */ 99 (flags & O_TRUNC) ? CREATE_ALWAYS : 100 (flags & O_CREAT) ? OPEN_ALWAYS : 101 OPEN_EXISTING; 102 const DWORD maybeWriteThrough = 103 (flags & (O_SYNC | O_DSYNC)) ? 104 FILE_FLAG_WRITE_THROUGH : 105 FILE_ATTRIBUTE_NORMAL; 106 const DWORD maybeDeleteOnClose = 107 (flags & O_TEMPORARY) ? 108 FILE_FLAG_DELETE_ON_CLOSE : 109 FILE_ATTRIBUTE_NORMAL; 110 const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose; 111 112 return (jlong) CreateFile( 113 fname, /* Wide char path name */ 114 access, /* Read and/or write permission */ 115 sharing, /* File sharing flags */ 116 NULL, /* Security attributes */ 117 disposition, /* creation disposition */ 118 flagsAndAttributes, /* flags and attributes */ 119 NULL); 120 #else 121 return JVM_Open(fname, flags, 0); 122 #endif 123 } 124 125 /* 126 * The io_util_md.h files do not provide IO_CLOSE, hence we use platform 127 * specifics. 128 */ 129 static void 130 ZFILE_Close(ZFILE zfd) { 131 #ifdef WIN32 132 CloseHandle((HANDLE) zfd); 133 #else 134 JVM_Close(zfd); 135 #endif 136 } 137 138 static int 139 ZFILE_read(ZFILE zfd, char *buf, jint nbytes) { 140 #ifdef WIN32 141 return (int) IO_Read(zfd, buf, nbytes); 142 #else 143 /* 144 * Calling JVM_Read will return JVM_IO_INTR when Thread.interrupt is called 145 * only on Solaris. Continue reading jar file in this case is the best 146 * thing to do since zip file reading is relatively fast and it is very onerous 147 * for a interrupted thread to deal with this kind of hidden I/O. However, handling 148 * JVM_IO_INTR is tricky and could cause undesired side effect. So we decided 149 * to simply call "read" on Solaris/Linux. See details in bug 6304463. 150 */ 151 return read(zfd, buf, nbytes); 152 #endif 153 } 154 155 /* 156 * Initialize zip file support. Return 0 if successful otherwise -1 157 * if could not be initialized. 158 */ 159 static jint 160 InitializeZip() 161 { 162 static jboolean inited = JNI_FALSE; 163 164 // Initialize errno to 0. It may be set later (e.g. during memory 165 // allocation) but we can disregard previous values. 166 errno = 0; 167 168 if (inited) 169 return 0; 170 zfiles_lock = MCREATE(); 171 if (zfiles_lock == 0) { 172 return -1; 173 } 174 inited = JNI_TRUE; 175 176 return 0; 177 } 178 179 /* 180 * Reads len bytes of data into buf. 181 * Returns 0 if all bytes could be read, otherwise returns -1. 182 */ 183 static int 184 readFully(ZFILE zfd, void *buf, jlong len) { 185 char *bp = (char *) buf; 186 187 while (len > 0) { 188 jlong limit = ((((jlong) 1) << 31) - 1); 189 jint count = (len < limit) ? 190 (jint) len : 191 (jint) limit; 192 jint n = ZFILE_read(zfd, bp, count); 193 if (n > 0) { 194 bp += n; 195 len -= n; 196 } else if (n == JVM_IO_ERR && errno == EINTR) { 197 /* Retry after EINTR (interrupted by signal). 198 We depend on the fact that JVM_IO_ERR == -1. */ 199 continue; 200 } else { /* EOF or IO error */ 201 return -1; 202 } 203 } 204 return 0; 205 } 206 207 /* 208 * Reads len bytes of data from the specified offset into buf. 209 * Returns 0 if all bytes could be read, otherwise returns -1. 210 */ 211 static int 212 readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset) 213 { 214 if (IO_Lseek(zfd, offset, SEEK_SET) == -1) { 215 return -1; /* lseek failure. */ 216 } 217 218 return readFully(zfd, buf, len); 219 } 220 221 /* 222 * Allocates a new zip file object for the specified file name. 223 * Returns the zip file object or NULL if not enough memory. 224 */ 225 static jzfile * 226 allocZip(const char *name) 227 { 228 jzfile *zip; 229 if (((zip = calloc(1, sizeof(jzfile))) != NULL) && 230 ((zip->name = strdup(name)) != NULL) && 231 ((zip->lock = MCREATE()) != NULL)) { 232 zip->zfd = -1; 233 return zip; 234 } 235 236 if (zip != NULL) { 237 free(zip->name); 238 free(zip); 239 } 240 return NULL; 241 } 242 243 /* 244 * Frees all native resources owned by the specified zip file object. 245 */ 246 static void 247 freeZip(jzfile *zip) 248 { 249 /* First free any cached jzentry */ 250 ZIP_FreeEntry(zip,0); 251 if (zip->lock != NULL) MDESTROY(zip->lock); 252 free(zip->name); 253 freeCEN(zip); 254 255 #ifdef USE_MMAP 256 if (zip->usemmap) { 257 if (zip->maddr != NULL) 258 munmap((char *)zip->maddr, zip->mlen); 259 } else 260 #endif 261 { 262 free(zip->cencache.data); 263 } 264 if (zip->comment != NULL) 265 free(zip->comment); 266 if (zip->zfd != -1) ZFILE_Close(zip->zfd); 267 free(zip); 268 } 269 270 /* The END header is followed by a variable length comment of size < 64k. */ 271 static const jlong END_MAXLEN = 0xFFFF + ENDHDR; 272 273 #define READBLOCKSZ 128 274 275 static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) { 276 /* ENDSIG matched, however the size of file comment in it does not 277 match the real size. One "common" cause for this problem is some 278 "extra" bytes are padded at the end of the zipfile. 279 Let's do some extra verification, we don't care about the performance 280 in this situation. 281 */ 282 jlong cenpos = endpos - ENDSIZ(endbuf); 283 jlong locpos = cenpos - ENDOFF(endbuf); 284 char buf[4]; 285 return (cenpos >= 0 && 286 locpos >= 0 && 287 readFullyAt(zip->zfd, buf, sizeof(buf), cenpos) != -1 && 288 GETSIG(buf) == CENSIG && 289 readFullyAt(zip->zfd, buf, sizeof(buf), locpos) != -1 && 290 GETSIG(buf) == LOCSIG); 291 } 292 293 /* 294 * Searches for end of central directory (END) header. The contents of 295 * the END header will be read and placed in endbuf. Returns the file 296 * position of the END header, otherwise returns -1 if the END header 297 * was not found or an error occurred. 298 */ 299 static jlong 300 findEND(jzfile *zip, void *endbuf) 301 { 302 char buf[READBLOCKSZ]; 303 jlong pos; 304 const jlong len = zip->len; 305 const ZFILE zfd = zip->zfd; 306 const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0; 307 const jlong minPos = minHDR - (sizeof(buf)-ENDHDR); 308 jint clen; 309 310 for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) { 311 312 int i; 313 jlong off = 0; 314 if (pos < 0) { 315 /* Pretend there are some NUL bytes before start of file */ 316 off = -pos; 317 memset(buf, '\0', (size_t)off); 318 } 319 320 if (readFullyAt(zfd, buf + off, sizeof(buf) - off, 321 pos + off) == -1) { 322 return -1; /* System error */ 323 } 324 325 /* Now scan the block backwards for END header signature */ 326 for (i = sizeof(buf) - ENDHDR; i >= 0; i--) { 327 if (buf[i+0] == 'P' && 328 buf[i+1] == 'K' && 329 buf[i+2] == '\005' && 330 buf[i+3] == '\006' && 331 ((pos + i + ENDHDR + ENDCOM(buf + i) == len) 332 || verifyEND(zip, pos + i, buf + i))) { 333 /* Found END header */ 334 memcpy(endbuf, buf + i, ENDHDR); 335 336 clen = ENDCOM(endbuf); 337 if (clen != 0) { 338 zip->comment = malloc(clen + 1); 339 if (zip->comment == NULL) { 340 return -1; 341 } 342 if (readFullyAt(zfd, zip->comment, clen, pos + i + ENDHDR) 343 == -1) { 344 free(zip->comment); 345 zip->comment = NULL; 346 return -1; 347 } 348 zip->comment[clen] = '\0'; 349 zip->clen = clen; 350 } 351 return pos + i; 352 } 353 } 354 } 355 356 return -1; /* END header not found */ 357 } 358 359 /* 360 * Searches for the ZIP64 end of central directory (END) header. The 361 * contents of the ZIP64 END header will be read and placed in end64buf. 362 * Returns the file position of the ZIP64 END header, otherwise returns 363 * -1 if the END header was not found or an error occurred. 364 * 365 * The ZIP format specifies the "position" of each related record as 366 * ... 367 * [central directory] 368 * [zip64 end of central directory record] 369 * [zip64 end of central directory locator] 370 * [end of central directory record] 371 * 372 * The offset of zip64 end locator can be calculated from endpos as 373 * "endpos - ZIP64_LOCHDR". 374 * The "offset" of zip64 end record is stored in zip64 end locator. 375 */ 376 static jlong 377 findEND64(jzfile *zip, void *end64buf, jlong endpos) 378 { 379 char loc64[ZIP64_LOCHDR]; 380 jlong end64pos; 381 if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) { 382 return -1; // end64 locator not found 383 } 384 end64pos = ZIP64_LOCOFF(loc64); 385 if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR, end64pos) == -1) { 386 return -1; // end64 record not found 387 } 388 return end64pos; 389 } 390 391 /* 392 * Returns a hash code value for a C-style NUL-terminated string. 393 */ 394 static unsigned int 395 hash(const char *s) 396 { 397 int h = 0; 398 while (*s != '\0') 399 h = 31*h + *s++; 400 return h; 401 } 402 403 /* 404 * Returns a hash code value for a string of a specified length. 405 */ 406 static unsigned int 407 hashN(const char *s, int length) 408 { 409 int h = 0; 410 while (length-- > 0) 411 h = 31*h + *s++; 412 return h; 413 } 414 415 static unsigned int 416 hash_append(unsigned int hash, char c) 417 { 418 return ((int)hash)*31 + c; 419 } 420 421 /* 422 * Returns true if the specified entry's name begins with the string 423 * "META-INF/" irrespective of case. 424 */ 425 static int 426 isMetaName(const char *name, int length) 427 { 428 const char *s; 429 if (length < (int)sizeof("META-INF/") - 1) 430 return 0; 431 for (s = "META-INF/"; *s != '\0'; s++) { 432 char c = *name++; 433 // Avoid toupper; it's locale-dependent 434 if (c >= 'a' && c <= 'z') c += 'A' - 'a'; 435 if (*s != c) 436 return 0; 437 } 438 return 1; 439 } 440 441 /* 442 * Increases the capacity of zip->metanames. 443 * Returns non-zero in case of allocation error. 444 */ 445 static int 446 growMetaNames(jzfile *zip) 447 { 448 jint i; 449 /* double the meta names array */ 450 const jint new_metacount = zip->metacount << 1; 451 zip->metanames = 452 realloc(zip->metanames, new_metacount * sizeof(zip->metanames[0])); 453 if (zip->metanames == NULL) return -1; 454 for (i = zip->metacount; i < new_metacount; i++) 455 zip->metanames[i] = NULL; 456 zip->metacurrent = zip->metacount; 457 zip->metacount = new_metacount; 458 return 0; 459 } 460 461 /* 462 * Adds name to zip->metanames. 463 * Returns non-zero in case of allocation error. 464 */ 465 static int 466 addMetaName(jzfile *zip, const char *name, int length) 467 { 468 jint i; 469 if (zip->metanames == NULL) { 470 zip->metacount = INITIAL_META_COUNT; 471 zip->metanames = calloc(zip->metacount, sizeof(zip->metanames[0])); 472 if (zip->metanames == NULL) return -1; 473 zip->metacurrent = 0; 474 } 475 476 i = zip->metacurrent; 477 478 /* current meta name array isn't full yet. */ 479 if (i < zip->metacount) { 480 zip->metanames[i] = (char *) malloc(length+1); 481 if (zip->metanames[i] == NULL) return -1; 482 memcpy(zip->metanames[i], name, length); 483 zip->metanames[i][length] = '\0'; 484 zip->metacurrent++; 485 return 0; 486 } 487 488 /* No free entries in zip->metanames? */ 489 if (growMetaNames(zip) != 0) return -1; 490 return addMetaName(zip, name, length); 491 } 492 493 static void 494 freeMetaNames(jzfile *zip) 495 { 496 if (zip->metanames) { 497 jint i; 498 for (i = 0; i < zip->metacount; i++) 499 free(zip->metanames[i]); 500 free(zip->metanames); 501 zip->metanames = NULL; 502 } 503 } 504 505 /* Free Zip data allocated by readCEN() */ 506 static void 507 freeCEN(jzfile *zip) 508 { 509 free(zip->entries); zip->entries = NULL; 510 free(zip->table); zip->table = NULL; 511 freeMetaNames(zip); 512 } 513 514 /* 515 * Counts the number of CEN headers in a central directory extending 516 * from BEG to END. Might return a bogus answer if the zip file is 517 * corrupt, but will not crash. 518 */ 519 static jint 520 countCENHeaders(unsigned char *beg, unsigned char *end) 521 { 522 jint count = 0; 523 ptrdiff_t i; 524 for (i = 0; i + CENHDR < end - beg; i += CENSIZE(beg + i)) 525 count++; 526 return count; 527 } 528 529 #define ZIP_FORMAT_ERROR(message) \ 530 if (1) { zip->msg = message; goto Catch; } else ((void)0) 531 532 /* 533 * Reads zip file central directory. Returns the file position of first 534 * CEN header, otherwise returns -1 if an error occured. If zip->msg != NULL 535 * then the error was a zip format error and zip->msg has the error text. 536 * Always pass in -1 for knownTotal; it's used for a recursive call. 537 */ 538 static jlong 539 readCEN(jzfile *zip, jint knownTotal) 540 { 541 /* Following are unsigned 32-bit */ 542 jlong endpos, end64pos, cenpos, cenlen, cenoff; 543 /* Following are unsigned 16-bit */ 544 jint total, tablelen, i, j; 545 unsigned char *cenbuf = NULL; 546 unsigned char *cenend; 547 unsigned char *cp; 548 #ifdef USE_MMAP 549 static jlong pagesize; 550 jlong offset; 551 #endif 552 unsigned char endbuf[ENDHDR]; 553 jint endhdrlen = ENDHDR; 554 jzcell *entries; 555 jint *table; 556 557 /* Clear previous zip error */ 558 zip->msg = NULL; 559 /* Get position of END header */ 560 if ((endpos = findEND(zip, endbuf)) == -1) 561 return -1; /* no END header or system error */ 562 563 if (endpos == 0) return 0; /* only END header present */ 564 565 freeCEN(zip); 566 /* Get position and length of central directory */ 567 cenlen = ENDSIZ(endbuf); 568 cenoff = ENDOFF(endbuf); 569 total = ENDTOT(endbuf); 570 if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL || 571 total == ZIP64_MAGICCOUNT) { 572 unsigned char end64buf[ZIP64_ENDHDR]; 573 if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) { 574 cenlen = ZIP64_ENDSIZ(end64buf); 575 cenoff = ZIP64_ENDOFF(end64buf); 576 total = (jint)ZIP64_ENDTOT(end64buf); 577 endpos = end64pos; 578 endhdrlen = ZIP64_ENDHDR; 579 } 580 } 581 582 if (cenlen > endpos) 583 ZIP_FORMAT_ERROR("invalid END header (bad central directory size)"); 584 cenpos = endpos - cenlen; 585 586 /* Get position of first local file (LOC) header, taking into 587 * account that there may be a stub prefixed to the zip file. */ 588 zip->locpos = cenpos - cenoff; 589 if (zip->locpos < 0) 590 ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)"); 591 592 #ifdef USE_MMAP 593 if (zip->usemmap) { 594 /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to 595 * read the jar file contents. However, this greatly increased the perceived 596 * footprint numbers because the mmap'ed pages were adding into the totals shown 597 * by 'ps' and 'top'. We switched to mmaping only the central directory of jar 598 * file while calling 'read' to read the rest of jar file. Here are a list of 599 * reasons apart from above of why we are doing so: 600 * 1. Greatly reduces mmap overhead after startup complete; 601 * 2. Avoids dual path code maintainance; 602 * 3. Greatly reduces risk of address space (not virtual memory) exhaustion. 603 */ 604 if (pagesize == 0) { 605 pagesize = (jlong)sysconf(_SC_PAGESIZE); 606 if (pagesize == 0) goto Catch; 607 } 608 if (cenpos > pagesize) { 609 offset = cenpos & ~(pagesize - 1); 610 } else { 611 offset = 0; 612 } 613 /* When we are not calling recursively, knownTotal is -1. */ 614 if (knownTotal == -1) { 615 void* mappedAddr; 616 /* Mmap the CEN and END part only. We have to figure 617 out the page size in order to make offset to be multiples of 618 page size. 619 */ 620 zip->mlen = cenpos - offset + cenlen + endhdrlen; 621 zip->offset = offset; 622 mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset); 623 zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL : 624 (unsigned char*)mappedAddr; 625 626 if (zip->maddr == NULL) { 627 jio_fprintf(stderr, "mmap failed for CEN and END part of zip file\n"); 628 goto Catch; 629 } 630 } 631 cenbuf = zip->maddr + cenpos - offset; 632 } else 633 #endif 634 { 635 if ((cenbuf = malloc((size_t) cenlen)) == NULL || 636 (readFullyAt(zip->zfd, cenbuf, cenlen, cenpos) == -1)) 637 goto Catch; 638 } 639 640 cenend = cenbuf + cenlen; 641 642 /* Initialize zip file data structures based on the total number 643 * of central directory entries as stored in ENDTOT. Since this 644 * is a 2-byte field, but we (and other zip implementations) 645 * support approx. 2**31 entries, we do not trust ENDTOT, but 646 * treat it only as a strong hint. When we call ourselves 647 * recursively, knownTotal will have the "true" value. 648 * 649 * Keep this path alive even with the Zip64 END support added, just 650 * for zip files that have more than 0xffff entries but don't have 651 * the Zip64 enabled. 652 */ 653 total = (knownTotal != -1) ? knownTotal : total; 654 entries = zip->entries = calloc(total, sizeof(entries[0])); 655 tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions 656 table = zip->table = malloc(tablelen * sizeof(table[0])); 657 if (entries == NULL || table == NULL) goto Catch; 658 for (j = 0; j < tablelen; j++) 659 table[j] = ZIP_ENDCHAIN; 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 (GETSIG(cp) != CENSIG) 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. 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. 750 */ 751 jzfile * 752 ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified) 753 { 754 static char errbuf[256]; 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 = "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. 795 */ 796 797 jzfile * 798 ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified) 799 { 800 return ZIP_Put_In_Cache0(name, zfd, pmsg, lastModified, JNI_TRUE); 801 } 802 803 jzfile * 804 ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified, 805 jboolean usemmap) 806 { 807 static char errbuf[256]; 808 jlong len; 809 jzfile *zip; 810 811 if ((zip = allocZip(name)) == NULL) { 812 return NULL; 813 } 814 815 #ifdef USE_MMAP 816 zip->usemmap = usemmap; 817 #endif 818 zip->refs = 1; 819 zip->lastModified = lastModified; 820 821 if (zfd == -1) { 822 if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0) 823 *pmsg = errbuf; 824 freeZip(zip); 825 return NULL; 826 } 827 828 len = zip->len = IO_Lseek(zfd, 0, SEEK_END); 829 if (len <= 0) { 830 if (len == 0) { /* zip file is empty */ 831 if (pmsg) { 832 *pmsg = "zip file is empty"; 833 } 834 } else { /* error */ 835 if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0) 836 *pmsg = errbuf; 837 } 838 ZFILE_Close(zfd); 839 freeZip(zip); 840 return NULL; 841 } 842 843 zip->zfd = zfd; 844 if (readCEN(zip, -1) < 0) { 845 /* An error occurred while trying to read the zip file */ 846 if (pmsg != 0) { 847 /* Set the zip error message */ 848 *pmsg = zip->msg; 849 } 850 freeZip(zip); 851 return NULL; 852 } 853 MLOCK(zfiles_lock); 854 zip->next = zfiles; 855 zfiles = zip; 856 MUNLOCK(zfiles_lock); 857 858 return zip; 859 } 860 861 /* 862 * Opens a zip file for reading. Returns the jzfile object or NULL 863 * if an error occurred. If a zip error occurred then *msg will be 864 * set to the error message text if msg != 0. Otherwise, *msg will be 865 * set to NULL. 866 */ 867 jzfile * JNICALL 868 ZIP_Open(const char *name, char **pmsg) 869 { 870 return ZIP_Open_Generic(name, pmsg, O_RDONLY, 0); 871 } 872 873 /* 874 * Closes the specified zip file object. 875 */ 876 void JNICALL 877 ZIP_Close(jzfile *zip) 878 { 879 MLOCK(zfiles_lock); 880 if (--zip->refs > 0) { 881 /* Still more references so just return */ 882 MUNLOCK(zfiles_lock); 883 return; 884 } 885 /* No other references so close the file and remove from list */ 886 if (zfiles == zip) { 887 zfiles = zfiles->next; 888 } else { 889 jzfile *zp; 890 for (zp = zfiles; zp->next != 0; zp = zp->next) { 891 if (zp->next == zip) { 892 zp->next = zip->next; 893 break; 894 } 895 } 896 } 897 MUNLOCK(zfiles_lock); 898 freeZip(zip); 899 return; 900 } 901 902 /* Empirically, most CEN headers are smaller than this. */ 903 #define AMPLE_CEN_HEADER_SIZE 160 904 905 /* A good buffer size when we want to read CEN headers sequentially. */ 906 #define CENCACHE_PAGESIZE 8192 907 908 static char * 909 readCENHeader(jzfile *zip, jlong cenpos, jint bufsize) 910 { 911 jint censize; 912 ZFILE zfd = zip->zfd; 913 char *cen; 914 if (bufsize > zip->len - cenpos) 915 bufsize = (jint)(zip->len - cenpos); 916 if ((cen = malloc(bufsize)) == NULL) goto Catch; 917 if (readFullyAt(zfd, cen, bufsize, cenpos) == -1) goto Catch; 918 censize = CENSIZE(cen); 919 if (censize <= bufsize) return cen; 920 if ((cen = realloc(cen, censize)) == NULL) goto Catch; 921 if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch; 922 return cen; 923 924 Catch: 925 free(cen); 926 return NULL; 927 } 928 929 static char * 930 sequentialAccessReadCENHeader(jzfile *zip, jlong cenpos) 931 { 932 cencache *cache = &zip->cencache; 933 char *cen; 934 if (cache->data != NULL 935 && (cenpos >= cache->pos) 936 && (cenpos + CENHDR <= cache->pos + CENCACHE_PAGESIZE)) 937 { 938 cen = cache->data + cenpos - cache->pos; 939 if (cenpos + CENSIZE(cen) <= cache->pos + CENCACHE_PAGESIZE) 940 /* A cache hit */ 941 return cen; 942 } 943 944 if ((cen = readCENHeader(zip, cenpos, CENCACHE_PAGESIZE)) == NULL) 945 return NULL; 946 free(cache->data); 947 cache->data = cen; 948 cache->pos = cenpos; 949 return cen; 950 } 951 952 typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint; 953 954 /* 955 * Return a new initialized jzentry corresponding to a given hash cell. 956 * In case of error, returns NULL. 957 * We already sanity-checked all the CEN headers for ZIP format errors 958 * in readCEN(), so we don't check them again here. 959 * The ZIP lock should be held here. 960 */ 961 static jzentry * 962 newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint) 963 { 964 jlong locoff; 965 jint nlen, elen, clen; 966 jzentry *ze; 967 char *cen; 968 969 if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL; 970 ze->name = NULL; 971 ze->extra = NULL; 972 ze->comment = NULL; 973 974 #ifdef USE_MMAP 975 if (zip->usemmap) { 976 cen = (char*) zip->maddr + zc->cenpos - zip->offset; 977 } else 978 #endif 979 { 980 if (accessHint == ACCESS_RANDOM) 981 cen = readCENHeader(zip, zc->cenpos, AMPLE_CEN_HEADER_SIZE); 982 else 983 cen = sequentialAccessReadCENHeader(zip, zc->cenpos); 984 if (cen == NULL) goto Catch; 985 } 986 987 nlen = CENNAM(cen); 988 elen = CENEXT(cen); 989 clen = CENCOM(cen); 990 ze->time = CENTIM(cen); 991 ze->size = CENLEN(cen); 992 ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen); 993 ze->crc = CENCRC(cen); 994 locoff = CENOFF(cen); 995 ze->pos = -(zip->locpos + locoff); 996 ze->flag = CENFLG(cen); 997 998 if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch; 999 memcpy(ze->name, cen + CENHDR, nlen); 1000 ze->name[nlen] = '\0'; 1001 if (elen > 0) { 1002 char *extra = cen + CENHDR + nlen; 1003 1004 /* This entry has "extra" data */ 1005 if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch; 1006 ze->extra[0] = (unsigned char) elen; 1007 ze->extra[1] = (unsigned char) (elen >> 8); 1008 memcpy(ze->extra+2, extra, elen); 1009 if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL || 1010 locoff == ZIP64_MAGICVAL) { 1011 jint off = 0; 1012 while ((off + 4) < elen) { // spec: HeaderID+DataSize+Data 1013 jint sz = SH(extra, off + 2); 1014 if (SH(extra, off) == ZIP64_EXTID) { 1015 off += 4; 1016 if (ze->size == ZIP64_MAGICVAL) { 1017 // if invalid zip64 extra fields, just skip 1018 if (sz < 8 || (off + 8) > elen) 1019 break; 1020 ze->size = LL(extra, off); 1021 sz -= 8; 1022 off += 8; 1023 } 1024 if (ze->csize == ZIP64_MAGICVAL) { 1025 if (sz < 8 || (off + 8) > elen) 1026 break; 1027 ze->csize = LL(extra, off); 1028 sz -= 8; 1029 off += 8; 1030 } 1031 if (locoff == ZIP64_MAGICVAL) { 1032 if (sz < 8 || (off + 8) > elen) 1033 break; 1034 ze->pos = -(zip->locpos + LL(extra, off)); 1035 sz -= 8; 1036 off += 8; 1037 } 1038 break; 1039 } 1040 off += (sz + 4); 1041 } 1042 } 1043 } 1044 1045 if (clen > 0) { 1046 /* This entry has a comment */ 1047 if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch; 1048 memcpy(ze->comment, cen + CENHDR + nlen + elen, clen); 1049 ze->comment[clen] = '\0'; 1050 } 1051 goto Finally; 1052 1053 Catch: 1054 free(ze->name); 1055 free(ze->extra); 1056 free(ze->comment); 1057 free(ze); 1058 ze = NULL; 1059 1060 Finally: 1061 #ifdef USE_MMAP 1062 if (!zip->usemmap) 1063 #endif 1064 if (cen != NULL && accessHint == ACCESS_RANDOM) free(cen); 1065 return ze; 1066 } 1067 1068 /* 1069 * Free the given jzentry. 1070 * In fact we maintain a one-entry cache of the most recently used 1071 * jzentry for each zip. This optimizes a common access pattern. 1072 */ 1073 1074 void 1075 ZIP_FreeEntry(jzfile *jz, jzentry *ze) 1076 { 1077 jzentry *last; 1078 ZIP_Lock(jz); 1079 last = jz->cache; 1080 jz->cache = ze; 1081 ZIP_Unlock(jz); 1082 if (last != NULL) { 1083 /* Free the previously cached jzentry */ 1084 free(last->name); 1085 if (last->extra) free(last->extra); 1086 if (last->comment) free(last->comment); 1087 free(last); 1088 } 1089 } 1090 1091 /* 1092 * Returns the zip entry corresponding to the specified name, or 1093 * NULL if not found. 1094 */ 1095 jzentry * 1096 ZIP_GetEntry(jzfile *zip, char *name, jint ulen) 1097 { 1098 unsigned int hsh = hash(name); 1099 jint idx; 1100 jzentry *ze = 0; 1101 1102 ZIP_Lock(zip); 1103 if (zip->total == 0) { 1104 goto Finally; 1105 } 1106 1107 idx = zip->table[hsh % zip->tablelen]; 1108 1109 /* 1110 * This while loop is an optimization where a double lookup 1111 * for name and name+/ is being performed. The name char 1112 * array has enough room at the end to try again with a 1113 * slash appended if the first table lookup does not succeed. 1114 */ 1115 while(1) { 1116 1117 /* Check the cached entry first */ 1118 ze = zip->cache; 1119 if (ze && strcmp(ze->name,name) == 0) { 1120 /* Cache hit! Remove and return the cached entry. */ 1121 zip->cache = 0; 1122 ZIP_Unlock(zip); 1123 return ze; 1124 } 1125 ze = 0; 1126 1127 /* 1128 * Search down the target hash chain for a cell whose 1129 * 32 bit hash matches the hashed name. 1130 */ 1131 while (idx != ZIP_ENDCHAIN) { 1132 jzcell *zc = &zip->entries[idx]; 1133 1134 if (zc->hash == hsh) { 1135 /* 1136 * OK, we've found a ZIP entry whose 32 bit hashcode 1137 * matches the name we're looking for. Try to read 1138 * its entry information from the CEN. If the CEN 1139 * name matches the name we're looking for, we're 1140 * done. 1141 * If the names don't match (which should be very rare) 1142 * we keep searching. 1143 */ 1144 ze = newEntry(zip, zc, ACCESS_RANDOM); 1145 if (ze && strcmp(ze->name, name)==0) { 1146 break; 1147 } 1148 if (ze != 0) { 1149 /* We need to release the lock across the free call */ 1150 ZIP_Unlock(zip); 1151 ZIP_FreeEntry(zip, ze); 1152 ZIP_Lock(zip); 1153 } 1154 ze = 0; 1155 } 1156 idx = zc->next; 1157 } 1158 1159 /* Entry found, return it */ 1160 if (ze != 0) { 1161 break; 1162 } 1163 1164 /* If no real length was passed in, we are done */ 1165 if (ulen == 0) { 1166 break; 1167 } 1168 1169 /* Slash is already there? */ 1170 if (name[ulen-1] == '/') { 1171 break; 1172 } 1173 1174 /* Add slash and try once more */ 1175 name[ulen] = '/'; 1176 name[ulen+1] = '\0'; 1177 hsh = hash_append(hsh, '/'); 1178 idx = zip->table[hsh % zip->tablelen]; 1179 ulen = 0; 1180 } 1181 1182 Finally: 1183 ZIP_Unlock(zip); 1184 return ze; 1185 } 1186 1187 /* 1188 * Returns the n'th (starting at zero) zip file entry, or NULL if the 1189 * specified index was out of range. 1190 */ 1191 jzentry * JNICALL 1192 ZIP_GetNextEntry(jzfile *zip, jint n) 1193 { 1194 jzentry *result; 1195 if (n < 0 || n >= zip->total) { 1196 return 0; 1197 } 1198 ZIP_Lock(zip); 1199 result = newEntry(zip, &zip->entries[n], ACCESS_SEQUENTIAL); 1200 ZIP_Unlock(zip); 1201 return result; 1202 } 1203 1204 /* 1205 * Locks the specified zip file for reading. 1206 */ 1207 void 1208 ZIP_Lock(jzfile *zip) 1209 { 1210 MLOCK(zip->lock); 1211 } 1212 1213 /* 1214 * Unlocks the specified zip file. 1215 */ 1216 void 1217 ZIP_Unlock(jzfile *zip) 1218 { 1219 MUNLOCK(zip->lock); 1220 } 1221 1222 /* 1223 * Returns the offset of the entry data within the zip file. 1224 * Returns -1 if an error occurred, in which case zip->msg will 1225 * contain the error text. 1226 */ 1227 jlong 1228 ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry) 1229 { 1230 /* The Zip file spec explicitly allows the LOC extra data size to 1231 * be different from the CEN extra data size, although the JDK 1232 * never creates such zip files. Since we cannot trust the CEN 1233 * extra data size, we need to read the LOC to determine the entry 1234 * data offset. We do this lazily to avoid touching the virtual 1235 * memory page containing the LOC when initializing jzentry 1236 * objects. (This speeds up javac by a factor of 10 when the JDK 1237 * is installed on a very slow filesystem.) 1238 */ 1239 if (entry->pos <= 0) { 1240 unsigned char loc[LOCHDR]; 1241 if (readFullyAt(zip->zfd, loc, LOCHDR, -(entry->pos)) == -1) { 1242 zip->msg = "error reading zip file"; 1243 return -1; 1244 } 1245 if (GETSIG(loc) != LOCSIG) { 1246 zip->msg = "invalid LOC header (bad signature)"; 1247 return -1; 1248 } 1249 entry->pos = (- entry->pos) + LOCHDR + LOCNAM(loc) + LOCEXT(loc); 1250 } 1251 return entry->pos; 1252 } 1253 1254 /* 1255 * Reads bytes from the specified zip entry. Assumes that the zip 1256 * file had been previously locked with ZIP_Lock(). Returns the 1257 * number of bytes read, or -1 if an error occurred. If zip->msg != 0 1258 * then a zip error occurred and zip->msg contains the error text. 1259 * 1260 * The current implementation does not support reading an entry that 1261 * has the size bigger than 2**32 bytes in ONE invocation. 1262 */ 1263 jint 1264 ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len) 1265 { 1266 jlong entry_size = (entry->csize != 0) ? entry->csize : entry->size; 1267 jlong start; 1268 1269 /* Clear previous zip error */ 1270 zip->msg = NULL; 1271 1272 /* Check specified position */ 1273 if (pos < 0 || pos > entry_size - 1) { 1274 zip->msg = "ZIP_Read: specified offset out of range"; 1275 return -1; 1276 } 1277 1278 /* Check specified length */ 1279 if (len <= 0) 1280 return 0; 1281 if (len > entry_size - pos) 1282 len = (jint)(entry_size - pos); 1283 1284 /* Get file offset to start reading data */ 1285 start = ZIP_GetEntryDataOffset(zip, entry); 1286 if (start < 0) 1287 return -1; 1288 start += pos; 1289 1290 if (start + len > zip->len) { 1291 zip->msg = "ZIP_Read: corrupt zip file: invalid entry size"; 1292 return -1; 1293 } 1294 1295 if (readFullyAt(zip->zfd, buf, len, start) == -1) { 1296 zip->msg = "ZIP_Read: error reading zip file"; 1297 return -1; 1298 } 1299 return len; 1300 } 1301 1302 1303 /* The maximum size of a stack-allocated buffer. 1304 */ 1305 #define BUF_SIZE 4096 1306 1307 /* 1308 * This function is used by the runtime system to load compressed entries 1309 * from ZIP/JAR files specified in the class path. It is defined here 1310 * so that it can be dynamically loaded by the runtime if the zip library 1311 * is found. 1312 * 1313 * The current implementation does not support reading an entry that 1314 * has the size bigger than 2**32 bytes in ONE invocation. 1315 */ 1316 jboolean 1317 InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg) 1318 { 1319 z_stream strm; 1320 char tmp[BUF_SIZE]; 1321 jlong pos = 0; 1322 jlong count = entry->csize; 1323 1324 *msg = 0; /* Reset error message */ 1325 1326 if (count == 0) { 1327 *msg = "inflateFully: entry not compressed"; 1328 return JNI_FALSE; 1329 } 1330 1331 memset(&strm, 0, sizeof(z_stream)); 1332 if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) { 1333 *msg = strm.msg; 1334 return JNI_FALSE; 1335 } 1336 1337 strm.next_out = buf; 1338 strm.avail_out = (uInt)entry->size; 1339 1340 while (count > 0) { 1341 jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : (jint)count; 1342 ZIP_Lock(zip); 1343 n = ZIP_Read(zip, entry, pos, tmp, n); 1344 ZIP_Unlock(zip); 1345 if (n <= 0) { 1346 if (n == 0) { 1347 *msg = "inflateFully: Unexpected end of file"; 1348 } 1349 inflateEnd(&strm); 1350 return JNI_FALSE; 1351 } 1352 pos += n; 1353 count -= n; 1354 strm.next_in = (Bytef *)tmp; 1355 strm.avail_in = n; 1356 do { 1357 switch (inflate(&strm, Z_PARTIAL_FLUSH)) { 1358 case Z_OK: 1359 break; 1360 case Z_STREAM_END: 1361 if (count != 0 || strm.total_out != entry->size) { 1362 *msg = "inflateFully: Unexpected end of stream"; 1363 inflateEnd(&strm); 1364 return JNI_FALSE; 1365 } 1366 break; 1367 default: 1368 break; 1369 } 1370 } while (strm.avail_in > 0); 1371 } 1372 inflateEnd(&strm); 1373 return JNI_TRUE; 1374 } 1375 1376 /* 1377 * The current implementation does not support reading an entry that 1378 * has the size bigger than 2**32 bytes in ONE invocation. 1379 */ 1380 jzentry * JNICALL 1381 ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP) 1382 { 1383 jzentry *entry = ZIP_GetEntry(zip, name, 0); 1384 if (entry) { 1385 *sizeP = (jint)entry->size; 1386 *nameLenP = strlen(entry->name); 1387 } 1388 return entry; 1389 } 1390 1391 /* 1392 * Reads a zip file entry into the specified byte array 1393 * When the method completes, it releases the jzentry. 1394 * Note: this is called from the separately delivered VM (hotspot/classic) 1395 * so we have to be careful to maintain the expected behaviour. 1396 */ 1397 jboolean JNICALL 1398 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname) 1399 { 1400 char *msg; 1401 1402 strcpy(entryname, entry->name); 1403 if (entry->csize == 0) { 1404 /* Entry is stored */ 1405 jlong pos = 0; 1406 jlong size = entry->size; 1407 while (pos < size) { 1408 jint n; 1409 jlong limit = ((((jlong) 1) << 31) - 1); 1410 jint count = (size - pos < limit) ? 1411 /* These casts suppress a VC++ Internal Compiler Error */ 1412 (jint) (size - pos) : 1413 (jint) limit; 1414 ZIP_Lock(zip); 1415 n = ZIP_Read(zip, entry, pos, buf, count); 1416 msg = zip->msg; 1417 ZIP_Unlock(zip); 1418 if (n == -1) { 1419 jio_fprintf(stderr, "%s: %s\n", zip->name, 1420 msg != 0 ? msg : strerror(errno)); 1421 return JNI_FALSE; 1422 } 1423 buf += n; 1424 pos += n; 1425 } 1426 } else { 1427 /* Entry is compressed */ 1428 int ok = InflateFully(zip, entry, buf, &msg); 1429 if (!ok) { 1430 if ((msg == NULL) || (*msg == 0)) { 1431 msg = zip->msg; 1432 } 1433 jio_fprintf(stderr, "%s: %s\n", zip->name, 1434 msg != 0 ? msg : strerror(errno)); 1435 return JNI_FALSE; 1436 } 1437 } 1438 1439 ZIP_FreeEntry(zip, entry); 1440 1441 return JNI_TRUE; 1442 }