6599383: Unable to open zip files more than 2GB in size
Reviewed-by: alanb
This commit is contained in:
parent
4f2325cf75
commit
ee5c2301ec
@ -135,11 +135,6 @@ ZFILE_Close(ZFILE zfd) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong
|
|
||||||
ZFILE_Lseek(ZFILE zfd, off_t offset, int whence) {
|
|
||||||
return IO_Lseek(zfd, offset, whence);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ZFILE_read(ZFILE zfd, char *buf, jint nbytes) {
|
ZFILE_read(ZFILE zfd, char *buf, jint nbytes) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@ -216,7 +211,7 @@ readFully(ZFILE zfd, void *buf, jlong len) {
|
|||||||
static int
|
static int
|
||||||
readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset)
|
readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset)
|
||||||
{
|
{
|
||||||
if (ZFILE_Lseek(zfd, (off_t) offset, SEEK_SET) == -1) {
|
if (IO_Lseek(zfd, offset, SEEK_SET) == -1) {
|
||||||
return -1; /* lseek failure. */
|
return -1; /* lseek failure. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +471,7 @@ readCEN(jzfile *zip, jint knownTotal)
|
|||||||
unsigned char *cp;
|
unsigned char *cp;
|
||||||
#ifdef USE_MMAP
|
#ifdef USE_MMAP
|
||||||
static jlong pagesize;
|
static jlong pagesize;
|
||||||
off_t offset;
|
jlong offset;
|
||||||
#endif
|
#endif
|
||||||
unsigned char endbuf[ENDHDR];
|
unsigned char endbuf[ENDHDR];
|
||||||
jzcell *entries;
|
jzcell *entries;
|
||||||
@ -534,7 +529,7 @@ readCEN(jzfile *zip, jint knownTotal)
|
|||||||
*/
|
*/
|
||||||
zip->mlen = cenpos - offset + cenlen + ENDHDR;
|
zip->mlen = cenpos - offset + cenlen + ENDHDR;
|
||||||
zip->offset = offset;
|
zip->offset = offset;
|
||||||
mappedAddr = mmap(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, offset);
|
mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
|
||||||
zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
|
zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
|
||||||
(unsigned char*)mappedAddr;
|
(unsigned char*)mappedAddr;
|
||||||
|
|
||||||
@ -720,7 +715,7 @@ ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = zip->len = ZFILE_Lseek(zfd, 0, SEEK_END);
|
len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
if (len == 0) { /* zip file is empty */
|
if (len == 0) { /* zip file is empty */
|
||||||
if (pmsg) {
|
if (pmsg) {
|
||||||
|
@ -174,7 +174,7 @@ typedef struct jzfile { /* Zip file */
|
|||||||
#ifdef USE_MMAP
|
#ifdef USE_MMAP
|
||||||
unsigned char *maddr; /* beginning address of the CEN & ENDHDR */
|
unsigned char *maddr; /* beginning address of the CEN & ENDHDR */
|
||||||
jlong mlen; /* length (in bytes) mmaped */
|
jlong mlen; /* length (in bytes) mmaped */
|
||||||
off_t offset; /* offset of the mmapped region from the
|
jlong offset; /* offset of the mmapped region from the
|
||||||
start of the file. */
|
start of the file. */
|
||||||
#else
|
#else
|
||||||
cencache cencache; /* CEN header cache */
|
cencache cencache; /* CEN header cache */
|
||||||
|
138
jdk/test/java/util/zip/ZipFile/LargeZipFile.java
Normal file
138
jdk/test/java/util/zip/ZipFile/LargeZipFile.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import java.io.*;
|
||||||
|
import java.nio.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.*;
|
||||||
|
|
||||||
|
public class LargeZipFile {
|
||||||
|
// If true, don't delete large ZIP file created for test.
|
||||||
|
static final boolean debug = System.getProperty("debug") != null;
|
||||||
|
|
||||||
|
static final int DATA_LEN = 1024 * 1024;
|
||||||
|
static final int DATA_SIZE = 8;
|
||||||
|
|
||||||
|
static long fileSize = 3L * 1024L * 1024L * 1024L; // 3GB
|
||||||
|
|
||||||
|
static boolean userFile = false;
|
||||||
|
|
||||||
|
static byte[] data;
|
||||||
|
static File largeFile;
|
||||||
|
static String lastEntryName;
|
||||||
|
|
||||||
|
/* args can be empty, in which case check a 3 GB file which is created for
|
||||||
|
* this test (and then deleted). Or it can be a number, in which case
|
||||||
|
* that designates the size of the file that's created for this test (and
|
||||||
|
* then deleted). Or it can be the name of a file to use for the test, in
|
||||||
|
* which case it is *not* deleted. Note that in this last case, the data
|
||||||
|
* comparison might fail.
|
||||||
|
*/
|
||||||
|
static void realMain (String[] args) throws Throwable {
|
||||||
|
if (args.length > 0) {
|
||||||
|
try {
|
||||||
|
fileSize = Long.parseLong(args[0]);
|
||||||
|
System.out.println("Testing with file of size " + fileSize);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
largeFile = new File(args[0]);
|
||||||
|
if (!largeFile.exists()) {
|
||||||
|
throw new Exception("Specified file " + args[0] + " does not exist");
|
||||||
|
}
|
||||||
|
userFile = true;
|
||||||
|
System.out.println("Testing with user-provided file " + largeFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File testDir = null;
|
||||||
|
if (largeFile == null) {
|
||||||
|
testDir = new File(System.getProperty("test.scratch", "."),
|
||||||
|
"LargeZip");
|
||||||
|
if (testDir.exists()) {
|
||||||
|
if (!testDir.delete()) {
|
||||||
|
throw new Exception("Cannot delete already-existing test directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check(!testDir.exists() && testDir.mkdirs());
|
||||||
|
largeFile = new File(testDir, "largezip.zip");
|
||||||
|
createLargeZip();
|
||||||
|
}
|
||||||
|
|
||||||
|
readLargeZip();
|
||||||
|
|
||||||
|
if (!userFile && !debug) {
|
||||||
|
check(largeFile.delete());
|
||||||
|
check(testDir.delete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createLargeZip() throws Throwable {
|
||||||
|
int iterations = DATA_LEN / DATA_SIZE;
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(DATA_SIZE);
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
bb.putDouble(0, Math.random());
|
||||||
|
baos.write(bb.array(), 0, DATA_SIZE);
|
||||||
|
}
|
||||||
|
data = baos.toByteArray();
|
||||||
|
|
||||||
|
ZipOutputStream zos = new ZipOutputStream(
|
||||||
|
new BufferedOutputStream(new FileOutputStream(largeFile)));
|
||||||
|
long length = 0;
|
||||||
|
while (length < fileSize) {
|
||||||
|
ZipEntry ze = new ZipEntry("entry-" + length);
|
||||||
|
lastEntryName = ze.getName();
|
||||||
|
zos.putNextEntry(ze);
|
||||||
|
zos.write(data, 0, data.length);
|
||||||
|
zos.closeEntry();
|
||||||
|
length = largeFile.length();
|
||||||
|
}
|
||||||
|
System.out.println("Last entry written is " + lastEntryName);
|
||||||
|
zos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void readLargeZip() throws Throwable {
|
||||||
|
ZipFile zipFile = new ZipFile(largeFile);
|
||||||
|
ZipEntry entry = null;
|
||||||
|
String entryName = null;
|
||||||
|
int count = 0;
|
||||||
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
entry = entries.nextElement();
|
||||||
|
entryName = entry.getName();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
System.out.println("Number of entries read: " + count);
|
||||||
|
System.out.println("Last entry read is " + entryName);
|
||||||
|
check(!entry.isDirectory());
|
||||||
|
if (check(entryName.equals(lastEntryName))) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
InputStream is = zipFile.getInputStream(entry);
|
||||||
|
byte buf[] = new byte[4096];
|
||||||
|
int len;
|
||||||
|
while ((len = is.read(buf)) >= 0) {
|
||||||
|
baos.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
baos.close();
|
||||||
|
is.close();
|
||||||
|
check(Arrays.equals(data, baos.toByteArray()));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
zipFile.close();
|
||||||
|
} catch (IOException ioe) {/* what can you do */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------- Infrastructure ---------------------------
|
||||||
|
static volatile int passed = 0, failed = 0;
|
||||||
|
static void pass() {passed++;}
|
||||||
|
static void pass(String msg) {System.out.println(msg); passed++;}
|
||||||
|
static void fail() {failed++; Thread.dumpStack();}
|
||||||
|
static void fail(String msg) {System.out.println(msg); fail();}
|
||||||
|
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||||
|
static void unexpected(Throwable t, String msg) {
|
||||||
|
System.out.println(msg); failed++; t.printStackTrace();}
|
||||||
|
static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
|
||||||
|
static void equal(Object x, Object y) {
|
||||||
|
if (x == null ? y == null : x.equals(y)) pass();
|
||||||
|
else fail(x + " not equal to " + y);}
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||||
|
System.out.println("\nPassed = " + passed + " failed = " + failed);
|
||||||
|
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user