Name: rlT66838 Date: 07/25/97
The jar utility sometimes fails exploding an archive. The failing case is
when a directory is named in the archive, and the parent directory of that
directory doesn't already exist. This turns out arguably to be a bug in the
java.io.File.getParent() method.
Consider the following sample program:
package aaa.bbb;
class Demo {
public static void main(String[] args) {
System.out.println("Hello");
}
}
Compile that program with the command: javac -d . Demo.java
Create an archive with the command: jar cf demo.jar aaa/bbb
To reproduce the problem, erase the aaa directory and all files and directories
underneath it, and issue the command: jar xf demo.jar
The given error messages are:
java.io.IOException: aaa/bbb/: could not create directory
at sun.tools.jar.Main.extractFile(Main.java:395)
at sun.tools.jar.Main.extract(Main.java:375)
at sun.tools.jar.Main.run(Main.java:106)
at sun.tools.jar.Main.main(Main.java:524)
The form of the jar command used to create the archive causes an entry for the
directory "aaa/bbb/" to be placed in the archive (notice the trailing path
separator), but not an entry for "aaa/". When exploding the archive, the jar
utility creates a java.io.File object out of the string "aaa/bbb/". It then
calls File.mkdirs() to create the directory and any necessary parent
directories. The File.mkdirs() method tries creating (via a call to mkdir())
"aaa/bbb/" immediately. When that fails, it calls File.getParent(), which
returns "aaa/bbb". This is the crux of the problem. This path is the same as
the original path, except for the trailing path separator. It is NOT the
parent directory of the original path. Consequently, after finally creating
"aaa/bbb", File.mkdirs() tries to create "aaa/bbb/". This fails, because now
the directory exists, causing the entire File.mkdirs() call to return false
(even though the directory was, in fact, created).
It seems to me there are several ways to fix this: You could either have the
jar command trim off the trailing path separator before calling File.mkdirs(),
or change the File class to realize that some trailing path separators are
irrelevant (at least File.getParent() would need to be changed in this way).
As an aside, File.getParent() also fails to consider that on UNIX systems, in
general, multiple slashes between directory names should be treated as a
single slash. This is mandated by this POSIX.1 standard.
Creating the original archive with: jar cf demo.jar aaa
would have avoided the problem, because the aaa directory will now have its
own entry in the archive, so that by the time aaa/bbb is processed, aaa will
already exist. This avoids the File.mkdirs() limitation. But I would argue
that an archive shouldn't necessarily need to contain entries for every parent
of every directory named within. Or if it should, that the jar utility ought
to create them itself.
This problem is important to my programming organization because we have a
utility that merges two jar files that operates by exploding them both. The
explode operations are failing, which causes the merge operation to fail,
which causes the whole build operation to fail.
company - IBM , email - ###@###.###
======================================================================
Create a jar with files down a subdirectory tree:
JAR -cf test.jar COM\lotus
when you unJAR them:
JAR -xf test.jar
in a directory in which COM\lotus does not exist,
you get:
D:\TEMP2>e:\jdk1.1.4\bin\jar -xf test.jar
java.io.IOException: COM\lotus\: could not create directory
at sun.tools.jar.Main.extractFile(Main.java:395)
at sun.tools.jar.Main.extract(Main.java:375)
at sun.tools.jar.Main.run(Main.java:106)
at sun.tools.jar.Main.main(Main.java:524)
even though the directories are, in fact, created.
The problem appears to be that JAR tries to make
COM\lotus instead of COM, then COM\lotus. You
can see this with:
JAR -tf test.jar
The first directory listed before the files in the
JAR will be
COM\lotus
If you created the JAR with
JAR -cf test.jar COM
then you will see
COM
COM\lotus
in a list of the JAR contents. I tested this
again with 1.1.5 and get the same failure as I did
on 1.1.4.
- duplicates
-
JDK-4217036 Cannot unjar rmiregistry.jar in RMI Registry Service Provider for JNDI
-
- Closed
-
- relates to
-
JDK-4097578 Enhance jar tool to preserve file permissions/modes
-
- Closed
-