Author: bodewig Date: Tue Mar 6 05:19:24 2012 New Revision: 1297339 URL: http://svn.apache.org/viewvc?rev=1297339&view=rev Log: Use PAX headers for big or negative numeric values in tar headers. COMPRESS-182 Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.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/TarArchiveOutputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java?rev=1297339&r1=1297338&r2=1297339&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java Tue Mar 6 05:19:24 2012 @@ -237,14 +237,10 @@ public class TarArchiveOutputStream exte } } - if (entry.getSize() > TarConstants.MAXSIZE) { - if (bigFileMode == BIGFILE_POSIX) { - paxHeaders.put("size", String.valueOf(entry.getSize())); - } else if (bigFileMode != BIGFILE_STAR) { - throw new RuntimeException("file size '" + entry.getSize() - + "' is too big ( > " - + TarConstants.MAXSIZE + " bytes)"); - } + if (bigFileMode == BIGFILE_POSIX) { + addPaxHeadersForBigNumbers(paxHeaders, entry); + } else if (bigFileMode != BIGFILE_STAR) { + failForBigNumbers(entry); } if (paxHeaders.size() > 0) { @@ -450,4 +446,58 @@ public class TarArchiveOutputStream exte } return new TarArchiveEntry(inputFile, entryName); } + + private void addPaxHeadersForBigNumbers(Map paxHeaders, + TarArchiveEntry entry) { + if (entry.getSize() > TarConstants.MAXSIZE) { + paxHeaders.put("size", String.valueOf(entry.getSize())); + } + if (entry.getGroupId() > TarConstants.MAXID) { + paxHeaders.put("gid", String.valueOf(entry.getGroupId())); + } + final long mtime = entry.getModTime().getTime() / 1000; + if (mtime < 0 || mtime > TarConstants.MAXSIZE) { + paxHeaders.put("mtime", String.valueOf(mtime)); + } + if (entry.getUserId() > TarConstants.MAXID) { + paxHeaders.put("uid", String.valueOf(entry.getUserId())); + } + if (entry.getMode() > TarConstants.MAXID) { + throw new RuntimeException("mode '" + entry.getMode() + + "' is too big ( > " + + TarConstants.MAXID + " bytes)"); + } + // TODO add devMajor and devMinor + } + + private void failForBigNumbers(TarArchiveEntry entry) { + if (entry.getSize() > TarConstants.MAXSIZE) { + throw new RuntimeException("file size '" + entry.getSize() + + "' is too big ( > " + + TarConstants.MAXSIZE + " bytes)"); + } + if (entry.getGroupId() > TarConstants.MAXID) { + throw new RuntimeException("group id '" + entry.getGroupId() + + "' is too big ( > " + + TarConstants.MAXID + " bytes)"); + } + final long mtime = entry.getModTime().getTime() / 1000; + if (mtime < 0 || mtime > TarConstants.MAXSIZE) { + throw new RuntimeException("last modification time '" + + entry.getModTime() + + "' is too big ( > " + + TarConstants.MAXSIZE + " bytes)"); + } + if (entry.getUserId() > TarConstants.MAXID) { + throw new RuntimeException("user id '" + entry.getUserId() + + "' is too big ( > " + + TarConstants.MAXID + " bytes)"); + } + if (entry.getMode() > TarConstants.MAXID) { + throw new RuntimeException("mode '" + entry.getMode() + + "' is too big ( > " + + TarConstants.MAXID + " bytes)"); + } + // TODO add devMajor and devMinor + } } 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=1297339&r1=1297338&r2=1297339&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 Tue Mar 6 05:19:24 2012 @@ -233,4 +233,45 @@ public class TarArchiveOutputStreamTest assertEquals(cal.getTime(), e.getLastModifiedDate()); } + public void testOldEntryPosixMode() 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_POSIX); + tos.putArchiveEntry(t); + // make sure header is written to byte array + tos.write(new byte[10 * 1024]); + byte[] data = bos.toByteArray(); + assertEquals("00000000000 ", + new String(data, + 1024 + TarConstants.NAMELEN + + TarConstants.MODELEN + + TarConstants.UIDLEN + + TarConstants.GIDLEN + + TarConstants.SIZELEN, 12, + "UTF-8")); + 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()); + } + + public void testOldEntryError() throws Exception { + TarArchiveEntry t = new TarArchiveEntry("foo"); + t.setSize(Integer.MAX_VALUE); + t.setModTime(-1000); + TarArchiveOutputStream tos = + new TarArchiveOutputStream(new ByteArrayOutputStream()); + try { + tos.putArchiveEntry(t); + fail("Should have generated RuntimeException"); + } catch (RuntimeException expected) { + } + } + } \ No newline at end of file