Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 33C8A8621 for ; Mon, 8 Aug 2011 09:50:04 +0000 (UTC) Received: (qmail 30758 invoked by uid 500); 8 Aug 2011 09:49:55 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 30394 invoked by uid 500); 8 Aug 2011 09:49:35 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 30386 invoked by uid 99); 8 Aug 2011 09:49:32 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 08 Aug 2011 09:49:32 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 08 Aug 2011 09:49:29 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id E539423889B3 for ; Mon, 8 Aug 2011 09:49:08 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1154895 - /commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java Date: Mon, 08 Aug 2011 09:49:08 -0000 To: commits@commons.apache.org From: bodewig@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110808094908.E539423889B3@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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? + * + *

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 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.

+ */ + 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); + } }