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 2020/01/21 17:30:08 UTC

[commons-compress] branch master updated (9e0d5a7 -> 2dbdb7b)

This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git.


    from 9e0d5a7  we trigger libbzip2's advertising clause
     new b4fd49a  COMPRESS-477 : add Zip64 support for split zip
     new 13cd268  Merge branch 'master' of https://github.com/apache/commons-compress into COMPRESS-477-zip64
     new 27fd203  COMPRESS-477 : add testcases for zip64 split zip
     new 2dbdb7b  Merge branch 'COMPRESS-477-zip64' of https://github.com/PeterAlfreadLee/commons-compress into PeterAlfreadLee-COMPRESS-477-zip64

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../archivers/zip/Zip64RequiredException.java      | 12 +++
 .../archivers/zip/ZipArchiveOutputStream.java      | 95 +++++++++++++++++++---
 .../compress/archivers/zip/Zip64SupportIT.java     | 87 +++++++++++++++-----
 3 files changed, 161 insertions(+), 33 deletions(-)


[commons-compress] 03/04: COMPRESS-477 : add testcases for zip64 split zip

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git

commit 27fd2033d1218a652f09f59aa3d52db2b4d839ab
Author: Lee <pe...@gmail.com>
AuthorDate: Sat Jan 11 09:19:16 2020 +0800

    COMPRESS-477 : add testcases for zip64 split zip
    
    add testcases about zip64 in split zip
---
 .../compress/archivers/zip/Zip64SupportIT.java     | 87 +++++++++++++++++-----
 1 file changed, 67 insertions(+), 20 deletions(-)

diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportIT.java b/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportIT.java
index ba30c3f..bc9cdf2 100644
--- a/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportIT.java
+++ b/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportIT.java
@@ -362,6 +362,10 @@ public class Zip64SupportIT {
         return write3EntriesCreatingBigArchive(Zip64Mode.AsNeeded);
     }
 
+    private static ZipOutputTest write3EntriesCreatingBigArchive(final Zip64Mode mode) {
+        return write3EntriesCreatingBigArchive(mode, false);
+    }
+
     /*
      * Individual sizes don't require ZIP64 but the offset of the
      * third entry is bigger than 0xFFFFFFFF so a ZIP64 extended
@@ -370,7 +374,7 @@ public class Zip64SupportIT {
      * Creates a temporary archive of approx 5GB in size
      */
     private static ZipOutputTest
