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
|
||||
}
|
||||
|
||||
static jlong
|
||||
ZFILE_Lseek(ZFILE zfd, off_t offset, int whence) {
|
||||
return IO_Lseek(zfd, offset, whence);
|
||||
}
|
||||
|
||||
static int
|
||||
ZFILE_read(ZFILE zfd, char *buf, jint nbytes) {
|
||||
#ifdef WIN32
|
||||
@ -216,7 +211,7 @@ readFully(ZFILE zfd, void *buf, jlong len) {
|
||||
static int
|
||||
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. */
|
||||
}
|
||||
|
||||
@ -476,7 +471,7 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||
unsigned char *cp;
|
||||
#ifdef USE_MMAP
|
||||
static jlong pagesize;
|
||||
off_t offset;
|
||||
jlong offset;
|
||||
#endif
|
||||
unsigned char endbuf[ENDHDR];
|
||||
jzcell *entries;
|
||||
@ -534,7 +529,7 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||
*/
|
||||
zip->mlen = cenpos - offset + cenlen + ENDHDR;
|
||||
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 :
|
||||
(unsigned char*)mappedAddr;
|
||||
|
||||
@ -720,7 +715,7 @@ ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified)
|
||||
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) { /* zip file is empty */
|
||||
if (pmsg) {
|
||||
|
@ -174,7 +174,7 @@ typedef struct jzfile { /* Zip file */
|
||||
#ifdef USE_MMAP
|
||||
unsigned char *maddr; /* beginning address of the CEN & ENDHDR */
|
||||
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. */
|
||||
#else
|
||||
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