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 2012/03/05 20:34:13 UTC

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

Author: bodewig
Date: Mon Mar  5 19:34:12 2012
New Revision: 1297191

URL: http://svn.apache.org/viewvc?rev=1297191&view=rev
Log:
user STAR encoding for all numeric fields in tar headers if they don't fit in the 'normal' range.  COMPRESS-182

Added:
    commons/proper/compress/trunk/src/test/resources/preepoch-star.tar
      - copied unchanged from r1297188, commons/proper/compress/trunk/src/test/resources/preepoch-gnu.tar
Removed:
    commons/proper/compress/trunk/src/test/resources/preepoch-gnu.tar
Modified:
    commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java
    commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStreamTest.java
    commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.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=1297191&r1=1297190&r2=1297191&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 Mar  5 19:34:12 2012
@@ -755,23 +755,22 @@ public class TarArchiveEntry implements 
      *
      * @param outbuf The tar entry header buffer to fill in.
      * @param starMode whether to use the star/GNU tar/BSD tar
-     * extension for the size field if the size is bigger than 8GiB
+     * extension for numeric fields if their value doesn't fit in the
+     * maximum size of standard tar archives
      * @since Apache Commons Compress 1.4
      */
     public void writeEntryHeader(byte[] outbuf, boolean starMode) {
         int offset = 0;
 
         offset = TarUtils.formatNameBytes(name, outbuf, offset, NAMELEN);
-        offset = TarUtils.formatOctalBytes(mode, outbuf, offset, MODELEN);
-        offset = TarUtils.formatOctalBytes(userId, outbuf, offset, UIDLEN);
-        offset = TarUtils.formatOctalBytes(groupId, outbuf, offset, GIDLEN);
-        if (size > TarConstants.MAXSIZE && !starMode) {
-            // size is in PAX header
-            offset = TarUtils.formatLongOctalBytes(0, outbuf, offset, SIZELEN);
-        } else {
-            offset = TarUtils.formatLongOctalOrBinaryBytes(size, outbuf, offset, SIZELEN);
-        }
-        offset = TarUtils.formatLongOctalBytes(modTime, outbuf, offset, MODTIMELEN);
+        offset = writeEntryHeaderField(mode, outbuf, offset, MODELEN, starMode);
+        offset = writeEntryHeaderField(userId, outbuf, offset, UIDLEN,
+                                       starMode);
+        offset = writeEntryHeaderField(groupId, outbuf, offset, GIDLEN,
+                                       starMode);
+        offset = writeEntryHeaderField(size, outbuf, offset, SIZELEN, starMode);
+        offset = writeEntryHeaderField(modTime, outbuf, offset, MODTIMELEN,
+                                       starMode);
 
         int csOffset = offset;
 
@@ -785,8 +784,10 @@ public class TarArchiveEntry implements 
         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);
-        offset = TarUtils.formatOctalBytes(devMinor, outbuf, offset, DEVLEN);
+        offset = writeEntryHeaderField(devMajor, outbuf, offset, DEVLEN,
+                                       starMode);
+        offset = writeEntryHeaderField(devMinor, outbuf, offset, DEVLEN,
+                                       starMode);
 
         while (offset < outbuf.length) {
             outbuf[offset++] = 0;
@@ -797,6 +798,19 @@ public class TarArchiveEntry implements 
         TarUtils.formatCheckSumOctalBytes(chk, outbuf, csOffset, CHKSUMLEN);
     }
 
+    private int writeEntryHeaderField(long value, byte[] outbuf, int offset,
+                                      int length, boolean starMode) {
+        if (!starMode && (value < 0
+                          || value >= (1l << (3 * (length - 1))))) {
+            // value doesn't fit into field when written as octal
+            // number, will be written to PAX header or causes an
+            // error
+            return TarUtils.formatLongOctalBytes(0, outbuf, offset, length);
+        }
+        return TarUtils.formatLongOctalOrBinaryBytes(value, outbuf, offset,
+                                                     length);
+    }
+
     /**
      * Parse an entry's header information from a header buffer.
      *

Modified: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStreamTest.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStreamTest.java?rev=1297191&r1=1297190&r2=1297191&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStreamTest.java (original)
+++ commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStreamTest.java Mon Mar  5 19:34:12 2012
@@ -69,7 +69,7 @@ public class TarArchiveInputStreamTest {
 
     @Test
     public void datePriorToEpochInGNUFormat() throws Exception {
-        datePriorToEpoch("/preepoch-gnu.tar");
+        datePriorToEpoch("/preepoch-star.tar");
     }
 
 

Modified: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java?rev=1297191&r1=1297190&r2=1297191&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java (original)
+++ commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java Mon Mar  5 19:34:12 2012
@@ -23,8 +23,10 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.TimeZone;
 
 import org.apache.commons.compress.AbstractTestCase;
 import org.apache.commons.compress.archivers.ArchiveOutputStream;
@@ -204,4 +206,31 @@ public class TarArchiveOutputStreamTest 
         TarArchiveEntry e = tin.getNextTarEntry();
         assertEquals(n, e.getName());
     }
+
+    public void testOldEntryStarMode() throws Exception {
+        TarArchiveEntry t = new TarArchiveEntry("foo");
+        t.setSize(Integer.MAX_VALUE);
+        t.setModTime(-1000);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
+        tos.setBigFileMode(TarArchiveOutputStream.BIGFILE_STAR);
+        tos.putArchiveEntry(t);
+        // make sure header is written to byte array
+        tos.write(new byte[10 * 1024]);
+        byte[] data = bos.toByteArray();
+        assertEquals((byte) 0xff,
+                     data[TarConstants.NAMELEN
+                          + TarConstants.MODELEN
+                          + TarConstants.UIDLEN
+                          + TarConstants.GIDLEN
+                          + TarConstants.SIZELEN]);
+        TarArchiveInputStream tin =
+            new TarArchiveInputStream(new ByteArrayInputStream(data));
+        TarArchiveEntry e = tin.getNextTarEntry();
+        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+        cal.set(1969, 11, 31, 23, 59, 59);
+        cal.set(Calendar.MILLISECOND, 0);
+        assertEquals(cal.getTime(), e.getLastModifiedDate());
+    }
+
 }
\ No newline at end of file