You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2013/06/03 11:20:31 UTC

svn commit: r1488935 - in /commons/proper/compress/trunk/src: changes/ main/java/org/apache/commons/compress/archivers/tar/ test/java/org/apache/commons/compress/archivers/ test/resources/longsymlink/

Author: bodewig
Date: Mon Jun  3 09:20:30 2013
New Revision: 1488935

URL: http://svn.apache.org/r1488935
Log:
COMPRESS-229 properly parse GNU_LONGLNK entries, patch by Christoph Gysin

Added:
    commons/proper/compress/trunk/src/test/resources/longsymlink/
    commons/proper/compress/trunk/src/test/resources/longsymlink/files.txt   (with props)
    commons/proper/compress/trunk/src/test/resources/longsymlink/gnu.tar   (with props)
Modified:
    commons/proper/compress/trunk/src/changes/changes.xml
    commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
    commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java
    commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java
    commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/LongPathTest.java

Modified: commons/proper/compress/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/changes/changes.xml?rev=1488935&r1=1488934&r2=1488935&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/changes/changes.xml (original)
+++ commons/proper/compress/trunk/src/changes/changes.xml Mon Jun  3 09:20:30 2013
@@ -54,6 +54,12 @@ The <action> type attribute can be add,u
         to be able to read archives created by DotNetZip and maybe
         other archivers as well.
       </action>
+      <action type="fix" date="2013-06-03" issue="COMPRESS-229"
+              due-to="Christoph Gysin">
+        TAR will now properly read the names of symbolic links with
+        long names that use the GNU variant to specify the long file
+        name.
+      </action>
     </release>
     <release version="1.5" date="2013-03-14"
              description="Release 1.5">

Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java?rev=1488935&r1=1488934&r2=1488935&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java (original)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java Mon Jun  3 09:20:30 2013
@@ -676,6 +676,16 @@ public class TarArchiveEntry implements 
     }
 
     /**
+     * Indicate if this entry is a GNU long linkname block
+     *
+     * @return true if this is a long name extension provided by GNU tar
+     */
+    public boolean isGNULongLinkEntry() {
+        return linkFlag == LF_GNUTYPE_LONGLINK
+            && name.equals(GNU_LONGLINK);
+    }
+
+    /**
      * Indicate if this entry is a GNU long name block
      *
      * @return true if this is a long name extension provided by GNU tar

Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java?rev=1488935&r1=1488934&r2=1488935&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java (original)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java Mon Jun  3 09:20:30 2013
@@ -248,31 +248,13 @@ public class TarArchiveInputStream exten
         entryOffset = 0;
         entrySize = currEntry.getSize();
 
-        if (currEntry.isGNULongNameEntry()) {
-            // read in the name
-            ByteArrayOutputStream longName = new ByteArrayOutputStream();
-            int length = 0;
-            while ((length = read(SMALL_BUF)) >= 0) {
-                longName.write(SMALL_BUF, 0, length);
-            }
-            getNextEntry();
-            if (currEntry == null) {
-                // Bugzilla: 40334
-                // Malformed tar file - long entry name not followed by entry
-                return null;
-            }
-            byte[] longNameData = longName.toByteArray();
-            // remove trailing null terminator(s)
-            length = longNameData.length;
-            while (length > 0 && longNameData[length - 1] == 0) {
-                --length;
-            }
-            if (length != longNameData.length) {
-                byte[] l = new byte[length];
-                System.arraycopy(longNameData, 0, l, 0, length);
-                longNameData = l;
-            }
+        if (currEntry.isGNULongLinkEntry()) {
+            byte[] longLinkData = getLongNameData();
+            currEntry.setLinkName(encoding.decode(longLinkData));
+        }
 
+        if (currEntry.isGNULongNameEntry()) {
+            byte[] longNameData = getLongNameData();
             currEntry.setName(encoding.decode(longNameData));
         }
 
@@ -293,6 +275,39 @@ public class TarArchiveInputStream exten
     }
 
     /**
+     * Get the next entry in this tar archive as longname data.
+     *
+     * @return The next entry in the archive as longname data, or null.
+     * @throws IOException on error
+     */
+    protected byte[] getLongNameData() throws IOException {
+        // read in the name
+        ByteArrayOutputStream longName = new ByteArrayOutputStream();
+        int length = 0;
+        while ((length = read(SMALL_BUF)) >= 0) {
+            longName.write(SMALL_BUF, 0, length);
+        }
+        getNextEntry();
+        if (currEntry == null) {
+            // Bugzilla: 40334
+            // Malformed tar file - long entry name not followed by entry
+            return null;
+        }
+        byte[] longNameData = longName.toByteArray();
+        // remove trailing null terminator(s)
+        length = longNameData.length;
+        while (length > 0 && longNameData[length - 1] == 0) {
+            --length;
+        }
+        if (length != longNameData.length) {
+            byte[] l = new byte[length];
+            System.arraycopy(longNameData, 0, l, 0, length);
+            longNameData = l;
+        }
+        return longNameData;
+    }
+
+    /**
      * Get the next record in this tar archive. This will skip
      * over any remaining data in the current entry, if there
      * is one, and place the input stream at the header of the

Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java?rev=1488935&r1=1488934&r2=1488935&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java (original)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarConstants.java Mon Jun  3 09:20:30 2013
@@ -233,6 +233,11 @@ public interface TarConstants {
     byte   LF_CONTIG = (byte) '7';
 
     /**
+     * Identifies the *next* file on the tape as having a long linkname.
+     */
+    byte LF_GNUTYPE_LONGLINK = (byte) 'K';
+
+    /**
      * Identifies the *next* file on the tape as having a long name.
      */
     byte LF_GNUTYPE_LONGNAME = (byte) 'L';

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=1488935&r1=1488934&r2=1488935&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 Mon Jun  3 09:20:30 2013
@@ -25,6 +25,8 @@ import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
@@ -33,6 +35,7 @@ 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.TarArchiveEntry;
 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
 
