Commits

Anonymous committed ad17645

propely handle GNU longlink entries, PR 55040, submitted by Christoph Gysin

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@148895113f79535-47bb-0310-9956-ffa450edef68

  • Participants
  • Parent commits 6389bb6

Comments (0)

Files changed (6)

 Charlie Hubbard
 Chris Povirk
 Christian Knorr
+Christoph Gysin
 Christoph Wilhelms
 Christophe Labouisse
 Christopher A. Longo
    be able to read archives created by DotNetZip and maybe other
    archivers as well.
 
+ * TarInputStream should now properly read GNU longlink entries' names.
+   Bugzilla Report 55040.
+
 Other changes:
 --------------
 
   </name>
   <name>
     <first>Christoph</first>
+    <last>Gysin</last>
+  </name>
+  <name>
+    <first>Christoph</first>
     <last>Wilhelms</last>
   </name>
   <name>

src/main/org/apache/tools/tar/TarConstants.java

     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';

src/main/org/apache/tools/tar/TarEntry.java

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

src/main/org/apache/tools/tar/TarInputStream.java

         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) {
+        if (currEntry.isGNULongLinkEntry()) {
+            byte[] longLinkData = getLongNameData();
+            if (longLinkData == null) {
                 // Bugzilla: 40334
-                // Malformed tar file - long entry name not followed by entry
+                // Malformed tar file - long link 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;
+            currEntry.setLinkName(encoding.decode(longLinkData));
+        }
+
+        if (currEntry.isGNULongNameEntry()) {
+            byte[] longNameData = getLongNameData();
+            if (longNameData == null) {
+                // Bugzilla: 40334
+                // Malformed tar file - long entry name not followed by
+                // entry
+                return null;
             }
-            
             currEntry.setName(encoding.decode(longNameData));
         }
 
     }
 
     /**
+     * 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