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