src/share/native/java/util/zip/zip_util.c

Print this page




 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;