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

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

commit 4766e284ac4be66154f13aa75bbfa83c2f779f68
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Mon Jan 15 11:01:43 2024 -0500

    Sort members
---
 .../zip/FileRandomAccessOutputStream.java          |  24 +-
 .../archivers/zip/RandomAccessOutputStream.java    |  24 +-
 .../SeekableChannelRandomAccessOutputStream.java   |  14 +-
 .../compress/archivers/zip/ZipEncodingHelper.java  |   8 +-
 .../commons/compress/archivers/zip/ZipFile.java    | 300 ++++++++++-----------
 .../archivers/zip/ZipSplitOutputStream.java        |  54 ++--
 .../zip/ZipSplitReadOnlySeekableByteChannel.java   |  22 +-
 .../apache/commons/compress/archivers/ZipTest.java | 118 ++++----
 .../archivers/cpio/CpioArchiveInputStreamTest.java |  16 +-
 .../archivers/zip/ZipArchiveOutputStreamTest.java  |  12 +-
 .../zip/ZipFileIgnoringLocalFileHeaderTest.java    |   8 +-
 .../FramedSnappyCompressorInputStreamTest.java     |  74 ++---
 12 files changed, 337 insertions(+), 337 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/FileRandomAccessOutputStream.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/FileRandomAccessOutputStream.java