-        write3EntriesCreatingBigArchive(final Zip64Mode mode) {
+        write3EntriesCreatingBigArchive(final Zip64Mode mode, final boolean isSplitArchive) {
         return new ZipOutputTest() {
             @Override
             public void test(final File f, final ZipArchiveOutputStream zos)
@@ -386,7 +390,7 @@ public class Zip64SupportIT {
                     a.skipBytes(2 * 47 /* CD entry of file with
                                           file name length 1 and no
                                           extra data */
-                                    + 2 * (mode == Zip64Mode.Always ? 28 : 0)
+                                    + 2 * (mode == Zip64Mode.Always ? 32 : 0)
                                 /* ZIP64 extra fields if mode is Always */
                     );
 
@@ -427,11 +431,11 @@ public class Zip64SupportIT {
                             // file name length
                             1, 0,
                             // extra field length
-                            (byte) (mode == Zip64Mode.Always? 28 : 12), 0,
+                            (byte) (mode == Zip64Mode.Always? 32 : 12), 0,
                             // comment length
                             0, 0,
                             // disk number
-                            0, 0,
+                            (byte) (isSplitArchive? 0xFF : 0), (byte) (isSplitArchive? 0xFF : 0),
                             // attributes
                             0, 0,
                             0, 0, 0, 0,
@@ -448,7 +452,7 @@ public class Zip64SupportIT {
                                 // Header-ID
                                 1, 0,
                                 // size
-                                24, 0,
+                                28, 0,
                                 // Original Size
                                 1, 0, 0, 0, 0, 0, 0, 0,
                             }, extra);
@@ -645,7 +649,7 @@ public class Zip64SupportIT {
                             // file name length
                             1, 0,
                             // extra field length
-                            (byte) (mode == Zip64Mode.Always? 28 : 20), 0,
+                            (byte) (mode == Zip64Mode.Always? 32 : 20), 0,
                             // comment length
                             0, 0,
                             // disk number
@@ -673,7 +677,7 @@ public class Zip64SupportIT {
                             // Header-ID
                             1, 0,
                             // size of extra
-                            (byte) (mode == Zip64Mode.Always? 24 : 16), 0,
+                            (byte) (mode == Zip64Mode.Always? 28 : 16), 0,
                             // original size
                             0, (byte) 0xF2, 5, (byte) 0x2A,
                             1, 0, 0, 0,
@@ -899,7 +903,7 @@ public class Zip64SupportIT {
                             // file name length
                             1, 0,
                             // extra field length
-                            (byte) (mode == Zip64Mode.Always? 28 : 20), 0,
+                            (byte) (mode == Zip64Mode.Always? 32 : 20), 0,
                             // comment length
                             0, 0,
                             // disk number
@@ -927,7 +931,7 @@ public class Zip64SupportIT {
                             // Header-ID
                             1, 0,
                             // size of extra
-                            (byte) (mode == Zip64Mode.Always? 24 : 16), 0,
+                            (byte) (mode == Zip64Mode.Always? 28 : 16), 0,
                             // original size
                             0, (byte) 0xF2, 5, (byte) 0x2A,
                             1, 0, 0, 0,
@@ -1153,7 +1157,7 @@ public class Zip64SupportIT {
                             // file name length
                             1, 0,
                             // extra field length
-                            (byte) (mode == Zip64Mode.Always? 28 : 20), 0,
+                            (byte) (mode == Zip64Mode.Always? 32 : 20), 0,
                             // comment length
                             0, 0,
                             // disk number
@@ -1181,7 +1185,7 @@ public class Zip64SupportIT {
                             // Header-ID
                             1, 0,
                             // size of extra
-                            (byte) (mode == Zip64Mode.Always? 24 : 16), 0,
+                            (byte) (mode == Zip64Mode.Always? 28 : 16), 0,
                             // original size
                             0, (byte) 0xF2, 5, (byte) 0x2A,
                             1, 0, 0, 0,
@@ -1594,7 +1598,7 @@ public class Zip64SupportIT {
                             // file name length
                             1, 0,
                             // extra field length
-                            28, 0,
+                            32, 0,
                             // comment length
                             0, 0,
                             // disk number
@@ -1614,7 +1618,7 @@ public class Zip64SupportIT {
                             // Header-ID
                             1, 0,
                             // size of extra
-                            24, 0,
+                            28, 0,
                             // original size
                             (byte) 0x40, (byte) 0x42, (byte) 0x0F, 0,
                             0, 0, 0, 0,
@@ -1935,7 +1939,7 @@ public class Zip64SupportIT {
                             // file name length
                             1, 0,
                             // extra field length
-                            28, 0,
+                            32, 0,
                             // comment length
                             0, 0,
                             // disk number
@@ -1954,7 +1958,7 @@ public class Zip64SupportIT {
                             // Header-ID
                             1, 0,
                             // size of extra
-                            24, 0,
+                            28, 0,
                             // original size
                             (byte) 0x40, (byte) 0x42, (byte) 0x0F, 0,
                             0, 0, 0, 0,
@@ -2294,7 +2298,7 @@ public class Zip64SupportIT {
                             // file name length
                             1, 0,
                             // extra field length
-                            28, 0,
+                            32, 0,
                             // comment length
                             0, 0,
                             // disk number
@@ -2313,7 +2317,7 @@ public class Zip64SupportIT {
                             // Header-ID
                             1, 0,
                             // size of extra
-                            24, 0,
+                            28, 0,
                             // original size
                             (byte) 0x40, (byte) 0x42, (byte) 0x0F, 0,
                             0, 0, 0, 0,
@@ -2398,19 +2402,56 @@ public class Zip64SupportIT {
                              true);
     }
 
+    @Test
+    public void write3EntriesCreatingManySplitArchiveFileModeNever()
+            throws Throwable {
+        withTemporaryArchive("write3EntriesCreatingManySplitArchiveFileModeNever",
+                write3EntriesCreatingBigArchiveModeNever,
+                true, 65536L);
+    }
+
+    @Test
+    public void write3EntriesCreatingManySplitArchiveFileModeAlways()
+            throws Throwable {
+        // about 76,293 zip split segments will be created
+        withTemporaryArchive("write3EntriesCreatingManySplitArchiveFileModeAlways",
+                write3EntriesCreatingBigArchive(Zip64Mode.Always, true),
+                true, 65536L);
+    }
+
     static interface ZipOutputTest {
         void test(File f, ZipArchiveOutputStream zos) throws IOException;
     }
 
     private static void withTemporaryArchive(final String testName,
                                              final ZipOutputTest test,
-                                             final boolean useRandomAccessFile)
+                                             final boolean useRandomAccessFile) throws Throwable {
+        withTemporaryArchive(testName, test, useRandomAccessFile, null);
+    }
+
+    private static void withTemporaryArchive(final String testName,
+                                             final ZipOutputTest test,
+                                             final boolean useRandomAccessFile,
+                                             final Long splitSize)
         throws Throwable {
-        final File f = getTempFile(testName);
+        File f = getTempFile(testName);
+        File dir = null;
+        if (splitSize != null) {
+            dir = File.createTempFile("commons-compress-" + testName, "");
+            dir.delete();
+            dir.mkdir();
+            dir.deleteOnExit();
+
+            f = new File(dir, "commons-compress-" + testName + ".zip");
+        }
         BufferedOutputStream os = null;
-        final ZipArchiveOutputStream zos = useRandomAccessFile
+        ZipArchiveOutputStream zos = useRandomAccessFile
             ? new ZipArchiveOutputStream(f)
             : new ZipArchiveOutputStream(os = new BufferedOutputStream(new FileOutputStream(f)));
+        if (splitSize != null) {
+            zos = new ZipArchiveOutputStream(f, splitSize);
+        }
+
         try {
             test.test(f, zos);
         } catch (final IOException ex) {
@@ -2421,6 +2462,12 @@ public class Zip64SupportIT {
         } finally {
             try {
                 zos.destroy();
+                if (dir != null) {
+                    for (File file : dir.listFiles()) {
+                        file.delete();
+                    }
+                    dir.delete();
+                }
             } finally {
                 if (os != null) {
                     os.close();


[commons-compress] 01/04: COMPRESS-477 : add Zip64 support for split zip

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git

commit b4fd49a959cc58db476e1c79f25df1728c7f22b8
Author: Lee <pe...@gmail.com>
AuthorDate: Fri Dec 27 20:07:47 2019 +0800

    COMPRESS-477 : add Zip64 support for split zip
---
 .../archivers/zip/Zip64RequiredException.java      | 12 +++
 .../archivers/zip/ZipArchiveOutputStream.java      | 95 +++++++++++++++++++---
 2 files changed, 94 insertions(+), 13 deletions(-)

diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/Zip64RequiredException.java b/src/main/java/org/apache/commons/compress/archivers/zip/Zip64RequiredException.java
index 625ea64..eb11d06 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/Zip64RequiredException.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/Zip64RequiredException.java
@@ -37,6 +37,18 @@ public class Zip64RequiredException extends ZipException {
         return ze.getName() + "'s size exceeds the limit of 4GByte.";
     }
 
+    static final String NUMBER_OF_THIS_DISK_TOO_BIG_MESSAGE =
+        "Number of the disk of End Of Central Directory exceeds the limmit of 65535.";
+
+    static final String NUMBER_OF_THE_DISK_OF_CENTRAL_DIRECTORY_TOO_BIG_MESSAGE =
+        "Number of the disk with the start of Central Directory exceeds the limmit of 65535.";
+
+    static final String TOO_MANY_ENTRIES_ON_THIS_DISK_MESSAGE =
+        "Number of entries on this disk exceeds the limmit of 65535.";
+
+    static final String SIZE_OF_CENTRAL_DIRECTORY_TOO_BIG_MESSAGE =
+        "The size of the entire central directory exceeds the limit of 4GByte.";
+
     static final String ARCHIVE_TOO_BIG_MESSAGE =
         "Archive's size exceeds the limit of 4GByte.";
 
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
index 345a5ad..759aa75 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
@@ -1297,6 +1297,7 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
                 || ze.getCompressedSize() >= ZIP64_MAGIC
                 || ze.getSize() >= ZIP64_MAGIC
                 || entryMetaData.offset >= ZIP64_MAGIC
+                || ze.getDiskNumberStart() >= ZIP64_MAGIC_SHORT
                 || zip64Mode == Zip64Mode.Always;
 
         if (needsZip64Extra && zip64Mode == Zip64Mode.Never) {
@@ -1392,7 +1393,11 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
 
         // disk number start
         if(isSplitZip) {
-            putShort((int) ze.getDiskNumberStart(), buf, CFH_DISK_NUMBER_OFFSET);
+            if (ze.getDiskNumberStart() >= ZIP64_MAGIC_SHORT || zip64Mode == Zip64Mode.Always) {
+                putShort(ZIP64_MAGIC_SHORT, buf, CFH_DISK_NUMBER_OFFSET);
+            } else {
+                putShort((int) ze.getDiskNumberStart(), buf, CFH_DISK_NUMBER_OFFSET);
+            }
         } else {
             System.arraycopy(ZERO, 0, buf, CFH_DISK_NUMBER_OFFSET, SHORT);
         }
@@ -1444,6 +1449,9 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
             if (lfhOffset >= ZIP64_MAGIC || zip64Mode == Zip64Mode.Always) {
                 z64.setRelativeHeaderOffset(new ZipEightByteInteger(lfhOffset));
             }
+            if (ze.getDiskNumberStart() >= ZIP64_MAGIC_SHORT || zip64Mode == Zip64Mode.Always) {
+                z64.setDiskStartNumber(new ZipLong(ze.getDiskNumberStart()));
+            }
             ze.setExtra();
         }
     }
@@ -1460,6 +1468,8 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
             ((ZipSplitOutputStream)this.out).prepareToWriteUnsplittableContent(eocdLength);
         }
 
+        validateIfZip64IsNeededInEOCD();
+
         writeCounted(EOCD_SIG);
 
         // number of this disk
@@ -1474,15 +1484,6 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
 
         // number of entries
         final int numberOfEntries = entries.size();
-        if (numberOfEntries > ZIP64_MAGIC_SHORT
-            && zip64Mode == Zip64Mode.Never) {
-            throw new Zip64RequiredException(Zip64RequiredException
-                                             .TOO_MANY_ENTRIES_MESSAGE);
-        }
-        if (cdOffset > ZIP64_MAGIC && zip64Mode == Zip64Mode.Never) {
-            throw new Zip64RequiredException(Zip64RequiredException
-                                             .ARCHIVE_TOO_BIG_MESSAGE);
-        }
 
         // total number of entries in the central directory on this disk
         int numOfEntriesOnThisDisk = numberOfCDInDiskData.get(numberOfThisDisk) == null ? 0 : numberOfCDInDiskData.get(numberOfThisDisk);
@@ -1507,6 +1508,54 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
     }
 
     /**
+     * If the Zip64 mode is set to never, then all the data in End Of Central Directory
+     * should not exceed their limits.
+     * @throws Zip64RequiredException if Zip64 is actually needed
+     */
+    private void validateIfZip64IsNeededInEOCD() throws Zip64RequiredException {
+        // exception will only be thrown if the Zip64 mode is never while Zip64 is actually needed
+        if (zip64Mode != Zip64Mode.Never) {
+            return;
+        }
+
+        long numberOfThisDisk = 0;
+        if (isSplitZip) {
+            numberOfThisDisk = ((ZipSplitOutputStream)this.out).getCurrentSplitSegmentIndex();
+        }
+        if (numberOfThisDisk >= ZIP64_MAGIC_SHORT) {
+            throw new Zip64RequiredException(Zip64RequiredException
+                    .NUMBER_OF_THIS_DISK_TOO_BIG_MESSAGE);
+        }
+
+        if (cdDiskNumberStart >= ZIP64_MAGIC_SHORT) {
+            throw new Zip64RequiredException(Zip64RequiredException
+                    .NUMBER_OF_THE_DISK_OF_CENTRAL_DIRECTORY_TOO_BIG_MESSAGE);
+        }
+
+        final int numOfEntriesOnThisDisk = numberOfCDInDiskData.get(numberOfThisDisk) == null ? 0 : numberOfCDInDiskData.get(numberOfThisDisk);
+        if (numOfEntriesOnThisDisk >= ZIP64_MAGIC_SHORT) {
+            throw new Zip64RequiredException(Zip64RequiredException
+                    .TOO_MANY_ENTRIES_ON_THIS_DISK_MESSAGE);
+        }
+
+        // number of entries
+        if (entries.size() >= ZIP64_MAGIC_SHORT) {
+            throw new Zip64RequiredException(Zip64RequiredException
+                    .TOO_MANY_ENTRIES_MESSAGE);
+        }
+
+        if (cdLength >= ZIP64_MAGIC) {
+            throw new Zip64RequiredException(Zip64RequiredException
+                    .SIZE_OF_CENTRAL_DIRECTORY_TOO_BIG_MESSAGE);
+        }
+
+        if (cdOffset >= ZIP64_MAGIC) {
+            throw new Zip64RequiredException(Zip64RequiredException
+                    .ARCHIVE_TOO_BIG_MESSAGE);
+        }
+    }
+
+    /**
      * Writes the &quot;ZIP64 End of central dir record&quot; and
      * &quot;ZIP64 End of central dir locator&quot;.
      * @throws IOException on error
@@ -1517,9 +1566,7 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
             return;
         }
 
-        if (!hasUsedZip64
-            && (cdOffset >= ZIP64_MAGIC || cdLength >= ZIP64_MAGIC
-                || entries.size() >= ZIP64_MAGIC_SHORT)) {
+        if (!hasUsedZip64 && shouldUseZip64EOCD()) {
             // actually "will use"
             hasUsedZip64 = true;
         }
@@ -1614,6 +1661,28 @@ public class ZipArchiveOutputStream extends ArchiveOutputStream {
     }
 
     /**
+     * 4.4.1.4  If one of the fields in the end of central directory
+     * record is too small to hold required data, the field SHOULD be
+     * set to -1 (0xFFFF or 0xFFFFFFFF) and the ZIP64 format record
+     * SHOULD be created.
+     * @return true if zip64 End Of Central Directory is needed
+     */
+    private boolean shouldUseZip64EOCD() {
+        int numberOfThisDisk = 0;
+        if(isSplitZip) {
+            numberOfThisDisk = ((ZipSplitOutputStream)this.out).getCurrentSplitSegmentIndex();
+        }
+        int numOfEntriesOnThisDisk = numberOfCDInDiskData.get(numberOfThisDisk) == null ? 0 : numberOfCDInDiskData.get(numberOfThisDisk);
+        return numberOfThisDisk >= ZIP64_MAGIC_SHORT            /* number of this disk */
+                || cdDiskNumberStart >= ZIP64_MAGIC_SHORT       /* number of the disk with the start of the central directory */
+                || numOfEntriesOnThisDisk >= ZIP64_MAGIC_SHORT  /* total number of entries in the central directory on this disk */
+                || entries.size() >= ZIP64_MAGIC_SHORT          /* total number of entries in the central directory */
+                || cdLength >= ZIP64_MAGIC                      /* size of the central directory */
+                || cdOffset >= ZIP64_MAGIC;                     /* offset of start of central directory with respect to
+                                                                the starting disk number */
+    }
+
+    /**
      * Write bytes to output or random access file.
      * @param data the byte array to write
      * @throws IOException on error


[commons-compress] 04/04: Merge branch 'COMPRESS-477-zip64' of https://github.com/PeterAlfreadLee/commons-compress into PeterAlfreadLee-COMPRESS-477-zip64

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git

commit 2dbdb7b8278e4e9df0a3754b7335325e6e275155
Merge: 9e0d5a7 27fd203
Author: Stefan Bodewig <bo...@apache.org>
AuthorDate: Tue Jan 21 18:14:50 2020 +0100

    Merge branch 'COMPRESS-477-zip64' of https://github.com/PeterAlfreadLee/commons-compress into PeterAlfreadLee-COMPRESS-477-zip64

 .../archivers/zip/Zip64RequiredException.java      | 12 +++
 .../archivers/zip/ZipArchiveOutputStream.java      | 95 +++++++++++++++++++---
 .../compress/archivers/zip/Zip64SupportIT.java     | 87 +++++++++++++++-----
 3 files changed, 161 insertions(+), 33 deletions(-)


[commons-compress] 02/04: Merge branch 'master' of https://github.com/apache/commons-compress into COMPRESS-477-zip64

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bodewig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git

commit 13cd268a4c99045a32a30ef5dc3d63ea04477d18
Merge: b4fd49a f161254
Author: Lee <pe...@gmail.com>
AuthorDate: Tue Jan 7 21:19:55 2020 +0800

    Merge branch 'master' of https://github.com/apache/commons-compress into COMPRESS-477-zip64

 .travis.yml                                        |   4 +-
 NOTICE.txt                                         |   2 +-
 RELEASE-NOTES.txt                                  |   3 +
 src/changes/changes.xml                            |  19 +-
 .../compress/archivers/tar/TarArchiveEntry.java    |  56 ++-
 .../archivers/tar/TarArchiveInputStream.java       | 415 +++++++++++++++++++--
 .../archivers/tar/TarArchiveSparseEntry.java       |  22 ++
 .../archivers/tar/TarArchiveStructSparse.java      |  82 ++++
 .../compress/archivers/tar/TarConstants.java       |  24 ++
 .../commons/compress/archivers/tar/TarUtils.java   |  19 +-
 .../archivers/zip/ZipArchiveOutputStream.java      |  11 +-
 .../zip/ZipSplitReadOnlySeekableByteChannel.java   |   6 +-
 .../commons/compress/utils/BoundedInputStream.java |  12 +
 .../utils/MultiReadOnlySeekableByteChannel.java    |  13 +
 .../utils/SeekableInMemoryByteChannel.java         |  40 +-
 src/site/xdoc/index.xml                            |   2 +
 src/site/xdoc/limitations.xml                      |  12 +-
 src/site/xdoc/zip.xml                              |  55 ++-
 .../org/apache/commons/compress/OsgiITest.java     |  23 ++
 .../compress/archivers/tar/SparseFilesTest.java    | 182 ++++++++-
 .../archivers/tar/TarArchiveInputStreamTest.java   |  10 +-
 .../compress/archivers/tar/TarUtilsTest.java       |  12 +
 .../MultiReadOnlySeekableByteChannelTest.java      |  93 +++++
 .../utils/SeekableInMemoryByteChannelTest.java     | 222 ++++++++++-
 src/test/resources/oldgnu_extended_sparse.tar      | Bin 0 -> 10240 bytes
 25 files changed, 1270 insertions(+), 69 deletions(-)

diff --cc src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
index 759aa75,0ad4f8b..f630036
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
@@@ -1484,9 -1474,20 +1484,11 @@@ public class ZipArchiveOutputStream ext
  
          // number of entries
          final int numberOfEntries = entries.size();
 -        if (numberOfEntries > ZIP64_MAGIC_SHORT
 -            && zip64Mode == Zip64Mode.Never) {
 -            throw new Zip64RequiredException(Zip64RequiredException
 -                                             .TOO_MANY_ENTRIES_MESSAGE);
 -        }
 -        if (cdOffset > ZIP64_MAGIC && zip64Mode == Zip64Mode.Never) {
 -            throw new Zip64RequiredException(Zip64RequiredException
 -                                             .ARCHIVE_TOO_BIG_MESSAGE);
 -        }
  
          // total number of entries in the central directory on this disk
-         int numOfEntriesOnThisDisk = numberOfCDInDiskData.get(numberOfThisDisk) == null ? 0 : numberOfCDInDiskData.get(numberOfThisDisk);
+         int numOfEntriesOnThisDisk = isSplitZip
+             ? (numberOfCDInDiskData.get(numberOfThisDisk) == null ? 0 : numberOfCDInDiskData.get(numberOfThisDisk))
+             : numberOfEntries;
          final byte[] numOfEntriesOnThisDiskData = ZipShort
                  .getBytes(Math.min(numOfEntriesOnThisDisk, ZIP64_MAGIC_SHORT));
          writeCounted(numOfEntriesOnThisDiskData);