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