index 8a431c4b5..6ec8ea9ea 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/FileRandomAccessOutputStream.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/FileRandomAccessOutputStream.java
@@ -33,6 +33,10 @@ class FileRandomAccessOutputStream extends 
RandomAccessOutputStream {
 
     private long position;
 
+    FileRandomAccessOutputStream(final FileChannel channel) throws IOException 
{
+        this.channel = channel;
+    }
+
     FileRandomAccessOutputStream(final Path file) throws IOException {
         this(file, StandardOpenOption.CREATE, 
StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
     }
@@ -41,18 +45,13 @@ class FileRandomAccessOutputStream extends 
RandomAccessOutputStream {
         this(FileChannel.open(file, options));
     }
 
-    FileRandomAccessOutputStream(final FileChannel channel) throws IOException 
{
-        this.channel = channel;
-    }
-
     FileChannel channel() {
         return channel;
     }
 
     @Override
-    public synchronized void write(final byte[] b, final int off, final int 
len) throws IOException {
-        ZipIoUtil.writeFully(this.channel, ByteBuffer.wrap(b, off, len));
-        position += len;
+    public void close() throws IOException {
+        channel.close();
     }
 
     @Override
@@ -60,6 +59,12 @@ class FileRandomAccessOutputStream extends 
RandomAccessOutputStream {
         return position;
     }
 
+    @Override
+    public synchronized void write(final byte[] b, final int off, final int 
len) throws IOException {
+        ZipIoUtil.writeFully(this.channel, ByteBuffer.wrap(b, off, len));
+        position += len;
+    }
+
     @Override
     public void writeFullyAt(final byte[] b, final int off, final int len, 
final long atPosition) throws IOException {
         ByteBuffer buf = ByteBuffer.wrap(b, off, len);
@@ -71,9 +76,4 @@ class FileRandomAccessOutputStream extends 
RandomAccessOutputStream {
             currentPos += written;
         }
     }
-
-    @Override
-    public void close() throws IOException {
-        channel.close();
-    }
 }
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/RandomAccessOutputStream.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/RandomAccessOutputStream.java
index 87bfd5913..d0f0aed4c 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/RandomAccessOutputStream.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/RandomAccessOutputStream.java
@@ -33,6 +33,11 @@ abstract class RandomAccessOutputStream extends OutputStream 
{
      */
     public abstract long position() throws IOException;
 
+    @Override
+    public void write(final int b) throws IOException {
+        write(new byte[]{ (byte) b });
+    }
+
     /**
      * Writes given data to specific position.
      *
@@ -40,12 +45,14 @@ abstract class RandomAccessOutputStream extends 
OutputStream {
      *      position in the stream
      * @param b
      *      data to write
+     * @param off
+     *      offset of the start of data in param b
+     * @param len
+     *      the length of data to write
      * @throws IOException
      *      when write fails.
      */
-    public void writeFullyAt(final byte[] b, final long position) throws 
IOException {
-        writeFullyAt(b, 0, b.length, position);
-    }
+    abstract void writeFullyAt(byte[] b, int off, int len, long position) 
throws IOException;
 
     /**
      * Writes given data to specific position.
@@ -54,17 +61,10 @@ abstract class RandomAccessOutputStream extends 
OutputStream {
      *      position in the stream
      * @param b
      *      data to write
-     * @param off
-     *      offset of the start of data in param b
-     * @param len
-     *      the length of data to write
      * @throws IOException
      *      when write fails.
      */
-    abstract void writeFullyAt(byte[] b, int off, int len, long position) 
throws IOException;
-
-    @Override
-    public void write(final int b) throws IOException {
-        write(new byte[]{ (byte) b });
+    public void writeFullyAt(final byte[] b, final long position) throws 
IOException {
+        writeFullyAt(b, 0, b.length, position);
     }
 }
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/SeekableChannelRandomAccessOutputStream.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/SeekableChannelRandomAccessOutputStream.java
index accad6879..473e9b2f5 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/SeekableChannelRandomAccessOutputStream.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/SeekableChannelRandomAccessOutputStream.java
@@ -35,8 +35,8 @@ class SeekableChannelRandomAccessOutputStream extends 
RandomAccessOutputStream {
     }
 
     @Override
-    public synchronized void write(final byte[] b, final int off, final int 
len) throws IOException {
-        ZipIoUtil.writeFully(this.channel, ByteBuffer.wrap(b, off, len));
+    public synchronized void close() throws IOException {
+        channel.close();
     }
 
     @Override
@@ -44,6 +44,11 @@ class SeekableChannelRandomAccessOutputStream extends 
RandomAccessOutputStream {
         return channel.position();
     }
 
+    @Override
+    public synchronized void write(final byte[] b, final int off, final int 
len) throws IOException {
+        ZipIoUtil.writeFully(this.channel, ByteBuffer.wrap(b, off, len));
+    }
+
     @Override
     public synchronized void writeFullyAt(final byte[] b, final int off, final 
int len, final long position) throws IOException {
         long saved = channel.position();
@@ -54,9 +59,4 @@ class SeekableChannelRandomAccessOutputStream extends 
RandomAccessOutputStream {
             channel.position(saved);
         }
     }
-
-    @Override
-    public synchronized void close() throws IOException {
-        channel.close();
-    }
 }
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java
index c73476ed8..e2b595e33 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipEncodingHelper.java
@@ -90,10 +90,6 @@ public abstract class ZipEncodingHelper {
         return isUTF8Alias(Charsets.toCharset(charset).name());
     }
 
-    private static boolean isUTF8Alias(final String actual) {
-        return UTF_8.name().equalsIgnoreCase(actual) || 
UTF_8.aliases().stream().anyMatch(alias -> alias.equalsIgnoreCase(actual));
-    }
-
     /**
      * Tests whether a given encoding is UTF-8. If the given name is null, 
then check the platform's default encoding.
      *
@@ -102,4 +98,8 @@ public abstract class ZipEncodingHelper {
     static boolean isUTF8(final String charsetName) {
         return isUTF8Alias(charsetName != null ? charsetName : 
Charset.defaultCharset().name());
     }
+
+    private static boolean isUTF8Alias(final String actual) {
+        return UTF_8.name().equalsIgnoreCase(actual) || 
UTF_8.aliases().stream().anyMatch(alias -> alias.equalsIgnoreCase(actual));
+    }
 }
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
index 3337308fd..dedcf0bfb 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
@@ -175,6 +175,19 @@ public class ZipFile implements Closeable {
             return this;
         }
 
+        /**
+         * Sets max number of multi archive disks, default is 1 (no multi 
archive).
+         *
+         * @param maxNumberOfDisks
+         *      max number of multi archive disks
+         *
+         * @return this instance
+         */
+        public Builder setMaxNumberOfDisks(final long maxNumberOfDisks) {
+            this.maxNumberOfDisks = maxNumberOfDisks;
+            return this;
+        }
+
         /**
          * The actual channel, overrides any other input aspects like a File, 
Path, and so on.
          *
@@ -197,19 +210,6 @@ public class ZipFile implements Closeable {
             return this;
         }
 
-        /**
-         * Sets max number of multi archive disks, default is 1 (no multi 
archive).
-         *
-         * @param maxNumberOfDisks
-         *      max number of multi archive disks
-         *
-         * @return this instance
-         */
-        public Builder setMaxNumberOfDisks(final long maxNumberOfDisks) {
-            this.maxNumberOfDisks = maxNumberOfDisks;
-            return this;
-        }
-
     }
 
     /**
@@ -497,6 +497,142 @@ public class ZipFile implements Closeable {
         return Files.newByteChannel(path, READ);
     }
 
+    private static SeekableByteChannel openZipChannel(Path path, long 
maxNumberOfDisks, OpenOption[] openOptions) throws IOException {
+        FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
+        List<FileChannel> channels = new ArrayList<>();
+        try {
+            boolean is64 = positionAtEndOfCentralDirectoryRecord(channel);
+            long numberOfDisks;
+            if (is64) {
+                channel.position(channel.position() + ZipConstants.WORD + 
ZipConstants.WORD + ZipConstants.DWORD);
+                ByteBuffer buf = ByteBuffer.allocate(ZipConstants.WORD);
+                buf.order(ByteOrder.LITTLE_ENDIAN);
+                IOUtils.readFully(channel, buf);
+                buf.flip();
+                numberOfDisks = buf.getInt() & 0xffffffffL;
+            } else {
+                channel.position(channel.position() + ZipConstants.WORD);
+                ByteBuffer buf = ByteBuffer.allocate(ZipConstants.SHORT);
+                buf.order(ByteOrder.LITTLE_ENDIAN);
+                IOUtils.readFully(channel, buf);
+                buf.flip();
+                numberOfDisks = (buf.getShort() & 0xffff) + 1;
+            }
+            if (numberOfDisks > Math.min(maxNumberOfDisks, Integer.MAX_VALUE)) 
{
+                throw new IOException("Too many disks for zip archive, max=" +
+                        Math.min(maxNumberOfDisks, Integer.MAX_VALUE) + " 
actual=" + numberOfDisks);
+            }
+
+            if (numberOfDisks <= 1) {
+                return channel;
+            }
+            channel.close();
+
+            Path parent = path.getParent();
+            String basename = 
FilenameUtils.removeExtension(path.getFileName().toString());
+
+            return ZipSplitReadOnlySeekableByteChannel.forPaths(
+                    IntStream.range(0, (int) numberOfDisks)
+                            .mapToObj(i -> {
+                                if (i == numberOfDisks - 1) {
+                                    return path;
+                                }
+                                Path lowercase = 
parent.resolve(String.format("%s.z%02d", basename, i + 1));
+                                if (Files.exists(lowercase)) {
+                                    return lowercase;
+                                }
+                                Path uppercase = 
parent.resolve(String.format("%s.Z%02d", basename, i + 1));
+                                if (Files.exists(uppercase)) {
+                                    return uppercase;
+                                }
+                                return lowercase;
+                            })
+                            .collect(Collectors.toList()),
+                    openOptions
+            );
+        } catch (Throwable ex) {
+            IOUtils.closeQuietly(channel);
+            channels.forEach(IOUtils::closeQuietly);
+            throw ex;
+        }
+    }
+
+    /**
+     * Searches for the and positions the stream at the start of the &quot;End 
of central dir record&quot;.
+     *
+     * @return
+     *      true if it's Zip64 end of central directory or false if it's Zip32
+     */
+    private static boolean 
positionAtEndOfCentralDirectoryRecord(SeekableByteChannel channel) throws 
IOException {
+        final boolean found = tryToLocateSignature(channel, MIN_EOCD_SIZE, 
MAX_EOCD_SIZE, ZipArchiveOutputStream.EOCD_SIG);
+        if (!found) {
+            throw new ZipException("Archive is not a ZIP archive");
+        }
+        boolean found64 = false;
+        long position = channel.position();
+        if (position > ZIP64_EOCDL_LENGTH) {
+            ByteBuffer wordBuf = ByteBuffer.allocate(4);
+            channel.position(channel.position() - ZIP64_EOCDL_LENGTH);
+            wordBuf.rewind();
+            IOUtils.readFully(channel, wordBuf);
+            wordBuf.flip();
+            found64 = 
wordBuf.equals(ByteBuffer.wrap(ZipArchiveOutputStream.ZIP64_EOCD_LOC_SIG));
+            if (!found64) {
+                channel.position(position);
+            } else {
+                channel.position(channel.position() - ZipConstants.WORD);
+            }
+        }
+
+        return found64;
+    }
+
+    /**
+     * Searches the archive backwards from minDistance to maxDistance for the 
given signature, positions the RandomaccessFile right at the signature if it has
+     * been found.
+     */
+    private static boolean tryToLocateSignature(
+            final SeekableByteChannel channel,
+            final long minDistanceFromEnd,
+            final long maxDistanceFromEnd,
+            final byte[] sig
+    ) throws IOException {
+        ByteBuffer wordBuf = ByteBuffer.allocate(ZipConstants.WORD);
+        boolean found = false;
+        long off = channel.size() - minDistanceFromEnd;
+        final long stopSearching = Math.max(0L, channel.size() - 
maxDistanceFromEnd);
+        if (off >= 0) {
+            for (; off >= stopSearching; off--) {
+                channel.position(off);
+                try {
+                    wordBuf.rewind();
+                    IOUtils.readFully(channel, wordBuf);
+                    wordBuf.flip();
+                } catch (final EOFException ex) { // NOSONAR
+                    break;
+                }
+                int curr = wordBuf.get();
+                if (curr == sig[POS_0]) {
+                    curr = wordBuf.get();
+                    if (curr == sig[POS_1]) {
+                        curr = wordBuf.get();
+                        if (curr == sig[POS_2]) {
+                            curr = wordBuf.get();
+                            if (curr == sig[POS_3]) {
+                                found = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (found) {
+            channel.position(off);
+        }
+        return found;
+    }
+
     /**
      * List of entries in the order they appear inside the central directory.
      */
@@ -558,13 +694,13 @@ public class ZipFile implements Closeable {
 
     private final ByteBuffer shortBbuf = ByteBuffer.wrap(shortBuf);
 
+
     private long centralDirectoryStartDiskNumber, 
centralDirectoryStartRelativeOffset;
 
     private long centralDirectoryStartOffset;
 
     private long firstLocalFileHeaderOffset;
 
-
     /**
      * Opens the given file for reading, assuming "UTF8" for file names.
      *
@@ -832,66 +968,6 @@ public class ZipFile implements Closeable {
         this(new File(name).toPath(), encoding, true);
     }
 
-    private static SeekableByteChannel openZipChannel(Path path, long 
maxNumberOfDisks, OpenOption[] openOptions) throws IOException {
-        FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
-        List<FileChannel> channels = new ArrayList<>();
-        try {
-            boolean is64 = positionAtEndOfCentralDirectoryRecord(channel);
-            long numberOfDisks;
-            if (is64) {
-                channel.position(channel.position() + ZipConstants.WORD + 
ZipConstants.WORD + ZipConstants.DWORD);
-                ByteBuffer buf = ByteBuffer.allocate(ZipConstants.WORD);
-                buf.order(ByteOrder.LITTLE_ENDIAN);
-                IOUtils.readFully(channel, buf);
-                buf.flip();
-                numberOfDisks = buf.getInt() & 0xffffffffL;
-            } else {
-                channel.position(channel.position() + ZipConstants.WORD);
-                ByteBuffer buf = ByteBuffer.allocate(ZipConstants.SHORT);
-                buf.order(ByteOrder.LITTLE_ENDIAN);
-                IOUtils.readFully(channel, buf);
-                buf.flip();
-                numberOfDisks = (buf.getShort() & 0xffff) + 1;
-            }
-            if (numberOfDisks > Math.min(maxNumberOfDisks, Integer.MAX_VALUE)) 
{
-                throw new IOException("Too many disks for zip archive, max=" +
-                        Math.min(maxNumberOfDisks, Integer.MAX_VALUE) + " 
actual=" + numberOfDisks);
-            }
-
-            if (numberOfDisks <= 1) {
-                return channel;
-            }
-            channel.close();
-
-            Path parent = path.getParent();
-            String basename = 
FilenameUtils.removeExtension(path.getFileName().toString());
-
-            return ZipSplitReadOnlySeekableByteChannel.forPaths(
-                    IntStream.range(0, (int) numberOfDisks)
-                            .mapToObj(i -> {
-                                if (i == numberOfDisks - 1) {
-                                    return path;
-                                }
-                                Path lowercase = 
parent.resolve(String.format("%s.z%02d", basename, i + 1));
-                                if (Files.exists(lowercase)) {
-                                    return lowercase;
-                                }
-                                Path uppercase = 
parent.resolve(String.format("%s.Z%02d", basename, i + 1));
-                                if (Files.exists(uppercase)) {
-                                    return uppercase;
-                                }
-                                return lowercase;
-                            })
-                            .collect(Collectors.toList()),
-                    openOptions
-            );
-        } catch (Throwable ex) {
-            IOUtils.closeQuietly(channel);
-            channels.forEach(IOUtils::closeQuietly);
-            throw ex;
-        }
-    }
-
     /**
      * Whether this class is able to read the given entry.
      * <p>
@@ -1327,36 +1403,6 @@ public class ZipFile implements Closeable {
         }
     }
 
-    /**
-     * Searches for the and positions the stream at the start of the &quot;End 
of central dir record&quot;.
-     *
-     * @return
-     *      true if it's Zip64 end of central directory or false if it's Zip32
-     */
-    private static boolean 
positionAtEndOfCentralDirectoryRecord(SeekableByteChannel channel) throws 
IOException {
-        final boolean found = tryToLocateSignature(channel, MIN_EOCD_SIZE, 
MAX_EOCD_SIZE, ZipArchiveOutputStream.EOCD_SIG);
-        if (!found) {
-            throw new ZipException("Archive is not a ZIP archive");
-        }
-        boolean found64 = false;
-        long position = channel.position();
-        if (position > ZIP64_EOCDL_LENGTH) {
-            ByteBuffer wordBuf = ByteBuffer.allocate(4);
-            channel.position(channel.position() - ZIP64_EOCDL_LENGTH);
-            wordBuf.rewind();
-            IOUtils.readFully(channel, wordBuf);
-            wordBuf.flip();
-            found64 = 
wordBuf.equals(ByteBuffer.wrap(ZipArchiveOutputStream.ZIP64_EOCD_LOC_SIG));
-            if (!found64) {
-                channel.position(position);
-            } else {
-                channel.position(channel.position() - ZipConstants.WORD);
-            }
-        }
-
-        return found64;
-    }
-
     /**
      * Reads an individual entry of the central directory, creates an 
ZipArchiveEntry from it and adds it to the global maps.
      *
@@ -1637,50 +1683,4 @@ public class ZipFile implements Closeable {
         IOUtils.readFully(archive, wordBbuf);
         return Arrays.equals(wordBuf, ZipArchiveOutputStream.LFH_SIG);
     }
-
-    /**
-     * Searches the archive backwards from minDistance to maxDistance for the 
given signature, positions the RandomaccessFile right at the signature if it has
-     * been found.
-     */
-    private static boolean tryToLocateSignature(
-            final SeekableByteChannel channel,
-            final long minDistanceFromEnd,
-            final long maxDistanceFromEnd,
-            final byte[] sig
-    ) throws IOException {
-        ByteBuffer wordBuf = ByteBuffer.allocate(ZipConstants.WORD);
-        boolean found = false;
-        long off = channel.size() - minDistanceFromEnd;
-        final long stopSearching = Math.max(0L, channel.size() - 
maxDistanceFromEnd);
-        if (off >= 0) {
-            for (; off >= stopSearching; off--) {
-                channel.position(off);
-                try {
-                    wordBuf.rewind();
-                    IOUtils.readFully(channel, wordBuf);
-                    wordBuf.flip();
-                } catch (final EOFException ex) { // NOSONAR
-                    break;
-                }
-                int curr = wordBuf.get();
-                if (curr == sig[POS_0]) {
-                    curr = wordBuf.get();
-                    if (curr == sig[POS_1]) {
-                        curr = wordBuf.get();
-                        if (curr == sig[POS_2]) {
-                            curr = wordBuf.get();
-                            if (curr == sig[POS_3]) {
-                                found = true;
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        if (found) {
-            channel.position(off);
-        }
-        return found;
-    }
 }
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitOutputStream.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitOutputStream.java
index 8d05ecfe5..a8a7a7938 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitOutputStream.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitOutputStream.java
@@ -99,6 +99,13 @@ final class ZipSplitOutputStream extends 
RandomAccessOutputStream {
         writeZipSplitSignature();
     }
 
+    public long calculateDiskPosition(long disk, long localOffset) throws 
IOException {
+        if (disk >= Integer.MAX_VALUE) {
+            throw new IOException("Disk number exceeded internal limits: 
limit=" + Integer.MAX_VALUE + " requested=" + disk);
+        }
+        return diskToPosition.get((int) disk) + localOffset;
+    }
+
     @Override
     public void close() throws IOException {
         if (!finished) {
@@ -130,23 +137,6 @@ final class ZipSplitOutputStream extends 
RandomAccessOutputStream {
         return newFile;
     }
 
-    private Path getSplitSegmentFilename(final Integer 
zipSplitSegmentSuffixIndex) throws IOException {
-        final int newZipSplitSegmentSuffixIndex = zipSplitSegmentSuffixIndex 
== null ? currentSplitSegmentIndex + 2 : zipSplitSegmentSuffixIndex;
-        final String baseName = FileNameUtils.getBaseName(zipFile);
-        String extension = ".z";
-        if (newZipSplitSegmentSuffixIndex <= 9) {
-            extension += "0" + newZipSplitSegmentSuffixIndex;
-        } else {
-            extension += newZipSplitSegmentSuffixIndex;
-        }
-
-        final Path parent = zipFile.getParent();
-        final String dir = Objects.nonNull(parent) ? 
parent.toAbsolutePath().toString() : ".";
-        final Path newFile = zipFile.getFileSystem().getPath(dir, baseName + 
extension);
-
-        return newFile;
-    }
-
 
     /**
      * The last ZIP split segment's suffix should be .zip
@@ -172,6 +162,23 @@ final class ZipSplitOutputStream extends 
RandomAccessOutputStream {
         return currentSplitSegmentIndex;
     }
 
+    private Path getSplitSegmentFilename(final Integer 
zipSplitSegmentSuffixIndex) throws IOException {
+        final int newZipSplitSegmentSuffixIndex = zipSplitSegmentSuffixIndex 
== null ? currentSplitSegmentIndex + 2 : zipSplitSegmentSuffixIndex;
+        final String baseName = FileNameUtils.getBaseName(zipFile);
+        String extension = ".z";
+        if (newZipSplitSegmentSuffixIndex <= 9) {
+            extension += "0" + newZipSplitSegmentSuffixIndex;
+        } else {
+            extension += newZipSplitSegmentSuffixIndex;
+        }
+
+        final Path parent = zipFile.getParent();
+        final String dir = Objects.nonNull(parent) ? 
parent.toAbsolutePath().toString() : ".";
+        final Path newFile = zipFile.getFileSystem().getPath(dir, baseName + 
extension);
+
+        return newFile;
+    }
+
     /**
      * Creates a new ZIP split segment and prepare to write to the new segment
      *
@@ -198,11 +205,9 @@ final class ZipSplitOutputStream extends 
RandomAccessOutputStream {
         this.positionToFiles.put(this.totalPosition, newFile);
     }
 
-    public long calculateDiskPosition(long disk, long localOffset) throws 
IOException {
-        if (disk >= Integer.MAX_VALUE) {
-            throw new IOException("Disk number exceeded internal limits: 
limit=" + Integer.MAX_VALUE + " requested=" + disk);
-        }
-        return diskToPosition.get((int) disk) + localOffset;
+    @Override
+    public long position() {
+        return totalPosition;
     }
 
     /**
@@ -266,11 +271,6 @@ final class ZipSplitOutputStream extends 
RandomAccessOutputStream {
         write(singleByte);
     }
 
-    @Override
-    public long position() {
-        return totalPosition;
-    }
-
     @Override
     public void writeFullyAt(final byte[] b, final int off, final int len, 
final long atPosition) throws IOException {
         long remainingPosition = atPosition;
diff --git 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java
 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java
index 20d7b8bed..14913ea7b 100644
--- 
a/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java
+++ 
b/src/main/java/org/apache/commons/compress/archivers/zip/ZipSplitReadOnlySeekableByteChannel.java
@@ -203,8 +203,15 @@ public class ZipSplitReadOnlySeekableByteChannel extends 
MultiReadOnlySeekableBy
      * @throws IOException          if the first channel doesn't seem to hold 
the beginning of a split archive
      * @since 1.22
      */
-    public static SeekableByteChannel forPaths(final Path... paths) throws 
IOException {
-        return forPaths(Arrays.asList(paths), new OpenOption[]{ 
StandardOpenOption.READ });
+    public static SeekableByteChannel forPaths(final List<Path> paths, 
OpenOption[] openOptions) throws IOException {
+        final List<SeekableByteChannel> channels = new ArrayList<>();
+        for (final Path path : Objects.requireNonNull(paths, "paths must not 
be null")) {
+            channels.add(Files.newByteChannel(path, openOptions));
+        }
+        if (channels.size() == 1) {
+            return channels.get(0);
+        }
+        return new ZipSplitReadOnlySeekableByteChannel(channels);
     }
 
     /**
@@ -218,15 +225,8 @@ public class ZipSplitReadOnlySeekableByteChannel extends 
MultiReadOnlySeekableBy
      * @throws IOException          if the first channel doesn't seem to hold 
the beginning of a split archive
      * @since 1.22
      */
-    public static SeekableByteChannel forPaths(final List<Path> paths, 
OpenOption[] openOptions) throws IOException {
-        final List<SeekableByteChannel> channels = new ArrayList<>();
-        for (final Path path : Objects.requireNonNull(paths, "paths must not 
be null")) {
-            channels.add(Files.newByteChannel(path, openOptions));
-        }
-        if (channels.size() == 1) {
-            return channels.get(0);
-        }
-        return new ZipSplitReadOnlySeekableByteChannel(channels);
+    public static SeekableByteChannel forPaths(final Path... paths) throws 
IOException {
+        return forPaths(Arrays.asList(paths), new OpenOption[]{ 
StandardOpenOption.READ });
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/compress/archivers/ZipTest.java 
b/src/test/java/org/apache/commons/compress/archivers/ZipTest.java
index c48e7dcd5..76c145c47 100644
--- a/src/test/java/org/apache/commons/compress/archivers/ZipTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/ZipTest.java
@@ -136,14 +136,6 @@ public final class ZipTest extends AbstractTest {
         return result;
     }
 
-    private byte[] createArtificialData(int size) {
-        final ByteArrayOutputStream output = new ByteArrayOutputStream();
-        for (int i = 0; i < size; i += 1) {
-            output.write((byte) ((i & 1) == 0 ? (i / 2 % 256) : (i / 2 / 
256)));
-        }
-        return output.toByteArray();
-    }
-
     private void createArchiveEntry(final String payload, final 
ZipArchiveOutputStream zos, final String name) throws IOException {
         final ZipArchiveEntry in = new ZipArchiveEntry(name);
         zos.putArchiveEntry(in);
@@ -152,6 +144,14 @@ public final class ZipTest extends AbstractTest {
         zos.closeArchiveEntry();
     }
 
+    private byte[] createArtificialData(int size) {
+        final ByteArrayOutputStream output = new ByteArrayOutputStream();
+        for (int i = 0; i < size; i += 1) {
+            output.write((byte) ((i & 1) == 0 ? (i / 2 % 256) : (i / 2 / 
256)));
+        }
+        return output.toByteArray();
+    }
+
     private ZipArchiveOutputStream createFirstEntry(final 
ZipArchiveOutputStream zos) throws IOException {
         createArchiveEntry(first_payload, zos, "file1.txt");
         return zos;
@@ -233,32 +233,6 @@ public final class ZipTest extends AbstractTest {
         list.add(Arrays.asList(t, b));
     }
 
-    @Test
-    public void testBuildSplitZipTest() throws IOException {
-        final File directoryToZip = getFilesToZip();
-        createTestSplitZipSegments();
-
-        final File lastFile = newTempFile("splitZip.zip");
-        try (SeekableByteChannel channel = 
ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
-                InputStream inputStream = Channels.newInputStream(channel);
-                ZipArchiveInputStream splitInputStream = new 
ZipArchiveInputStream(inputStream, UTF_8.toString(), true, false, true)) {
-
-            ArchiveEntry entry;
-            final int filesNum = countNonDirectories(directoryToZip);
-            int filesCount = 0;
-            while ((entry = splitInputStream.getNextEntry()) != null) {
-                if (entry.isDirectory()) {
-                    continue;
-                }
-                // compare all files one by one
-                assertArrayEquals(IOUtils.toByteArray(splitInputStream), 
Files.readAllBytes(Paths.get(entry.getName())));
-                filesCount++;
-            }
-            // and the number of files should equal
-            assertEquals(filesCount, filesNum);
-        }
-    }
-
     /**
      * Tests split archive with 32-bit limit, both STORED and DEFLATED.
      */
@@ -322,6 +296,37 @@ public final class ZipTest extends AbstractTest {
         }
     }
 
+    /**
+     * Tests split archive with 32-bit limit, with end of central directory 
skipping lack of space in segment.
+     */
+    @Test
+    public void testBuildSplitZip32_endOfCentralDirectorySkipBoundary() throws 
IOException {
+        final File outputZipFile = newTempFile("artificialSplitZip.zip");
+        final long splitSize = 64 * 1024L; /* 64 KB */
+        // 4 is PK signature, 36 is size of header + local file header,
+        // 36 is length of central directory entry
+        // 1 is remaining byte in first archive, this should be skipped
+        byte[] data1 = createArtificialData(64 * 1024 - 4 - 36 - 52 - 1);
+        try (ZipArchiveOutputStream zipArchiveOutputStream = new 
ZipArchiveOutputStream(outputZipFile, splitSize)) {
+            zipArchiveOutputStream.setUseZip64(Zip64Mode.Never);
+            ZipArchiveEntry ze1 = new ZipArchiveEntry("file01");
+            ze1.setMethod(ZipEntry.STORED);
+            zipArchiveOutputStream.putArchiveEntry(ze1);
+            zipArchiveOutputStream.write(data1);
+            zipArchiveOutputStream.closeArchiveEntry();
+        }
+
+        assertEquals(64 * 1024L - 1, 
Files.size(outputZipFile.toPath().getParent().resolve("artificialSplitZip.z01")));
+
+        try (ZipFile zipFile = ZipFile.builder()
+                .setPath(outputZipFile.toPath())
+                .setMaxNumberOfDisks(Integer.MAX_VALUE)
+                .get()
+        ) {
+            assertArrayEquals(data1, 
IOUtils.toByteArray(zipFile.getInputStream(zipFile.getEntry("file01"))));
+        }
+    }
+
     /**
      * Tests split archive with 32-bit limit, with file local headers crossing 
segment boundaries.
      */
@@ -377,34 +382,29 @@ public final class ZipTest extends AbstractTest {
         }
     }
 
-    /**
-     * Tests split archive with 32-bit limit, with end of central directory 
skipping lack of space in segment.
-     */
     @Test
-    public void testBuildSplitZip32_endOfCentralDirectorySkipBoundary() throws 
IOException {
-        final File outputZipFile = newTempFile("artificialSplitZip.zip");
-        final long splitSize = 64 * 1024L; /* 64 KB */
-        // 4 is PK signature, 36 is size of header + local file header,
-        // 36 is length of central directory entry
-        // 1 is remaining byte in first archive, this should be skipped
-        byte[] data1 = createArtificialData(64 * 1024 - 4 - 36 - 52 - 1);
-        try (ZipArchiveOutputStream zipArchiveOutputStream = new 
ZipArchiveOutputStream(outputZipFile, splitSize)) {
-            zipArchiveOutputStream.setUseZip64(Zip64Mode.Never);
-            ZipArchiveEntry ze1 = new ZipArchiveEntry("file01");
-            ze1.setMethod(ZipEntry.STORED);
-            zipArchiveOutputStream.putArchiveEntry(ze1);
-            zipArchiveOutputStream.write(data1);
-            zipArchiveOutputStream.closeArchiveEntry();
-        }
+    public void testBuildSplitZipTest() throws IOException {
+        final File directoryToZip = getFilesToZip();
+        createTestSplitZipSegments();
 
-        assertEquals(64 * 1024L - 1, 
Files.size(outputZipFile.toPath().getParent().resolve("artificialSplitZip.z01")));
+        final File lastFile = newTempFile("splitZip.zip");
+        try (SeekableByteChannel channel = 
ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(lastFile);
+                InputStream inputStream = Channels.newInputStream(channel);
+                ZipArchiveInputStream splitInputStream = new 
ZipArchiveInputStream(inputStream, UTF_8.toString(), true, false, true)) {
 
-        try (ZipFile zipFile = ZipFile.builder()
-                .setPath(outputZipFile.toPath())
-                .setMaxNumberOfDisks(Integer.MAX_VALUE)
-                .get()
-        ) {
-            assertArrayEquals(data1, 
IOUtils.toByteArray(zipFile.getInputStream(zipFile.getEntry("file01"))));
+            ArchiveEntry entry;
+            final int filesNum = countNonDirectories(directoryToZip);
+            int filesCount = 0;
+            while ((entry = splitInputStream.getNextEntry()) != null) {
+                if (entry.isDirectory()) {
+                    continue;
+                }
+                // compare all files one by one
+                assertArrayEquals(IOUtils.toByteArray(splitInputStream), 
Files.readAllBytes(Paths.get(entry.getName())));
+                filesCount++;
+            }
+            // and the number of files should equal
+            assertEquals(filesCount, filesNum);
         }
     }
 
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
index 6fb2ed6ef..6da5068fc 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/cpio/CpioArchiveInputStreamTest.java
@@ -84,6 +84,14 @@ public class CpioArchiveInputStreamTest extends AbstractTest 
{
         assertEquals(2, count);
     }
 
+    @Test
+    public void testInvalidLongValueInMetadata() throws Exception {
+        try (InputStream in = 
newInputStream("org/apache/commons/compress/cpio/bad_long_value.cpio");
+             CpioArchiveInputStream archive = new CpioArchiveInputStream(in)) {
+            assertThrows(IOException.class, archive::getNextEntry);
+        }
+    }
+
     @Test
     public void testMultiByteReadConsistentlyReturnsMinusOneAtEof() throws 
Exception {
         final byte[] buf = new byte[2];
@@ -107,12 +115,4 @@ public class CpioArchiveInputStreamTest extends 
AbstractTest {
         }
     }
 
-    @Test
-    public void testInvalidLongValueInMetadata() throws Exception {
-        try (InputStream in = 
newInputStream("org/apache/commons/compress/cpio/bad_long_value.cpio");
-             CpioArchiveInputStream archive = new CpioArchiveInputStream(in)) {
-            assertThrows(IOException.class, archive::getNextEntry);
-        }
-    }
-
 }
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStreamTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStreamTest.java
index 0c3fb4899..0a121b51b 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStreamTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStreamTest.java
@@ -29,16 +29,16 @@ import org.junit.jupiter.api.Test;
 public class ZipArchiveOutputStreamTest extends AbstractTempDirTest {
 
     @Test
-    public void testOutputStreamBasics() throws IOException {
-        try (ZipArchiveOutputStream stream = new ZipArchiveOutputStream(new 
ByteArrayOutputStream())) {
-            assertFalse(stream.isSeekable());
+    public void testFileBasics() throws IOException {
+        try (ZipArchiveOutputStream stream = new 
ZipArchiveOutputStream(createTempFile())) {
+            assertTrue(stream.isSeekable());
         }
     }
 
     @Test
-    public void testFileBasics() throws IOException {
-        try (ZipArchiveOutputStream stream = new 
ZipArchiveOutputStream(createTempFile())) {
-            assertTrue(stream.isSeekable());
+    public void testOutputStreamBasics() throws IOException {
+        try (ZipArchiveOutputStream stream = new ZipArchiveOutputStream(new 
ByteArrayOutputStream())) {
+            assertFalse(stream.isSeekable());
         }
     }
 }
diff --git 
a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java
 
b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java
index 8c7b0fd9f..74234c542 100644
--- 
a/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java
+++ 
b/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileIgnoringLocalFileHeaderTest.java
@@ -33,10 +33,6 @@ import org.junit.jupiter.api.io.TempDir;
 
 public class ZipFileIgnoringLocalFileHeaderTest {
 
-    private static ZipFile openZipWithoutLocalFileHeaderDeprecated(final 
String fileName) throws IOException {
-        return new ZipFile(AbstractTest.getFile(fileName), CharsetNames.UTF_8, 
true, true);
-    }
-
     private static ZipFile openZipWithoutLocalFileHeader(final String 
fileName) throws IOException {
         // @formatter:off
         return ZipFile.builder()
@@ -48,6 +44,10 @@ public class ZipFileIgnoringLocalFileHeaderTest {
         // @formatter:on
     }
 
+    private static ZipFile openZipWithoutLocalFileHeaderDeprecated(final 
String fileName) throws IOException {
+        return new ZipFile(AbstractTest.getFile(fileName), CharsetNames.UTF_8, 
true, true);
+    }
+
     @TempDir
     private File dir;
 
diff --git 
a/src/test/java/org/apache/commons/compress/compressors/snappy/FramedSnappyCompressorInputStreamTest.java
 
b/src/test/java/org/apache/commons/compress/compressors/snappy/FramedSnappyCompressorInputStreamTest.java
index 27f178fec..5c9a629ad 100644
--- 
a/src/test/java/org/apache/commons/compress/compressors/snappy/FramedSnappyCompressorInputStreamTest.java
+++ 
b/src/test/java/org/apache/commons/compress/compressors/snappy/FramedSnappyCompressorInputStreamTest.java
@@ -40,6 +40,15 @@ import org.junit.jupiter.api.Test;
 
 public final class FramedSnappyCompressorInputStreamTest extends AbstractTest {
 
+    private static byte[] generateTestData(final int inputSize) {
+        final byte[] arr = new byte[inputSize];
+        for (int i = 0; i < arr.length; i++) {
+          arr[i] = (byte) (65 + i % 10);
+        }
+
+        return arr;
+    }
+
     private long mask(final long x) {
         return (x >>> 15 | x << 17) + 
FramedSnappyCompressorInputStream.MASK_OFFSET & 0xffffFFFFL;
     }
@@ -69,6 +78,15 @@ public final class FramedSnappyCompressorInputStreamTest 
extends AbstractTest {
         assertEquals(Long.toHexString(x), 
Long.toHexString(FramedSnappyCompressorInputStream.unmask(mask(x))));
     }
 
+    @Test
+    public void testFinishWithNoWrite() throws IOException {
+        final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        try (FramedSnappyCompressorOutputStream compressor = new 
FramedSnappyCompressorOutputStream(buffer)) {
+            // do nothing here. this will test that flush on close doesn't 
throw any exceptions if no data is written.
+        }
+        assertTrue(buffer.size() == 10, "Only the signature gets written.");
+    }
+
     /**
      * Something big enough to make buffers slide.
      */
@@ -171,6 +189,25 @@ public final class FramedSnappyCompressorInputStreamTest 
extends AbstractTest {
         }
     }
 
+    @Test
+    public void testWriteByteArrayVsWriteByte() throws IOException {
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        final byte[] bytes = "abcdefghijklmnop".getBytes();
+        try (FramedSnappyCompressorOutputStream compressor = new 
FramedSnappyCompressorOutputStream(buffer)) {
+            compressor.write(bytes);
+            compressor.finish();
+        }
+        final byte[] bulkOutput = buffer.toByteArray();
+        buffer = new ByteArrayOutputStream();
+        try (FramedSnappyCompressorOutputStream compressor = new 
FramedSnappyCompressorOutputStream(buffer)) {
+            for (final byte element : bytes) {
+                compressor.write(element);
+            }
+            compressor.finish();
+        }
+        assertArrayEquals(bulkOutput, buffer.toByteArray());
+    }
+
     @Test
     public void testWriteDataLargerThanBufferOneCall() throws IOException {
         final int inputSize = 500_000;
@@ -195,41 +232,4 @@ public final class FramedSnappyCompressorInputStreamTest 
extends AbstractTest {
         assertArrayEquals(data, decompressed);
     }
 
-    private static byte[] generateTestData(final int inputSize) {
-        final byte[] arr = new byte[inputSize];
-        for (int i = 0; i < arr.length; i++) {
-          arr[i] = (byte) (65 + i % 10);
-        }
-
-        return arr;
-    }
-
-    @Test
-    public void testFinishWithNoWrite() throws IOException {
-        final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-        try (FramedSnappyCompressorOutputStream compressor = new 
FramedSnappyCompressorOutputStream(buffer)) {
-            // do nothing here. this will test that flush on close doesn't 
throw any exceptions if no data is written.
-        }
-        assertTrue(buffer.size() == 10, "Only the signature gets written.");
-    }
-
-    @Test
-    public void testWriteByteArrayVsWriteByte() throws IOException {
-        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-        final byte[] bytes = "abcdefghijklmnop".getBytes();
-        try (FramedSnappyCompressorOutputStream compressor = new 
FramedSnappyCompressorOutputStream(buffer)) {
-            compressor.write(bytes);
-            compressor.finish();
-        }
-        final byte[] bulkOutput = buffer.toByteArray();
-        buffer = new ByteArrayOutputStream();
-        try (FramedSnappyCompressorOutputStream compressor = new 
FramedSnappyCompressorOutputStream(buffer)) {
-            for (final byte element : bytes) {
-                compressor.write(element);
-            }
-            compressor.finish();
-        }
-        assertArrayEquals(bulkOutput, buffer.toByteArray());
-    }
-
 }


Reply via email to