297 * was not found or an error occurred.
298 */
299 static jlong
300 findEND(jzfile *zip, void *endbuf)
301 {
302 char buf[READBLOCKSZ];
303 jlong pos;
304 const jlong len = zip->len;
305 const ZFILE zfd = zip->zfd;
306 const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0;
307 const jlong minPos = minHDR - (sizeof(buf)-ENDHDR);
308 jint clen;
309
310 for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) {
311
312 int i;
313 jlong off = 0;
314 if (pos < 0) {
315 /* Pretend there are some NUL bytes before start of file */
316 off = -pos;
317 memset(buf, '\0', off);
318 }
319
320 if (readFullyAt(zfd, buf + off, sizeof(buf) - off,
321 pos + off) == -1) {
322 return -1; /* System error */
323 }
324
325 /* Now scan the block backwards for END header signature */
326 for (i = sizeof(buf) - ENDHDR; i >= 0; i--) {
327 if (buf[i+0] == 'P' &&
328 buf[i+1] == 'K' &&
329 buf[i+2] == '\005' &&
330 buf[i+3] == '\006' &&
331 ((pos + i + ENDHDR + ENDCOM(buf + i) == len)
332 || verifyEND(zip, pos + i, buf + i))) {
333 /* Found END header */
334 memcpy(endbuf, buf + i, ENDHDR);
335
336 clen = ENDCOM(endbuf);
337 if (clen != 0) {
409 int h = 0;
410 while (length-- > 0)
411 h = 31*h + *s++;
412 return h;
413 }
414
415 static unsigned int
416 hash_append(unsigned int hash, char c)
417 {
418 return ((int)hash)*31 + c;
419 }
420
421 /*
422 * Returns true if the specified entry's name begins with the string
423 * "META-INF/" irrespective of case.
424 */
425 static int
426 isMetaName(const char *name, int length)
427 {
428 const char *s;
429 if (length < sizeof("META-INF/") - 1)
430 return 0;
431 for (s = "META-INF/"; *s != '\0'; s++) {
432 char c = *name++;
433 // Avoid toupper; it's locale-dependent
434 if (c >= 'a' && c <= 'z') c += 'A' - 'a';
435 if (*s != c)
436 return 0;
437 }
438 return 1;
439 }
440
441 /*
442 * Increases the capacity of zip->metanames.
443 * Returns non-zero in case of allocation error.
444 */
445 static int
446 growMetaNames(jzfile *zip)
447 {
448 jint i;
449 /* double the meta names array */
895 }
896 }
897 MUNLOCK(zfiles_lock);
898 freeZip(zip);
899 return;
900 }
901
902 /* Empirically, most CEN headers are smaller than this. */
903 #define AMPLE_CEN_HEADER_SIZE 160
904
905 /* A good buffer size when we want to read CEN headers sequentially. */
906 #define CENCACHE_PAGESIZE 8192
907
908 static char *
909 readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
910 {
911 jint censize;
912 ZFILE zfd = zip->zfd;
913 char *cen;
914 if (bufsize > zip->len - cenpos)
915 bufsize = zip->len - cenpos;
916 if ((cen = malloc(bufsize)) == NULL) goto Catch;
917 if (readFullyAt(zfd, cen, bufsize, cenpos) == -1) goto Catch;
918 censize = CENSIZE(cen);
919 if (censize <= bufsize) return cen;
920 if ((cen = realloc(cen, censize)) == NULL) goto Catch;
921 if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;
922 return cen;
923
924 Catch:
925 free(cen);
926 return NULL;
927 }
928
929 static char *
930 sequentialAccessReadCENHeader(jzfile *zip, jlong cenpos)
931 {
932 cencache *cache = &zip->cencache;
933 char *cen;
934 if (cache->data != NULL
935 && (cenpos >= cache->pos)
1239 if (entry->pos <= 0) {
1240 unsigned char loc[LOCHDR];
1241 if (readFullyAt(zip->zfd, loc, LOCHDR, -(entry->pos)) == -1) {
1242 zip->msg = "error reading zip file";
1243 return -1;
1244 }
1245 if (GETSIG(loc) != LOCSIG) {
1246 zip->msg = "invalid LOC header (bad signature)";
1247 return -1;
1248 }
1249 entry->pos = (- entry->pos) + LOCHDR + LOCNAM(loc) + LOCEXT(loc);
1250 }
1251 return entry->pos;
1252 }
1253
1254 /*
1255 * Reads bytes from the specified zip entry. Assumes that the zip
1256 * file had been previously locked with ZIP_Lock(). Returns the
1257 * number of bytes read, or -1 if an error occurred. If zip->msg != 0
1258 * then a zip error occurred and zip->msg contains the error text.
1259 */
1260 jint
1261 ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
1262 {
1263 jlong entry_size = (entry->csize != 0) ? entry->csize : entry->size;
1264 jlong start;
1265
1266 /* Clear previous zip error */
1267 zip->msg = NULL;
1268
1269 /* Check specified position */
1270 if (pos < 0 || pos > entry_size - 1) {
1271 zip->msg = "ZIP_Read: specified offset out of range";
1272 return -1;
1273 }
1274
1275 /* Check specified length */
1276 if (len <= 0)
1277 return 0;
1278 if (len > entry_size - pos)
1279 len = entry_size - pos;
1280
1281 /* Get file offset to start reading data */
1282 start = ZIP_GetEntryDataOffset(zip, entry);
1283 if (start < 0)
1284 return -1;
1285 start += pos;
1286
1287 if (start + len > zip->len) {
1288 zip->msg = "ZIP_Read: corrupt zip file: invalid entry size";
1289 return -1;
1290 }
1291
1292 if (readFullyAt(zip->zfd, buf, len, start) == -1) {
1293 zip->msg = "ZIP_Read: error reading zip file";
1294 return -1;
1295 }
1296 return len;
1297 }
1298
1299
1300 /* The maximum size of a stack-allocated buffer.
1301 */
1302 #define BUF_SIZE 4096
1303
1304 /*
1305 * This function is used by the runtime system to load compressed entries
1306 * from ZIP/JAR files specified in the class path. It is defined here
1307 * so that it can be dynamically loaded by the runtime if the zip library
1308 * is found.
1309 */
1310 jboolean
1311 InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
1312 {
1313 z_stream strm;
1314 char tmp[BUF_SIZE];
1315 jlong pos = 0;
1316 jlong count = entry->csize;
1317 jboolean status;
1318
1319 *msg = 0; /* Reset error message */
1320
1321 if (count == 0) {
1322 *msg = "inflateFully: entry not compressed";
1323 return JNI_FALSE;
1324 }
1325
1326 memset(&strm, 0, sizeof(z_stream));
1327 if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
1328 *msg = strm.msg;
1329 return JNI_FALSE;
1330 }
1331
1332 strm.next_out = buf;
1333 strm.avail_out = entry->size;
1334
1335 while (count > 0) {
1336 jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : count;
1337 ZIP_Lock(zip);
1338 n = ZIP_Read(zip, entry, pos, tmp, n);
1339 ZIP_Unlock(zip);
1340 if (n <= 0) {
1341 if (n == 0) {
1342 *msg = "inflateFully: Unexpected end of file";
1343 }
1344 inflateEnd(&strm);
1345 return JNI_FALSE;
1346 }
1347 pos += n;
1348 count -= n;
1349 strm.next_in = (Bytef *)tmp;
1350 strm.avail_in = n;
1351 do {
1352 switch (inflate(&strm, Z_PARTIAL_FLUSH)) {
1353 case Z_OK:
1354 break;
1355 case Z_STREAM_END:
1356 if (count != 0 || strm.total_out != entry->size) {
1357 *msg = "inflateFully: Unexpected end of stream";
1358 inflateEnd(&strm);
1359 return JNI_FALSE;
1360 }
1361 break;
1362 default:
1363 break;
1364 }
1365 } while (strm.avail_in > 0);
1366 }
1367 inflateEnd(&strm);
1368 return JNI_TRUE;
1369 }
1370
1371 jzentry * JNICALL
1372 ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
1373 {
1374 jzentry *entry = ZIP_GetEntry(zip, name, 0);
1375 if (entry) {
1376 *sizeP = entry->size;
1377 *nameLenP = strlen(entry->name);
1378 }
1379 return entry;
1380 }
1381
1382 /*
1383 * Reads a zip file entry into the specified byte array
1384 * When the method completes, it releases the jzentry.
1385 * Note: this is called from the separately delivered VM (hotspot/classic)
1386 * so we have to be careful to maintain the expected behaviour.
1387 */
1388 jboolean JNICALL
1389 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
1390 {
1391 char *msg;
1392
1393 strcpy(entryname, entry->name);
1394 if (entry->csize == 0) {
1395 /* Entry is stored */
1396 jlong pos = 0;
|
297 * was not found or an error occurred.
298 */
299 static jlong
300 findEND(jzfile *zip, void *endbuf)
301 {
302 char buf[READBLOCKSZ];
303 jlong pos;
304 const jlong len = zip->len;
305 const ZFILE zfd = zip->zfd;
306 const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0;
307 const jlong minPos = minHDR - (sizeof(buf)-ENDHDR);
308 jint clen;
309
310 for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) {
311
312 int i;
313 jlong off = 0;
314 if (pos < 0) {
315 /* Pretend there are some NUL bytes before start of file */
316 off = -pos;
317 memset(buf, '\0', (size_t)off);
318 }
319
320 if (readFullyAt(zfd, buf + off, sizeof(buf) - off,
321 pos + off) == -1) {
322 return -1; /* System error */
323 }
324
325 /* Now scan the block backwards for END header signature */
326 for (i = sizeof(buf) - ENDHDR; i >= 0; i--) {
327 if (buf[i+0] == 'P' &&
328 buf[i+1] == 'K' &&
329 buf[i+2] == '\005' &&
330 buf[i+3] == '\006' &&
331 ((pos + i + ENDHDR + ENDCOM(buf + i) == len)
332 || verifyEND(zip, pos + i, buf + i))) {
333 /* Found END header */
334 memcpy(endbuf, buf + i, ENDHDR);
335
336 clen = ENDCOM(endbuf);
337 if (clen != 0) {
409 int h = 0;
410 while (length-- > 0)
411 h = 31*h + *s++;
412 return h;
413 }
414
415 static unsigned int
416 hash_append(unsigned int hash, char c)
417 {
418 return ((int)hash)*31 + c;
419 }
420
421 /*
422 * Returns true if the specified entry's name begins with the string
423 * "META-INF/" irrespective of case.
424 */
425 static int
426 isMetaName(const char *name, int length)
427 {
428 const char *s;
429 if (length < (int)sizeof("META-INF/") - 1)
430 return 0;
431 for (s = "META-INF/"; *s != '\0'; s++) {
432 char c = *name++;
433 // Avoid toupper; it's locale-dependent
434 if (c >= 'a' && c <= 'z') c += 'A' - 'a';
435 if (*s != c)
436 return 0;
437 }
438 return 1;
439 }
440
441 /*
442 * Increases the capacity of zip->metanames.
443 * Returns non-zero in case of allocation error.
444 */
445 static int
446 growMetaNames(jzfile *zip)
447 {
448 jint i;
449 /* double the meta names array */
895 }
896 }
897 MUNLOCK(zfiles_lock);
898 freeZip(zip);
899 return;
900 }
901
902 /* Empirically, most CEN headers are smaller than this. */
903 #define AMPLE_CEN_HEADER_SIZE 160
904
905 /* A good buffer size when we want to read CEN headers sequentially. */
906 #define CENCACHE_PAGESIZE 8192
907
908 static char *
909 readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
910 {
911 jint censize;
912 ZFILE zfd = zip->zfd;
913 char *cen;
914 if (bufsize > zip->len - cenpos)
915 bufsize = (jint)(zip->len - cenpos);
916 if ((cen = malloc(bufsize)) == NULL) goto Catch;
917 if (readFullyAt(zfd, cen, bufsize, cenpos) == -1) goto Catch;
918 censize = CENSIZE(cen);
919 if (censize <= bufsize) return cen;
920 if ((cen = realloc(cen, censize)) == NULL) goto Catch;
921 if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;
922 return cen;
923
924 Catch:
925 free(cen);
926 return NULL;
927 }
928
929 static char *
930 sequentialAccessReadCENHeader(jzfile *zip, jlong cenpos)
931 {
932 cencache *cache = &zip->cencache;
933 char *cen;
934 if (cache->data != NULL
935 && (cenpos >= cache->pos)
1239 if (entry->pos <= 0) {
1240 unsigned char loc[LOCHDR];
1241 if (readFullyAt(zip->zfd, loc, LOCHDR, -(entry->pos)) == -1) {
1242 zip->msg = "error reading zip file";
1243 return -1;
1244 }
1245 if (GETSIG(loc) != LOCSIG) {
1246 zip->msg = "invalid LOC header (bad signature)";
1247 return -1;
1248 }
1249 entry->pos = (- entry->pos) + LOCHDR + LOCNAM(loc) + LOCEXT(loc);
1250 }
1251 return entry->pos;
1252 }
1253
1254 /*
1255 * Reads bytes from the specified zip entry. Assumes that the zip
1256 * file had been previously locked with ZIP_Lock(). Returns the
1257 * number of bytes read, or -1 if an error occurred. If zip->msg != 0
1258 * then a zip error occurred and zip->msg contains the error text.
1259 *
1260 * The current implementation does not support reading an entry that
1261 * has the size bigger than 2**32 bytes in ONE invocation.
1262 */
1263 jint
1264 ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
1265 {
1266 jlong entry_size = (entry->csize != 0) ? entry->csize : entry->size;
1267 jlong start;
1268
1269 /* Clear previous zip error */
1270 zip->msg = NULL;
1271
1272 /* Check specified position */
1273 if (pos < 0 || pos > entry_size - 1) {
1274 zip->msg = "ZIP_Read: specified offset out of range";
1275 return -1;
1276 }
1277
1278 /* Check specified length */
1279 if (len <= 0)
1280 return 0;
1281 if (len > entry_size - pos)
1282 len = (jint)(entry_size - pos);
1283
1284 /* Get file offset to start reading data */
1285 start = ZIP_GetEntryDataOffset(zip, entry);
1286 if (start < 0)
1287 return -1;
1288 start += pos;
1289
1290 if (start + len > zip->len) {
1291 zip->msg = "ZIP_Read: corrupt zip file: invalid entry size";
1292 return -1;
1293 }
1294
1295 if (readFullyAt(zip->zfd, buf, len, start) == -1) {
1296 zip->msg = "ZIP_Read: error reading zip file";
1297 return -1;
1298 }
1299 return len;
1300 }
1301
1302
1303 /* The maximum size of a stack-allocated buffer.
1304 */
1305 #define BUF_SIZE 4096
1306
1307 /*
1308 * This function is used by the runtime system to load compressed entries
1309 * from ZIP/JAR files specified in the class path. It is defined here
1310 * so that it can be dynamically loaded by the runtime if the zip library
1311 * is found.
1312 *
1313 * The current implementation does not support reading an entry that
1314 * has the size bigger than 2**32 bytes in ONE invocation.
1315 */
1316 jboolean
1317 InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
1318 {
1319 z_stream strm;
1320 char tmp[BUF_SIZE];
1321 jlong pos = 0;
1322 jlong count = entry->csize;
1323
1324 *msg = 0; /* Reset error message */
1325
1326 if (count == 0) {
1327 *msg = "inflateFully: entry not compressed";
1328 return JNI_FALSE;
1329 }
1330
1331 memset(&strm, 0, sizeof(z_stream));
1332 if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
1333 *msg = strm.msg;
1334 return JNI_FALSE;
1335 }
1336
1337 strm.next_out = buf;
1338 strm.avail_out = (uInt)entry->size;
1339
1340 while (count > 0) {
1341 jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : (jint)count;
1342 ZIP_Lock(zip);
1343 n = ZIP_Read(zip, entry, pos, tmp, n);
1344 ZIP_Unlock(zip);
1345 if (n <= 0) {
1346 if (n == 0) {
1347 *msg = "inflateFully: Unexpected end of file";
1348 }
1349 inflateEnd(&strm);
1350 return JNI_FALSE;
1351 }
1352 pos += n;
1353 count -= n;
1354 strm.next_in = (Bytef *)tmp;
1355 strm.avail_in = n;
1356 do {
1357 switch (inflate(&strm, Z_PARTIAL_FLUSH)) {
1358 case Z_OK:
1359 break;
1360 case Z_STREAM_END:
1361 if (count != 0 || strm.total_out != entry->size) {
1362 *msg = "inflateFully: Unexpected end of stream";
1363 inflateEnd(&strm);
1364 return JNI_FALSE;
1365 }
1366 break;
1367 default:
1368 break;
1369 }
1370 } while (strm.avail_in > 0);
1371 }
1372 inflateEnd(&strm);
1373 return JNI_TRUE;
1374 }
1375
1376 /*
1377 * The current implementation does not support reading an entry that
1378 * has the size bigger than 2**32 bytes in ONE invocation.
1379 */
1380 jzentry * JNICALL
1381 ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
1382 {
1383 jzentry *entry = ZIP_GetEntry(zip, name, 0);
1384 if (entry) {
1385 *sizeP = (jint)entry->size;
1386 *nameLenP = strlen(entry->name);
1387 }
1388 return entry;
1389 }
1390
1391 /*
1392 * Reads a zip file entry into the specified byte array
1393 * When the method completes, it releases the jzentry.
1394 * Note: this is called from the separately delivered VM (hotspot/classic)
1395 * so we have to be careful to maintain the expected behaviour.
1396 */
1397 jboolean JNICALL
1398 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
1399 {
1400 char *msg;
1401
1402 strcpy(entryname, entry->name);
1403 if (entry->csize == 0) {
1404 /* Entry is stored */
1405 jlong pos = 0;
|