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