You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2009/04/03 01:34:48 UTC

svn commit: r761475 - in /commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar: TarArchiveEntry.java TarArchiveInputStream.java TarConstants.java

Author: sebb
Date: Thu Apr  2 23:34:48 2009
New Revision: 761475

URL: http://svn.apache.org/viewvc?rev=761475&view=rev
Log:
Split magic into magic and version
Improve match() method so it works for Posix and GNU

Modified:
    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

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=761475&r1=761474&r2=761475&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 Thu Apr  2 23:34:48 2009
@@ -54,24 +54,25 @@
  * The C structure for a Tar Entry's header is:
  * <pre>
  * struct header {
- * char name[100];     // TarConstants.NAMELEN
- * char mode[8];       // TarConstants.MODELEN
- * char uid[8];        // TarConstants.UIDLEN
- * char gid[8];        // TarConstants.GIDLEN
- * char size[12];      // TarConstants.SIZELEN
- * char mtime[12];     // TarConstants.MODTIMELEN
- * char chksum[8];     // TarConstants.CHKSUMLEN
- * char linkflag[1];
- * char linkname[100]; // TarConstants.NAMELEN
+ * char name[100];     // TarConstants.NAMELEN    - offset   0
+ * char mode[8];       // TarConstants.MODELEN    - offset 100
+ * char uid[8];        // TarConstants.UIDLEN     - offset 108
+ * char gid[8];        // TarConstants.GIDLEN     - offset 116
+ * char size[12];      // TarConstants.SIZELEN    - offset 124
+ * char mtime[12];     // TarConstants.MODTIMELEN - offset 136
+ * char chksum[8];     // TarConstants.CHKSUMLEN  - offset 148
+ * char linkflag[1];   //                         - offset 156
+ * char linkname[100]; // TarConstants.NAMELEN    - offset 157
  * The following fields are only present in new-style POSIX tar archives:
- * char magic[8];      // TarConstants.MAGICLEN
- * TODO: Posix/GNU split this into magic[6] and char version[2];
- * char uname[32];     // TarConstants.UNAMELEN
- * char gname[32];     // TarConstants.GNAMELEN
- * char devmajor[8];   // TarConstants.DEVLEN
- * char devminor[8];   // TarConstants.DEVLEN
- * char prefix[155];   // Used if "name" field is not long enough to hold the path
- * char pad[12];       // NULs
+ * char magic[6];      // TarConstants.MAGICLEN   - offset 257
+ * char version[2];    // TarConstants.VERSIONLEN - offset 263
+ * char uname[32];     // TarConstants.UNAMELEN   - offset 265
+ * char gname[32];     // TarConstants.GNAMELEN   - offset 297
+ * char devmajor[8];   // TarConstants.DEVLEN     - offset 329
+ * char devminor[8];   // TarConstants.DEVLEN     - offset 337
+ * char prefix[155];   // TarConstants.PREFIXLEN  - offset 345
+ * // Used if "name" field is not long enough to hold the path
+ * char pad[12];       // NULs                    - offset 500
  * } header;
  * All unused bytes are set to null.
  * New-style GNU tar files are slightly different from the above.
@@ -107,6 +108,8 @@
 
     /** The entry's magic tag. */
     private String magic;
+    /** The version of the format */
+    private String version;
 
     /** The entry's user name. */
     private String userName;
