254 #ifdef USE_MMAP |
254 #ifdef USE_MMAP |
255 if (zip->maddr != NULL) munmap((char *)zip->maddr, zip->mlen); |
255 if (zip->maddr != NULL) munmap((char *)zip->maddr, zip->mlen); |
256 #else |
256 #else |
257 free(zip->cencache.data); |
257 free(zip->cencache.data); |
258 #endif |
258 #endif |
|
259 if (zip->comment != NULL) |
|
260 free(zip->comment); |
259 if (zip->zfd != -1) ZFILE_Close(zip->zfd); |
261 if (zip->zfd != -1) ZFILE_Close(zip->zfd); |
260 free(zip); |
262 free(zip); |
261 } |
263 } |
262 |
264 |
263 /* The END header is followed by a variable length comment of size < 64k. */ |
265 /* The END header is followed by a variable length comment of size < 64k. */ |
264 static const jlong END_MAXLEN = 0xFFFF + ENDHDR; |
266 static const jlong END_MAXLEN = 0xFFFF + ENDHDR; |
265 |
267 |
266 #define READBLOCKSZ 128 |
268 #define READBLOCKSZ 128 |
|
269 |
|
270 static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) { |
|
271 /* ENDSIG matched, however the size of file comment in it does not |
|
272 match the real size. One "common" cause for this problem is some |
|
273 "extra" bytes are padded at the end of the zipfile. |
|
274 Let's do some extra verification, we don't care about the performance |
|
275 in this situation. |
|
276 */ |
|
277 jlong cenpos = endpos - ENDSIZ(endbuf); |
|
278 jlong locpos = cenpos - ENDOFF(endbuf); |
|
279 char buf[4]; |
|
280 return (cenpos >= 0 && |
|
281 locpos >= 0 && |
|
282 readFullyAt(zip->zfd, buf, sizeof(buf), cenpos) != -1 && |
|
283 GETSIG(buf) == CENSIG && |
|
284 readFullyAt(zip->zfd, buf, sizeof(buf), locpos) != -1 && |
|
285 GETSIG(buf) == LOCSIG); |
|
286 } |
267 |
287 |
268 /* |
288 /* |
269 * Searches for end of central directory (END) header. The contents of |
289 * Searches for end of central directory (END) header. The contents of |
270 * the END header will be read and placed in endbuf. Returns the file |
290 * the END header will be read and placed in endbuf. Returns the file |
271 * position of the END header, otherwise returns -1 if the END header |
291 * position of the END header, otherwise returns -1 if the END header |
278 jlong pos; |
298 jlong pos; |
279 const jlong len = zip->len; |
299 const jlong len = zip->len; |
280 const ZFILE zfd = zip->zfd; |
300 const ZFILE zfd = zip->zfd; |
281 const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0; |
301 const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0; |
282 const jlong minPos = minHDR - (sizeof(buf)-ENDHDR); |
302 const jlong minPos = minHDR - (sizeof(buf)-ENDHDR); |
|
303 jint clen; |
283 |
304 |
284 for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) { |
305 for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) { |
285 |
306 |
286 int i; |
307 int i; |
287 jlong off = 0; |
308 jlong off = 0; |
300 for (i = sizeof(buf) - ENDHDR; i >= 0; i--) { |
321 for (i = sizeof(buf) - ENDHDR; i >= 0; i--) { |
301 if (buf[i+0] == 'P' && |
322 if (buf[i+0] == 'P' && |
302 buf[i+1] == 'K' && |
323 buf[i+1] == 'K' && |
303 buf[i+2] == '\005' && |
324 buf[i+2] == '\005' && |
304 buf[i+3] == '\006' && |
325 buf[i+3] == '\006' && |
305 (pos + i + ENDHDR + ENDCOM(buf + i) == len)) { |
326 ((pos + i + ENDHDR + ENDCOM(buf + i) == len) |
306 /* Found END header */ |
327 || verifyEND(zip, pos + i, buf + i))) { |
307 memcpy(endbuf, buf + i, ENDHDR); |
328 /* Found END header */ |
308 return pos + i; |
329 memcpy(endbuf, buf + i, ENDHDR); |
|
330 |
|
331 clen = ENDCOM(endbuf); |
|
332 if (clen != 0) { |
|
333 zip->comment = malloc(clen + 1); |
|
334 if (zip->comment == NULL) { |
|
335 return -1; |
|
336 } |
|
337 if (readFullyAt(zfd, zip->comment, clen, pos + i + ENDHDR) |
|
338 == -1) { |
|
339 free(zip->comment); |
|
340 zip->comment = NULL; |
|
341 return -1; |
|
342 } |
|
343 zip->comment[clen] = '\0'; |
|
344 zip->clen = clen; |
|
345 } |
|
346 return pos + i; |
309 } |
347 } |
310 } |
348 } |
311 } |
349 } |
|
350 |
312 return -1; /* END header not found */ |
351 return -1; /* END header not found */ |
313 } |
352 } |
314 |
353 |
315 /* |
354 /* |
316 * Searches for the ZIP64 end of central directory (END) header. The |
355 * Searches for the ZIP64 end of central directory (END) header. The |