Author: sebb
Date: Thu May 13 10:25:15 2010
New Revision: 943863
URL: http://svn.apache.org/viewvc?rev=943863&view=rev
Log:
COMPRESS-112 ArArchiveInputStream does not handle GNU extended filename records
(//)
Added:
commons/proper/compress/trunk/src/test/resources/longpath/minotaur.ar
(with props)
Modified:
commons/proper/compress/trunk/RELEASE-NOTES.txt
commons/proper/compress/trunk/src/changes/changes.xml
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/LongPathTest.java
Modified: commons/proper/compress/trunk/RELEASE-NOTES.txt
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/RELEASE-NOTES.txt?rev=943863&r1=943862&r2=943863&view=diff
==============================================================================
--- commons/proper/compress/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/compress/trunk/RELEASE-NOTES.txt Thu May 13 10:25:15 2010
@@ -76,11 +76,12 @@ o The ar and cpio streams now properly r
o COMPRESS-81: TarOutputStream can leave garbage at the end of the archive
Changes:
+o COMPRESS-112: ArArchiveInputStream does not handle GNU extended filename
records (//)
o COMPRESS-109: Tar implementation does not support Pax headers
Added support for reading pax headers.
Note: does not support global pax headers
o COMPRESS-105: Document that the name of an ZipArchiveEntry determines
whether
- an entry is considered a directory or not.
+ an entry is considered a directory or not.
If you don't use the constructor with the File argument the entry's
name must end in a "/" in order for the entry to be known as a
directory.
o COMPRESS-79: Move DOS/Java time conversions into Zip utility class.
Modified: commons/proper/compress/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/changes/changes.xml?rev=943863&r1=943862&r2=943863&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/changes/changes.xml (original)
+++ commons/proper/compress/trunk/src/changes/changes.xml Thu May 13 10:25:15
2010
@@ -45,6 +45,9 @@ The <action> type attribute can be add,u
</properties>
<body>
<release version="1.1" date="as in SVN" description="Release 1.1">
+ <action issue="COMPRESS-112" type="update" date="2010-05-13">
+ ArArchiveInputStream does not handle GNU extended filename records (//)
+ </action>
<action issue="COMPRESS-109" type="update" date="2010-05-10">
Tar implementation does not support Pax headers
Added support for reading pax headers.
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java?rev=943863&r1=943862&r2=943863&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
(original)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
Thu May 13 10:25:15 2010
@@ -43,6 +43,9 @@ public class ArArchiveInputStream extend
*/
private ArArchiveEntry currentEntry = null;
+ // Storage area for extra long names (GNU ar)
+ private byte[] namebuffer = null;
+
/*
* The offset where the current entry started. -1 if no entry has been
* called
@@ -125,22 +128,38 @@ public class ArArchiveInputStream extend
final byte[] realized = new byte[expected.length];
final int read = read(realized);
if (read != expected.length) {
- throw new IOException("failed to read entry header. Occured at
byte: " + getBytesRead());
+ throw new IOException("failed to read entry trailer. Occured
at byte: " + getBytesRead());
}
for (int i = 0; i < expected.length; i++) {
if (expected[i] != realized[i]) {
- throw new IOException("invalid entry header. not read the
content? Occured at byte: " + getBytesRead());
+ throw new IOException("invalid entry trailer. not read the
content? Occured at byte: " + getBytesRead());
}
}
}
entryOffset = offset;
- // SVR4/GNU adds a trailing "/" to names
+// GNU ar stores multiple extended filenames in the data section of a
file with the name "//", this record is referred to by future headers. A header
references an extended filename by storing a "/" followed by a decimal offset
to the start of the filename in the extended filename data section. The format
of this "//" file itself is simply a list of the long filenames, each separated
by one or more LF characters. Note that the decimal offsets are number of
characters, not line or string number within the "//" file.
+//
+// GNU ar uses a '/' to mark the end of the filename; this allows for
the use of spaces without the use of an extended filename.
+
// entry name is stored as ASCII string
String temp = ArchiveUtils.toAsciiString(name).trim();
- if (temp.endsWith("/")) {
+
+ if (temp.equals("//")){ // GNU extended filenames entry
+ int bufflen = asInt(length); // Assume length will fit in an int
+ namebuffer = new byte[bufflen];
+ int read = read(namebuffer, 0, bufflen);
+ if (read != bufflen){
+ throw new IOException("Failed to read complete // record:
expected="+bufflen+" read="+read);
+ }
+ currentEntry = new ArArchiveEntry(temp, bufflen);
+ return getNextArEntry();
+ } else if (temp.endsWith("/")) { // GNU terminator
temp = temp.substring(0, temp.length() - 1);
+ } else if (temp.matches("^/\\d+")) {// GNU long filename ref.
+ int offset = Integer.parseInt(temp.substring(1));// get the offset
+ temp = getExtendedName(offset); // convert to the long name
}
currentEntry = new ArArchiveEntry(temp, asLong(length), asInt(userid),
asInt(groupid), asInt(filemode, 8),
@@ -148,6 +167,27 @@ public class ArArchiveInputStream extend
return currentEntry;
}
+ /**
+ * Get an extended name from the GNU extended name buffer.
+ *
+ * @param offset pointer to entry within the buffer
+ * @return the extended file name; without trailing "/" if present.
+ * @throws IOException if name not found or buffer not set up
+ */
+ private String getExtendedName(int offset) throws IOException{
+ if (namebuffer == null) {
+ throw new IOException("Cannot process GNU long filename as no //
record was found");
+ }
+ for(int i=offset; i < namebuffer.length; i++){
+ if (namebuffer[i]=='\012'){
+ if (namebuffer[i-1]=='/') {
+ i--; // drop trailing /
+ }
+ return ArchiveUtils.toAsciiString(namebuffer, offset,
i-offset);
+ }
+ }
+ throw new IOException("Failed to read entry: "+offset);
+ }
private long asLong(byte[] input) {
return Long.parseLong(new String(input).trim());
}
Modified:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/LongPathTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/LongPathTest.java?rev=943863&r1=943862&r2=943863&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/LongPathTest.java
(original)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/LongPathTest.java
Thu May 13 10:25:15 2010
@@ -31,6 +31,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.compress.AbstractTestCase;
+import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
@@ -112,6 +113,21 @@ public class LongPathTest extends Abstra
expected.set(i, ent.substring(0, ent.length()-1));
}
}
+ } else if (name.endsWith(".ar")){
+ assertTrue(ais instanceof ArArchiveInputStream);
+ // CPIO does not store directories or directory names
+ expected.clear();
+ for(int i=0; i < fileList.size(); i++){
+ String ent = (String) fileList.get(i);
+ if (!ent.endsWith("/")){// not a directory
+ final int lastSlash = ent.lastIndexOf('/');
+ if (lastSlash >= 0) { // extract path name
+ expected.add(ent.substring(lastSlash+1,
ent.length()));
+ } else {
+ expected.add(ent);
+ }
+ }
+ }
} else {
fail("Unexpected file type: "+name);
}
Added: commons/proper/compress/trunk/src/test/resources/longpath/minotaur.ar
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/resources/longpath/minotaur.ar?rev=943863&view=auto
==============================================================================
Binary file - no diff available.
Propchange:
commons/proper/compress/trunk/src/test/resources/longpath/minotaur.ar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream