Author: bodewig
Date: Sat Jul 30 14:08:56 2011
New Revision: 1152467

URL: http://svn.apache.org/viewvc?rev=1152467&view=rev
Log:
second of seven permutations: size known, compression, writing to a stream.  
Lesson learned: don't trust Deflater.getBytesRead, likely don't trust any of 
the related methods either, must fix later.  COMPRESS-150

Modified:
    
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
    
commons/proper/compress/branches/zip64/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java

Modified: 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java?rev=1152467&r1=1152466&r2=1152467&view=diff
==============================================================================
--- 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
 (original)
+++ 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
 Sat Jul 30 14:08:56 2011
@@ -170,6 +170,14 @@ public class ZipArchiveOutputStream exte
     private long cdLength = 0;
 
     /**
+     * Number of bytes read for the current entry (can't rely on
+     * Deflater#getBytesRead) when using DEFLATED.
+     *
+     * @since Apache Commons Compress 1.3
+     */
+    private long bytesRead = 0;
+
+    /**
      * Helper, a 0 as ZipShort.
      */
     private static final byte[] ZERO = {0, 0};
@@ -393,7 +401,12 @@ public class ZipArchiveOutputStream exte
                 deflate();
             }
 
+            /* It turns out def.getBytesRead() returns wrong values if
+             * the size exceeds 4 GB - no idea whether one can trust
+             * def.getBytesWritten()
             entry.setSize(def.getBytesRead());
+            */
+            entry.setSize(bytesRead);
             entry.setCompressedSize(def.getBytesWritten());
             entry.setCrc(realCrc);
 
@@ -438,6 +451,7 @@ public class ZipArchiveOutputStream exte
 
         writeDataDescriptor(entry);
         entry = null;
+        bytesRead = 0;
     }
 
     /**
@@ -569,6 +583,7 @@ public class ZipArchiveOutputStream exte
         ZipUtil.checkRequestedFeatures(entry);
         if (entry.getMethod() == DEFLATED) {
             if (length > 0 && !def.finished()) {
+                bytesRead += length;
                 if (length <= DEFLATER_BLOCK_SIZE) {
                     def.setInput(b, offset, length);
                     deflateUntilInputIsNeeded();
@@ -782,15 +797,15 @@ public class ZipArchiveOutputStream exte
             return;
         }
         writeOut(DD_SIG);
-        writeOut(ZipLong.getBytes(entry.getCrc()));
+        writeOut(ZipLong.getBytes(ze.getCrc()));
         int sizeFieldSize = WORD;
         if (!hasZip64Extra(ze)) {
-            writeOut(ZipLong.getBytes(entry.getCompressedSize()));
-            writeOut(ZipLong.getBytes(entry.getSize()));
+            writeOut(ZipLong.getBytes(ze.getCompressedSize()));
+            writeOut(ZipLong.getBytes(ze.getSize()));
         } else {
             sizeFieldSize = DWORD;
-            writeOut(ZipEightByteInteger.getBytes(entry.getCompressedSize()));
-            writeOut(ZipEightByteInteger.getBytes(entry.getSize()));
+            writeOut(ZipEightByteInteger.getBytes(ze.getCompressedSize()));
+            writeOut(ZipEightByteInteger.getBytes(ze.getSize()));
         }
         written += 2 * WORD + 2 * sizeFieldSize;
     }
@@ -811,16 +826,13 @@ public class ZipArchiveOutputStream exte
 
         if (needsZip64Extra) {
             Zip64ExtendedInformationExtraField z64 = getZip64Extra(ze);
-            if (ze.getCompressedSize() >= ZIP64_MAGIC) { 
+            if (ze.getCompressedSize() >= ZIP64_MAGIC
+                || ze.getSize() >= ZIP64_MAGIC) {
                 z64.setCompressedSize(new 
ZipEightByteInteger(ze.getCompressedSize()));
-            } else {
-                // reset value that may have been set for LFH
-                z64.setCompressedSize(null);
-            }
-            if (ze.getSize() >= ZIP64_MAGIC) {
                 z64.setSize(new ZipEightByteInteger(ze.getSize()));
             } else {
                 // reset value that may have been set for LFH
+                z64.setCompressedSize(null);
                 z64.setSize(null);
             }
             if (lfhOffset >= ZIP64_MAGIC) {
@@ -856,8 +868,14 @@ public class ZipArchiveOutputStream exte
         // compressed length
         // uncompressed length
         writeOut(ZipLong.getBytes(ze.getCrc()));
-        writeOut(ZipLong.getBytes(Math.min(ze.getCompressedSize(), 
ZIP64_MAGIC)));
-        writeOut(ZipLong.getBytes(Math.min(ze.getSize(), ZIP64_MAGIC)));
+        if (ze.getCompressedSize() >= ZIP64_MAGIC
+            || ze.getSize() >= ZIP64_MAGIC) {
+            writeOut(ZipLong.ZIP64_MAGIC.getBytes());
+            writeOut(ZipLong.ZIP64_MAGIC.getBytes());
+        } else {
+            writeOut(ZipLong.getBytes(ze.getCompressedSize()));
+            writeOut(ZipLong.getBytes(ze.getSize()));
+        }
         // CheckStyle:MagicNumber OFF
         written += 12;
         // CheckStyle:MagicNumber ON
@@ -1133,7 +1151,7 @@ public class ZipArchiveOutputStream exte
     private Zip64ExtendedInformationExtraField
         getZip64Extra(ZipArchiveEntry ze) {
         hasUsedZip64 = true;
-        Zip64ExtendedInformationExtraField z64 =  
+        Zip64ExtendedInformationExtraField z64 =
             (Zip64ExtendedInformationExtraField)
             ze.getExtraField(Zip64ExtendedInformationExtraField
                              .HEADER_ID);

Modified: 
commons/proper/compress/branches/zip64/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/branches/zip64/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java?rev=1152467&r1=1152466&r2=1152467&view=diff
==============================================================================
--- 
commons/proper/compress/branches/zip64/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java
 (original)
+++ 
commons/proper/compress/branches/zip64/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java
 Sat Jul 30 14:08:56 2011
@@ -213,16 +213,7 @@ public class Zip64SupportTest {
 
                 RandomAccessFile a = new RandomAccessFile(f, "r");
                 try {
-                    final long end = a.length();
-                    long cdOffsetLoc = end - 22 /* eocd.length */
-                        - 20 /* z64 eocd locator.length */
-                        - 56 /* z64 eocd without extensible data sector */
-                        + 48 /* position in z64 eocd */;
-                    // seek to central directory
-                    a.seek(cdOffsetLoc);
-                    byte[] cdOffset = new byte[8];
-                    a.readFully(cdOffset);
-                    a.seek(ZipEightByteInteger.getLongValue(cdOffset));
+                    final long end = getLengthAndPositionAtCentralDirectory(a);
                     // skip first two entries
                     a.skipBytes(2 * 47 /* CD entry of file with
                                           file name length 1 and no
@@ -339,17 +330,8 @@ public class Zip64SupportTest {
                                      RandomAccessFile a =
                                          new RandomAccessFile(f, "r");
                                      try {
-                                         final long end = a.length();
-                                         long cdOffsetLoc = end - 22
-                                             - 20
-                                             - 56
-                                             + 48;
-                                         // seek to central directory
-                                         a.seek(cdOffsetLoc);
-                                         byte[] cdOffset = new byte[8];
-                                         a.readFully(cdOffset);
-                                         a.seek(ZipEightByteInteger
-                                                .getLongValue(cdOffset));
+                                         final long end =
+                                             
getLengthAndPositionAtCentralDirectory(a);
 
                                          // grab first entry, verify
                                          // sizes are 0xFFFFFFFF and
@@ -473,7 +455,6 @@ public class Zip64SupportTest {
      *
      * Creates a temporary archive of approx 4MB in size
      */
-    @Ignore
     @Test public void writeBigDeflatedEntryKnownSizeToStream()
         throws Throwable {
         withTemporaryArchive("writeBigDeflatedEntryKnownSizeToStream",
@@ -498,18 +479,10 @@ public class Zip64SupportTest {
                                      RandomAccessFile a =
                                          new RandomAccessFile(f, "r");
                                      try {
-                                         final long end = a.length();
-                                         long cdOffsetLoc = end - 22
-                                             - 20
-                                             - 56
-                                             + 48;
-                                         // seek to central directory
-                                         a.seek(cdOffsetLoc);
-                                         byte[] cdOffset = new byte[8];
-                                         a.readFully(cdOffset);
-                                         a.seek(ZipEightByteInteger
-                                                .getLongValue(cdOffset));
+                                         final long end =
+                                             
getLengthAndPositionAtCentralDirectory(a);
 
+                                         long cfhPos = a.getFilePointer();
                                          // grab first entry, verify
                                          // sizes are 0xFFFFFFFF and
                                          // it has a ZIP64 extended
@@ -523,35 +496,29 @@ public class Zip64SupportTest {
                                                  45, 0,
                                                  // version needed to extract
                                                  45, 0,
-                                                 // GPB
+                                                 // GPB (EFS + Data Descriptor)
                                                  8, 8,
                                                  // method
                                                  8, 0,
                                              }, header);
                                          // ignore timestamp
                                          a.skipBytes(4);
-                                         byte[] crc = new byte[4];
-                                         a.readFully(crc);
+                                         byte[] rest = new byte[31];
+                                         a.readFully(rest);
                                          assertArrayEquals(new byte[] {
+                                                 // CRC
                                                  (byte) 0x50, (byte) 0x6F,
                                                  (byte) 0x31, (byte) 0x5c,
-                                             }, crc);
-                                         // ignore compressed size,
-                                         // check it is smaller than
-                                         // 4GB by validating it is
-                                         // not part of the ZIP64
-                                         // extra field
-                                         a.skipBytes(4);
-                                         byte[] rest = new byte[23];
-                                         a.readFully(rest);
-                                         assertArrayEquals(new byte[] {
+                                                 // Compressed Size
+                                                 (byte) 0xFF, (byte) 0xFF,
+                                                 (byte) 0xFF, (byte) 0xFF,
                                                  // Original Size
                                                  (byte) 0xFF, (byte) 0xFF,
                                                  (byte) 0xFF, (byte) 0xFF,
                                                  // file name length
                                                  1, 0,
                                                  // extra field length
-                                                 12, 0,
+                                                 20, 0,
                                                  // comment length
                                                  0, 0,
                                                  // disk number
@@ -571,12 +538,37 @@ public class Zip64SupportTest {
                                                  // Header-ID
                                                  1, 0,
                                                  // size of extra
-                                                 8, 0,
+                                                 16, 0,
                                                  // original size
                                                  0, (byte) 0xF2, 5, (byte) 
0x2A,
                                                  1, 0, 0, 0,
+                                                 // don't know the
+                                                 // compressed size,
+                                                 // don't want to
+                                                 // hard-code it
                                              }, extra);
 
+                                         // validate data descriptor
+                                         a.seek(cfhPos - 24);
+                                         byte[] dd = new byte[8];
+                                         a.readFully(dd);
+                                         assertArrayEquals(new byte[] {
+                                                 // sig
+                                                 (byte) 0x50, (byte) 0x4b, 7, 
8,
+                                                 // CRC
+                                                 (byte) 0x50, (byte) 0x6F,
+                                                 (byte) 0x31, (byte) 0x5c,
+                                             }, dd);
+                                         // skip uncompressed size
+                                         a.skipBytes(8);
+                                         dd = new byte[8];
+                                         a.readFully(dd);
+                                         assertArrayEquals(new byte[] {
+                                                 // original size
+                                                 0, (byte) 0xF2, 5, (byte) 
0x2A,
+                                                 1, 0, 0, 0,
+                                             }, dd);
+
                                          // and now validate local file header
                                          a.seek(0);
                                          header = new byte[10];
@@ -623,8 +615,6 @@ public class Zip64SupportTest {
                                      } finally {
                                          a.close();
                                      }
-
-                                     read5GBOfZerosImpl(f, "0");
                                  }
                              },
                              false);
@@ -717,4 +707,16 @@ public class Zip64SupportTest {
             }
         }
     }
+
+    private static long 
getLengthAndPositionAtCentralDirectory(RandomAccessFile a)
+        throws IOException {
+        final long end = a.length();
+        long cdOffsetLoc = end - 22 - 20 - 56 + 48;
+        // seek to central directory locator
+        a.seek(cdOffsetLoc);
+        byte[] cdOffset = new byte[8];
+        a.readFully(cdOffset);
+        a.seek(ZipEightByteInteger.getLongValue(cdOffset));
+        return end;
+    }
 }


Reply via email to