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