Author: bodewig Date: Mon Aug 8 11:39:41 2011 New Revision: 1154928 URL: http://svn.apache.org/viewvc?rev=1154928&view=rev Log: support writing of BSD dialect AR archives with long file names. COMPRESS-144
Added: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java (with props) Modified: 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/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java commons/proper/compress/trunk/src/site/xdoc/examples.xml Modified: commons/proper/compress/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/changes/changes.xml?rev=1154928&r1=1154927&r2=1154928&view=diff ============================================================================== --- commons/proper/compress/trunk/src/changes/changes.xml (original) +++ commons/proper/compress/trunk/src/changes/changes.xml Mon Aug 8 11:39:41 2011 @@ -46,6 +46,10 @@ The <action> type attribute can be add,u <body> <release version="1.3" date="unreleased" description="Release 1.3 - API compatible to 1.2 but requires Java5 at runtime"> + <action issue="COMPRESS-144" type="update" date="2011-08-08"> + The AR package now supports the BSD dialect of storing file + names longer than 16 chars (both reading and writing). + </action> <action type="fix" date="2011-08-08"> BZip2CompressorInputStream's getBytesRead method always returned 0. 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=1154928&r1=1154927&r2=1154928&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 11:39:41 2011 @@ -304,7 +304,7 @@ public class ArArchiveInputStream extend return true; } - private static final String BSD_LONGNAME_PREFIX = "#1/"; + 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 = Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java?rev=1154928&r1=1154927&r2=1154928&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStream.java Mon Aug 8 11:39:41 2011 @@ -32,13 +32,19 @@ import org.apache.commons.compress.utils * @NotThreadSafe */ public class ArArchiveOutputStream extends ArchiveOutputStream { + /** Fail if a long file name is required in the archive. */ + public static final int LONGFILE_ERROR = 0; + + /** BSD ar extensions are used to store long file names in the archive. */ + public static final int LONGFILE_BSD = 1; private final OutputStream out; private long archiveOffset = 0; private long entryOffset = 0; private ArArchiveEntry prevEntry; private boolean haveUnclosedEntry = false; - + private int longFileMode = LONGFILE_ERROR; + /** indicates if this archive is finished */ private boolean finished = false; @@ -46,6 +52,18 @@ public class ArArchiveOutputStream exten this.out = pOut; } + /** + * Set the long file mode. + * This can be LONGFILE_ERROR(0) or LONGFILE_BSD(1). + * This specifies the treatment of long file names (names >= 16). + * Default is LONGFILE_ERROR. + * @param longFileMode the mode to use + * @since Apache Commons Compress 1.3 + */ + public void setLongFileMode(int longFileMode) { + this.longFileMode = longFileMode; + } + private long writeArchiveHeader() throws IOException { byte [] header = ArchiveUtils.toAsciiBytes(ArArchiveEntry.HEADER); out.write(header); @@ -74,7 +92,7 @@ public class ArArchiveOutputStream exten if(finished) { throw new IOException("Stream has already been finished"); } - + ArArchiveEntry pArEntry = (ArArchiveEntry)pEntry; if (prevEntry == null) { archiveOffset += writeArchiveHeader(); @@ -117,12 +135,20 @@ public class ArArchiveOutputStream exten private long writeEntryHeader( final ArArchiveEntry pEntry ) throws IOException { long offset = 0; + boolean mustAppendName = false; final String n = pEntry.getName(); - if (n.length() > 16) { + if (LONGFILE_ERROR == longFileMode && n.length() > 16) { throw new IOException("filename too long, > 16 chars: "+n); } - offset += write(n); + if (LONGFILE_BSD == longFileMode && + (n.length() > 16 || n.indexOf(" ") > -1)) { + mustAppendName = true; + offset += write(ArArchiveInputStream.BSD_LONGNAME_PREFIX + + String.valueOf(n.length())); + } else { + offset += write(n); + } offset = fill(offset, 16, ' '); final String m = "" + (pEntry.getLastModified()); @@ -153,7 +179,9 @@ public class ArArchiveOutputStream exten offset += write(fm); offset = fill(offset, 48, ' '); - final String s = "" + pEntry.getLength(); + final String s = + String.valueOf(pEntry.getLength() + + (mustAppendName ? n.length() : 0)); if (s.length() > 10) { throw new IOException("size too long"); } @@ -163,6 +191,10 @@ public class ArArchiveOutputStream exten offset += write(ArArchiveEntry.TRAILER); + if (mustAppendName) { + offset += write(n); + } + return offset; } 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=1154928&r1=1154927&r2=1154928&view=diff ============================================================================== --- commons/proper/compress/trunk/src/site/xdoc/examples.xml (original) +++ commons/proper/compress/trunk/src/site/xdoc/examples.xml Mon Aug 8 11:39:41 2011 @@ -100,9 +100,10 @@ LOOP UNTIL entry.getSize() HAS BEEN READ this limitation in different ways, the GNU/SRV4 and the BSD 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.</p> + been added in Commons Compress 1.3. Commons Compress 1.3 + also optionally supports writing archives with file names + longer than 16 characters using the BSD dialect, writing + the SVR4/GNU dialect is not supported.</p> </subsection> Added: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java?rev=1154928&view=auto ============================================================================== --- commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java (added) +++ commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java Mon Aug 8 11:39:41 2011 @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.commons.compress.archivers.ar; + +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.compress.AbstractTestCase; + +public class ArArchiveOutputStreamTest extends AbstractTestCase { + + public void testLongFileNamesCauseExceptionByDefault() { + try { + ArArchiveOutputStream os = + new ArArchiveOutputStream(new ByteArrayOutputStream()); + ArArchiveEntry ae = new ArArchiveEntry("this_is_a_long_name.txt", + 0); + os.putArchiveEntry(ae); + fail("Expected an exception"); + } catch (IOException ex) { + assertTrue(ex.getMessage().startsWith("filename too long")); + } + } + + public void testLongFileNamesWorkUsingBSDDialect() throws Exception { + FileOutputStream fos = null; + ArArchiveOutputStream os = null; + File[] df = createTempDirAndFile(); + try { + fos = new FileOutputStream(df[1]); + os = new ArArchiveOutputStream(fos); + os.setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD); + ArArchiveEntry ae = new ArArchiveEntry("this_is_a_long_name.txt", + 14); + os.putArchiveEntry(ae); + os.write(new byte[] { + 'H', 'e', 'l', 'l', 'o', ',', ' ', + 'w', 'o', 'r', 'l', 'd', '!', '\n' + }); + os.closeArchiveEntry(); + os.close(); + os = null; + fos = null; + + List<String> expected = new ArrayList<String>(); + expected.add("this_is_a_long_name.txt"); + checkArchiveContent(df[1], expected); + } finally { + if (os != null) { + os.close(); + } + if (fos != null) { + fos.close(); + } + rmdir(df[0]); + } + } +} \ No newline at end of file Propchange: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ar/ArArchiveOutputStreamTest.java ------------------------------------------------------------------------------ svn:eol-style = native