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