JDK-6374379 : ZipFile class cannot open zip files with long filenames
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.jar
  • Affected Version: 1.4.0,5.0u6,6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS:
    generic,windows_nt,windows_2000,windows_xp generic,windows_nt,windows_2000,windows_xp
  • CPU: generic,x86
  • Submitted: 2006-01-19
  • Updated: 2010-05-09
  • Resolved: 2006-05-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u15Fixed 6 b86Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
OPERATING SYSTEM(S):
Windows

FULL JDK VERSION(S):
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode)

DESCRIPTION:
Sunbug 6182812 allowed unicode and long filenames within Java classes including FileOutputStream.

java.util.zip.ZipFile remains unable to cope with long filenames on both Java 1.5 u06, and 1.6 b65.

I think that this is related to 6329168 "new ZipFile(name) fails on Windows when name contains non-Latin1".

E:\long_filenames_in_zip>java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode)

E:\long_filenames_in_zip>java TestLongJarName
Test failed - problem reading the Jar file back in.
java.util.zip.ZipException: Filename too long
        at java.util.zip.ZipFile.open(Native Method)
        at java.util.zip.ZipFile.<init>(ZipFile.java:203)
        at java.util.zip.ZipFile.<init>(ZipFile.java:234)
        at ReadLongNameZipFile.main(ReadLongNameZipFile.java:43)

You can verify that the long filename is causing the problem by reducing the value of 
minRequiredLength in the attached testcase.  The test passes with a smaller number like 30.
		
//-- Testcase: -------
import java.io.*;
import java.util.jar.*;
import java.util.zip.*;

public class ReadLongNameZipFile {
	public static void main (String args[]) {
		String longDirName = "abcdefghijklmnopqrstuvwx"; // 24 chars.
		String jarFileName = "areallylargejarfilename.jar";    // 27 chars.
		File file = null;
		File myJarFile = null;
		int currentFileLength = 0;
		int minRequiredLength = 300; // try something big enough to definitely fail.
	
		String sb = "."+File.separator;
		try {
		// create a directory structure long enough that the filename will put us over the minRequiredLength
			do {
				sb=sb+longDirName+File.separator;
				file = new File(sb);
				file.mkdir();
				currentFileLength = file.getCanonicalPath().length();
				file.deleteOnExit();			
			} while (currentFileLength < (minRequiredLength - jarFileName.length()));
		// create a new Jar file - this passes OK
			sb=sb+jarFileName;
			FileOutputStream destJar = new FileOutputStream(sb.toString());
			JarOutputStream out = new JarOutputStream(new BufferedOutputStream(destJar));
			JarEntry jarEntry = new JarEntry("testFile.txt");
			out.putNextEntry(jarEntry);
			out.write(1);
			out.close();
			myJarFile = new File(sb.toString());
			currentFileLength = myJarFile.getCanonicalPath().length();
			if(!myJarFile.exists()) {
				System.err.println("Jar file does not exist.");
			}
		} catch (IOException e) {
			System.err.println("Problem creating the Jar file.");
			e.printStackTrace();
		}
		try {
		// create a new ZipFile object (also fails with JarFile - a subclass of ZipFile) using the myJarFile File object...
			ZipFile readJarFile = new ZipFile(myJarFile);
			readJarFile.close();
			System.out.println("Test passed - opened Jar file for reading with a name "+currentFileLength+" characters long!");
		} catch (IOException e) {
			System.err.println("Test failed - problem reading the Jar file back in.");
			e.printStackTrace();
		} finally {
		// clean up a bit
			if(myJarFile!=null) {
				if(myJarFile.exists()) {
					if(!myJarFile.delete()) {
						System.err.println("Jar file cannot be deleted.");					
					}	
				}
				if(file.exists()) {
					if(!file.delete()) {
						System.err.println("Directory structure cannot be deleted.");
					}
				}
			}
		}
	}
}
//-----------------------

Comments
EVALUATION The key portability API is fileOpen, which does all the heavy lifting. Taking a cue from FileInputStream, JNIEXPORT void JNICALL Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) { fileOpen(env, this, path, fis_fd, O_RDONLY); } I think we can fix this problem without too much effort, by having a ZipFile.open native method that initialized a file descriptor. Then that filedescriptor can be used in zip_util.c as it is now. We really really need to avoid having two copies of zip_util.c to maintain.
01-02-2006

EVALUATION I believe the "Filename too long" error is actually a windows error string. We could support windows filenames up to 32k in length, and we do in other parts of the JDK (there was a whole "long windows filename feature" in mustang) but it's not clear whether that other work can be reused here or whether the effort is worth it.
19-01-2006