protected void writeZip64CentralDirectory()

in src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java [1931:2029]


    protected void writeZip64CentralDirectory() throws IOException {
        if (zip64Mode == Zip64Mode.Never) {
            return;
        }

        if (!hasUsedZip64 && shouldUseZip64EOCD()) {
            // actually "will use"
            hasUsedZip64 = true;
        }

        if (!hasUsedZip64) {
            return;
        }

        long offset = streamCompressor.getTotalBytesWritten();
        long diskNumberStart = 0L;
        if (isSplitZip) {
            // when creating a split zip, the offset of should be
            // the offset to the corresponding segment disk
            final ZipSplitOutputStream zipSplitOutputStream = (ZipSplitOutputStream)this.outputStream;
            offset = zipSplitOutputStream.getCurrentSplitSegmentBytesWritten();
            diskNumberStart = zipSplitOutputStream.getCurrentSplitSegmentIndex();
        }


        writeOut(ZIP64_EOCD_SIG);
        // size of zip64 end of central directory, we don't have any variable length
        // as we don't support the extensible data sector, yet
        writeOut(ZipEightByteInteger
                 .getBytes(ZipConstants.SHORT   /* version made by */
                           + ZipConstants.SHORT /* version needed to extract */
                           + ZipConstants.WORD  /* disk number */
                           + ZipConstants.WORD  /* disk with central directory */
                           + ZipConstants.DWORD /* number of entries in CD on this disk */
                           + ZipConstants.DWORD /* total number of entries */
                           + ZipConstants.DWORD /* size of CD */
                           + (long) ZipConstants.DWORD /* offset of CD */
                           ));

        // version made by and version needed to extract
        writeOut(ZipShort.getBytes(ZipConstants.ZIP64_MIN_VERSION));
        writeOut(ZipShort.getBytes(ZipConstants.ZIP64_MIN_VERSION));

        // number of this disk
        int numberOfThisDisk = 0;
        if (isSplitZip) {
            numberOfThisDisk = ((ZipSplitOutputStream)this.outputStream).getCurrentSplitSegmentIndex();
        }
        writeOut(ZipLong.getBytes(numberOfThisDisk));

        // disk number of the start of central directory
        writeOut(ZipLong.getBytes(cdDiskNumberStart));

        // total number of entries in the central directory on this disk
        final int numOfEntriesOnThisDisk = isSplitZip
            ? numberOfCDInDiskData.getOrDefault(numberOfThisDisk, 0)
            : entries.size();
        final byte[] numOfEntriesOnThisDiskData = ZipEightByteInteger.getBytes(numOfEntriesOnThisDisk);
        writeOut(numOfEntriesOnThisDiskData);

        // number of entries
        final byte[] num = ZipEightByteInteger.getBytes(entries.size());
        writeOut(num);

        // length and location of CD
        writeOut(ZipEightByteInteger.getBytes(cdLength));
        writeOut(ZipEightByteInteger.getBytes(cdOffset));

        // no "zip64 extensible data sector" for now

        if (isSplitZip) {
            // based on the ZIP specification, the End Of Central Directory record and
            // the Zip64 End Of Central Directory locator record must be on the same segment
            final int zip64EOCDLOCLength = ZipConstants.WORD  /* length of ZIP64_EOCD_LOC_SIG */
                    + ZipConstants.WORD  /* disk number of ZIP64_EOCD_SIG */
                    + ZipConstants.DWORD /* offset of ZIP64_EOCD_SIG */
                    + ZipConstants.WORD  /* total number of disks */;

            final long unsplittableContentSize = zip64EOCDLOCLength + eocdLength;
            ((ZipSplitOutputStream)this.outputStream).prepareToWriteUnsplittableContent(unsplittableContentSize);
        }

        // and now the "ZIP64 end of central directory locator"
        writeOut(ZIP64_EOCD_LOC_SIG);

        // disk number holding the ZIP64 EOCD record
        writeOut(ZipLong.getBytes(diskNumberStart));
        // relative offset of ZIP64 EOCD record
        writeOut(ZipEightByteInteger.getBytes(offset));
        // total number of disks
        if (isSplitZip) {
            // the Zip64 End Of Central Directory Locator and the End Of Central Directory must be
            // in the same split disk, it means they must be located in the last disk
            final int totalNumberOfDisks = ((ZipSplitOutputStream)this.outputStream).getCurrentSplitSegmentIndex() + 1;
            writeOut(ZipLong.getBytes(totalNumberOfDisks));
        } else {
            writeOut(ONE);
        }
    }