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 8E44382DC
for ;
Mon, 8 Aug 2011 08:55:29 +0000 (UTC)
Received: (qmail 51204 invoked by uid 500); 8 Aug 2011 08:55:25 -0000
Delivered-To: apmail-commons-commits-archive@commons.apache.org
Received: (qmail 50743 invoked by uid 500); 8 Aug 2011 08:55:02 -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 50682 invoked by uid 99); 8 Aug 2011 08:54:58 -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 08:54:58 +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 08:54:54 +0000
Received: from eris.apache.org (localhost [127.0.0.1])
by eris.apache.org (Postfix) with ESMTP id 3CA2423889D5
for ; Mon, 8 Aug 2011 08:54:34 +0000 (UTC)
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: svn commit: r1154877 - in /commons/proper/compress/trunk/src:
main/java/org/apache/commons/compress/archivers/ar/ site/xdoc/
test/java/org/apache/commons/compress/archivers/ar/ test/resources/
Date: Mon, 08 Aug 2011 08:54:34 -0000
To: commits@commons.apache.org
From: bodewig@apache.org
X-Mailer: svnmailer-1.0.8
Message-Id: <20110808085434.3CA2423889D5@eris.apache.org>
X-Virus-Checked: Checked by ClamAV on apache.org
Author: bodewig
Date: Mon Aug 8 08:54:33 2011
New Revision: 1154877
URL: http://svn.apache.org/viewvc?rev=1154877&view=rev
Log:
support reading of long file names in AR archives that use the BSD variant. COMPRESS-144
Added:
commons/proper/compress/trunk/src/test/resources/longfile_bsd.ar
- copied, changed from r1154851, commons/proper/compress/trunk/src/test/resources/longfile_gnu.ar
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStream.java
commons/proper/compress/trunk/src/site/xdoc/examples.xml
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.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=1154877&r1=1154876&r2=1154877&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 08:54:33 2011
@@ -18,6 +18,7 @@
*/
package org.apache.commons.compress.archivers.ar;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -143,6 +144,7 @@ public class ArArchiveInputStream extend
// 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
@@ -158,8 +160,17 @@ public class ArArchiveInputStream extend
} 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
+ } else if (isBSDLongName(temp)) {
+ temp = getBSDLongName(temp);
+ // entry length contained the length of the file name in
+ // addition to the real length of the entry.
+ // assume file name was ASCII, there is no "standard" otherwise
+ int nameLen = temp.length();
+ len -= nameLen;
+ entryOffset += nameLen;
}
- currentEntry = new ArArchiveEntry(temp, asLong(length), asInt(userid, true),
+
+ currentEntry = new ArArchiveEntry(temp, len, asInt(userid, true),
asInt(groupid, true), asInt(filemode, 8),
asLong(lastmodified));
return currentEntry;
@@ -301,4 +312,58 @@ public class ArArchiveInputStream extend
return true;
}
+ private static final String BSD_LONGNAME_PREFIX = "#1/";
+ private static final int BSD_LONGNAME_PREFIX_LEN =
+ BSD_LONGNAME_PREFIX.length();
+
+ /**
+ * Does the name look like it is a long name (or a name containing
+ * spaces) as encoded by BSD ar?
+ *
+ * From the FreeBSD ar(5) man page:
+ *
+ * BSD In the BSD variant, names that are shorter than 16
+ * characters and without embedded spaces are stored
+ * directly in this field. If a name has an embedded
+ * space, or if it is longer than 16 characters, then
+ * the string "#1/" followed by the decimal represen-
+ * tation of the length of the file name is placed in
+ * this field. The actual file name is stored immedi-
+ * ately after the archive header. The content of the
+ * archive member follows the file name. The ar_size
+ * field of the header (see below) will then hold the
+ * sum of the size of the file name and the size of
+ * the member.
+ *
+ *
+ * @since Apache Commons Compress 1.3
+ */
+ private static boolean isBSDLongName(String name) {
+ return name.startsWith(BSD_LONGNAME_PREFIX)
+ && name.length() > BSD_LONGNAME_PREFIX_LEN;
+ }
+
+ /**
+ * Reads the real name from the current stream assuming the very
+ * first bytes to be read are the real file name.
+ *
+ * @see #isBSDLongName
+ */
+ private String getBSDLongName(String bsdLongName) throws IOException {
+ int nameLen =
+ Integer.parseInt(bsdLongName.substring(BSD_LONGNAME_PREFIX_LEN));
+ byte[] name = new byte[nameLen];
+ int read = 0, readNow = 0;
+ while ((readNow = input.read(name, read, nameLen - read)) >= 0) {
+ read += readNow;
+ count(readNow);
+ if (read == nameLen) {
+ break;
+ }
+ }
+ if (read != nameLen) {
+ throw new EOFException();
+ }
+ return ArchiveUtils.toAsciiString(name);
+ }
}
Modified: commons/proper/compress/trunk/src/site/xdoc/examples.xml
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/site/xdoc/examples.xml?rev=1154877&r1=1154876&r2=1154877&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/site/xdoc/examples.xml (original)
+++ commons/proper/compress/trunk/src/site/xdoc/examples.xml Mon Aug 8 08:54:33 2011
@@ -98,10 +98,11 @@ LOOP UNTIL entry.getSize() HAS BEEN READ
Traditionally the AR format doesn't allow file names longer
than 16 characters. There are two variants that circumvent
this limitation in different ways, the GNU/SRV4 and the BSD
- variant. Currently Commons Compress can only read archives
- using the GNU/SRV4 variant, it doesn't support writing
- archives with file names longer than 16 characters at
- all.
+ variant. Commons Compress 1.0 to 1.2 can only read archives
+ using the GNU/SRV4 variant, support for the BSD variant has
+ been added in Commons Compress 1.3. It doesn't support
+ writing archives with file names longer than 16 characters
+ at all.
Modified: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java?rev=1154877&r1=1154876&r2=1154877&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java (original)
+++ commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveInputStreamTest.java Mon Aug 8 08:54:33 2011
@@ -18,15 +18,39 @@
package org.apache.commons.compress.archivers.ar;
-import java.util.ArrayList;
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
import org.apache.commons.compress.AbstractTestCase;
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.utils.ArchiveUtils;
public class ArArchiveInputStreamTest extends AbstractTestCase {
public void testReadLongNamesGNU() throws Exception {
- ArrayList l = new ArrayList();
- l.add("this_is_a_long_file_name.txt");
- checkArchiveContent(getFile("longfile_gnu.ar"), l);
+ checkLongNameEntry("longfile_gnu.ar");
}
+ public void testReadLongNamesBSD() throws Exception {
+ checkLongNameEntry("longfile_bsd.ar");
+ }
+
+ private void checkLongNameEntry(String archive) throws Exception {
+ FileInputStream fis = new FileInputStream(getFile(archive));
+ ArArchiveInputStream s = null;
+ try {
+ s = new ArArchiveInputStream(new BufferedInputStream(fis));
+ ArchiveEntry e = s.getNextEntry();
+ assertEquals("this_is_a_long_file_name.txt", e.getName());
+ assertEquals(14, e.getSize());
+ byte[] hello = new byte[14];
+ s.read(hello);
+ assertEquals("Hello, world!\n", ArchiveUtils.toAsciiString(hello));
+ assertNull(s.getNextEntry());
+ } finally {
+ if (s != null) {
+ s.close();
+ }
+ fis.close();
+ }
+ }
}
Copied: commons/proper/compress/trunk/src/test/resources/longfile_bsd.ar (from r1154851, commons/proper/compress/trunk/src/test/resources/longfile_gnu.ar)
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/resources/longfile_bsd.ar?p2=commons/proper/compress/trunk/src/test/resources/longfile_bsd.ar&p1=commons/proper/compress/trunk/src/test/resources/longfile_gnu.ar&r1=1154851&r2=1154877&rev=1154877&view=diff
==============================================================================
Binary files - no diff available.