@@ -140,6 +143,7 @@
      */
     private TarArchiveEntry () {
         this.magic = MAGIC_POSIX;
+        this.version = VERSION_POSIX;
         this.name = "";
         this.linkName = "";
 
@@ -577,6 +581,7 @@
         outbuf[offset++] = linkFlag;
         offset = TarUtils.formatNameBytes(linkName, outbuf, offset, NAMELEN);
         offset = TarUtils.formatNameBytes(magic, outbuf, offset, MAGICLEN);
+        offset = TarUtils.formatNameBytes(version, outbuf, offset, VERSIONLEN);
         offset = TarUtils.formatNameBytes(userName, outbuf, offset, UNAMELEN);
         offset = TarUtils.formatNameBytes(groupName, outbuf, offset, GNAMELEN);
         offset = TarUtils.formatOctalBytes(devMajor, outbuf, offset, DEVLEN);
@@ -617,6 +622,8 @@
         offset += NAMELEN;
         magic = TarUtils.parseName(header, offset, MAGICLEN);
         offset += MAGICLEN;
+        version = TarUtils.parseName(header, offset, VERSIONLEN);
+        offset += VERSIONLEN;
         userName = TarUtils.parseName(header, offset, UNAMELEN);
         offset += UNAMELEN;
         groupName = TarUtils.parseName(header, offset, GNAMELEN);

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=761475&r1=761474&r2=761475&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 Thu Apr  2 23:34:48 2009
@@ -28,6 +28,7 @@
 import java.io.OutputStream;
 import org.apache.commons.compress.archivers.ArchiveEntry;
 import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.utils.ArchiveUtils;
 
 /**
  * The TarInputStream reads a UNIX tar archive as an InputStream.
@@ -380,39 +381,32 @@
     // ArchiveInputStream
 
     public static boolean matches(byte[] signature, int length) {
-        // 6574 7473 2e31 6d78 == "test1.xml"
-        // TODO replace with a proper test if possible - see COMPRESS-65
-
-        if (length < 8) {
+        if (length < TarConstants.VERSION_OFFSET+TarConstants.VERSIONLEN) {
             return false;
         }
 
-        if (signature[0] != 0x74) {
-            return false;
+        if (ArchiveUtils.matchAsciiBuffer(TarConstants.MAGIC_POSIX, 
+                signature, TarConstants.MAGIC_OFFSET, TarConstants.MAGICLEN)
+            &&
+            ArchiveUtils.matchAsciiBuffer(TarConstants.VERSION_POSIX, 
+                signature, TarConstants.VERSION_OFFSET, TarConstants.VERSIONLEN)
+                ){
+            return true;
+        }
+        if (ArchiveUtils.matchAsciiBuffer(TarConstants.MAGIC_GNU, 
+                signature, TarConstants.MAGIC_OFFSET, TarConstants.MAGICLEN)
+            &&
+            (
+             ArchiveUtils.matchAsciiBuffer(TarConstants.VERSION_GNU_SPACE, 
+                signature, TarConstants.VERSION_OFFSET, TarConstants.VERSIONLEN)
+            ||
+            ArchiveUtils.matchAsciiBuffer(TarConstants.VERSION_GNU_ZERO, 
+                signature, TarConstants.VERSION_OFFSET, TarConstants.VERSIONLEN)
+            )
+                ){
+            return true;
         }
-        if (signature[1] != 0x65) {
-            return false;
-        }
-        if (signature[2] != 0x73) {
-            return false;
-        }
-        if (signature[3] != 0x74) {
-            return false;
-        }
-        if (signature[4] != 0x31) {
-            return false;
-        }
-        if (signature[5] != 0x2e) {
-            return false;
-        }
-        if (signature[6] != 0x78) {
-            return false;
-        }
-        if (signature[7] != 0x6d) {
-            return false;
-        }
-
-        return true;
+        return false;
     }
 
 }

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=761475&r1=761474&r2=761475&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 Thu Apr  2 23:34:48 2009
@@ -60,10 +60,19 @@
      */
     long   MAXSIZE = 077777777777L;
 
+    /** Offset of start of magic field within header record */
+    int    MAGIC_OFFSET = 257;
     /**
      * The length of the magic field in a header buffer.
      */
-    int    MAGICLEN = 8; // TODO split this into MAGICLEN=6 and VERSIONLEN=2
+    int    MAGICLEN = 6;
+
+    /** Offset of start of magic field within header record */
+    int    VERSION_OFFSET = 263;
+    /**
+     * Previously this was regarded as part of "magic" field, but it is separate.
+     */
+    int    VERSIONLEN = 2;
 
     /**
      * The length of the modification time field in a header buffer.
@@ -86,6 +95,12 @@
     int    DEVLEN = 8;
 
     /**
+     * Length of the prefix field.
+     * 
+     */
+    int    PREFIXLEN = 155;
+
+    /**
      * LF_ constants represent the "link flag" of an entry, or more commonly,
      * the "entry type". This is the "old way" of indicating a normal file.
      */
@@ -134,12 +149,16 @@
     /**
      * The magic tag representing a POSIX tar archive.
      */
-    String MAGIC_POSIX = "ustar"; // TODO this should be NUL-terminated
+    String MAGIC_POSIX = "ustar\0";
+    String VERSION_POSIX = "00";
 
     /**
      * The magic tag representing a GNU tar archive.
      */
-    String MAGIC_GNU = "ustar  "; // TODO this should have single space terminator
+    String MAGIC_GNU = "ustar ";
+    // Appear to be two possible GNU versions
+    String VERSION_GNU_SPACE = " \0";
+    String VERSION_GNU_ZERO  = "0\0";
 
     /**
      * The name of the GNU tar entry which contains a long name.