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