Author: bodewig
Date: Mon Aug 8 09:49:08 2011
New Revision: 1154895
URL: http://svn.apache.org/viewvc?rev=1154895&view=rev
Log:
small refactoring of long filename support in AR input stream
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
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=1154895&r1=1154894&r2=1154895&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
Mon Aug 8 09:49:08 2011
@@ -138,26 +138,18 @@ public class ArArchiveInputStream extend
entryOffset = offset;
-// 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();
long len = asLong(length);
- 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);
+ if (isGNUStringTable(temp)) { // GNU extended filenames entry
+ currentEntry = readGNUStringTable(length);
return getNextArEntry();
} else if (temp.endsWith("/")) { // GNU terminator
temp = temp.substring(0, temp.length() - 1);
- } else if (temp.matches("^/\\d+")) {// GNU long filename ref.
+ } else if (isGNULongName(temp)) {
int offset = Integer.parseInt(temp.substring(1));// get the offset
temp = getExtendedName(offset); // convert to the long name
} else if (isBSDLongName(temp)) {
@@ -315,6 +307,8 @@ public class ArArchiveInputStream extend
private static final String BSD_LONGNAME_PREFIX = "#1/";
private static final int BSD_LONGNAME_PREFIX_LEN =
BSD_LONGNAME_PREFIX.length();
+ private static final String BSD_LONGNAME_PATTERN =
+ "^" + BSD_LONGNAME_PREFIX + "\\d+";
/**
* Does the name look like it is a long name (or a name containing
@@ -339,8 +333,7 @@ public class ArArchiveInputStream extend
* @since Apache Commons Compress 1.3
*/
private static boolean isBSDLongName(String name) {
- return name.startsWith(BSD_LONGNAME_PREFIX)
- && name.length() > BSD_LONGNAME_PREFIX_LEN;
+ return name != null && name.matches(BSD_LONGNAME_PATTERN);
}
/**
@@ -348,6 +341,8 @@ public class ArArchiveInputStream extend
* first bytes to be read are the real file name.
*
* @see #isBSDLongName
+ *
+ * @since Apache Commons Compress 1.3
*/
private String getBSDLongName(String bsdLongName) throws IOException {
int nameLen =
@@ -366,4 +361,55 @@ public class ArArchiveInputStream extend
}
return ArchiveUtils.toAsciiString(name);
}
+
+ private static final String GNU_STRING_TABLE_NAME = "//";
+
+ /**
+ * Is this the name of the "Archive String Table" as used by
+ * SVR4/GNU to store long file names?
+ *
+ * <p>GNU ar stores multiple extended filenames in the data section
+ * of a file with the name "//", this record is referred to by
+ * future headers.</p>
+ *
+ * <p>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.</p>
+ *
+ * <p>The format of the "//" 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.</p>
+ */
+ private static boolean isGNUStringTable(String name) {
+ return GNU_STRING_TABLE_NAME.equals(name);
+ }
+
+ /**
+ * Reads the GNU archive String Table.
+ *
+ * @see #isGNUStringTable
+ */
+ private ArArchiveEntry readGNUStringTable(byte[] length) throws
IOException {
+ 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);
+ }
+ return new ArArchiveEntry(GNU_STRING_TABLE_NAME, bufflen);
+ }
+
+ private static final String GNU_LONGNAME_PATTERN = "^/\\d+";
+
+ /**
+ * Does the name look like it is a long name (or a name containing
+ * spaces) as encoded by SVR4/GNU ar?
+ *
+ * @see #isGNUStringTable
+ */
+ private boolean isGNULongName(String name) {
+ return name != null && name.matches(GNU_LONGNAME_PATTERN);
+ }
}