@@ -44,26 +47,37 @@ import org.apache.commons.compress.archi
  */
 public class LongPathTest extends AbstractTestCase {
 
+    private String name;
     private File file;
 
-    private static final ArrayList<String> fileList = new ArrayList<String>();
+    private static final Map<String, ArrayList<String>> fileLists = new HashMap<String, ArrayList<String>>();
 
     public LongPathTest(String name) {
         super(name);
     }
 
-    private LongPathTest(String name, File file){
-        super(name);
+    private LongPathTest(String name, String function, File file) {
+        super(function);
+        this.name = name;
         this.file = file;
     }
 
     public static TestSuite suite() throws IOException{
         TestSuite suite = new TestSuite("LongPathTests");
-        File arcdir = getFile("longpath");
+        suite.addTest(createSuite("LongPathTest", "longpath"));
+        suite.addTest(createSuite("LongSymlinkTest", "longsymlink"));
+        return suite;
+    }
+
+    public static TestSuite createSuite(String name, String dirname) throws IOException {
+        TestSuite suite = new TestSuite(name);
+        File arcdir = getFile(dirname);
         assertTrue(arcdir.exists());
         File listing= new File(arcdir,"files.txt");
         assertTrue("File listing is readable",listing.canRead());
         BufferedReader br = new BufferedReader(new FileReader(listing));
+
+        ArrayList<String> fileList = new ArrayList<String>();
         String line;
         while ((line=br.readLine())!=null){
             if (line.startsWith("#")){
@@ -71,6 +85,7 @@ public class LongPathTest extends Abstra
             }
             fileList.add(line);
         }
+        fileLists.put(name, fileList);
         br.close();
         File[]files=arcdir.listFiles();
         for (final File file : files) {
@@ -79,14 +94,25 @@ public class LongPathTest extends Abstra
             }
             // Appears to be the only way to give the test a variable name
             TestSuite namedSuite = new TestSuite(file.getName());
-            Test test = new LongPathTest("testArchive", file);
+            Test test = new LongPathTest(name, "testArchive", file);
             namedSuite.addTest(test);
             suite.addTest(namedSuite);
         }
         return suite;
     }
 
+    protected String getExpectedString(ArchiveEntry entry) {
+        if (entry instanceof TarArchiveEntry) {
+            TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
+            if (tarEntry.isSymbolicLink()) {
+                return tarEntry.getName() + " -> " + tarEntry.getLinkName();
+            }
+        }
+        return entry.getName();
+    }
+
     public void testArchive() throws Exception {
+        ArrayList<String> fileList = fileLists.get(name);
         @SuppressWarnings("unchecked") // fileList is of correct type
         ArrayList<String> expected = (ArrayList<String>) fileList.clone();
         String name = file.getName();

Added: commons/proper/compress/trunk/src/test/resources/longsymlink/files.txt
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/resources/longsymlink/files.txt?rev=1488935&view=auto
==============================================================================
--- commons/proper/compress/trunk/src/test/resources/longsymlink/files.txt (added)
+++ commons/proper/compress/trunk/src/test/resources/longsymlink/files.txt Mon Jun  3 09:20:30 2013
@@ -0,0 +1 @@
+0xxxxxxxxx10xxxxxxxx20xxxxxxxx30xxxxxxxx40xxxxxxxx50xxxxxxxx60xxxxxxxx70xxxxxxxx80xxxxxxxx90xxxxxxxx100xxxxxxx110xxxxxxx120xxxxxxx130xxxxxxx -> 0yyyyyyyyy10yyyyyyyy20yyyyyyyy30yyyyyyyy40yyyyyyyy50yyyyyyyy60yyyyyyyy70yyyyyyyy80yyyyyyyy90yyyyyyyy100yyyyyyy110yyyyyyy120yyyyyyy130yyyyyyy

Propchange: commons/proper/compress/trunk/src/test/resources/longsymlink/files.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/compress/trunk/src/test/resources/longsymlink/gnu.tar
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/resources/longsymlink/gnu.tar?rev=1488935&view=auto
==============================================================================
Binary file - no diff available.

Propchange: commons/proper/compress/trunk/src/test/resources/longsymlink/gnu.tar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream