private void positionAtCentralDirectory64() throws IOException { this.skipBytes(4); this.archive.readFully(this.DWORD_BUF); this.archive.seek(ZipEightByteInteger.getLongValue(this.DWORD_BUF)); this.archive.readFully(this.WORD_BUF); if (!Arrays.equals(this.WORD_BUF, ZipOutputStream.ZIP64_EOCD_SIG)) { throw new ZipException("archive's ZIP64 end of central directory locator is corrupt."); } this.skipBytes(44); this.archive.readFully(this.DWORD_BUF); this.archive.seek(ZipEightByteInteger.getLongValue(this.DWORD_BUF)); }
/** * Writes the data descriptor entry. * * @param ze the entry to write * @throws IOException on error */ protected void writeDataDescriptor(ZipArchiveEntry ze) throws IOException { if (ze.getMethod() != DEFLATED || raf != null) { return; } writeOut(DD_SIG); writeOut(ZipLong.getBytes(ze.getCrc())); int sizeFieldSize = WORD; if (!hasZip64Extra(ze)) { writeOut(ZipLong.getBytes(ze.getCompressedSize())); writeOut(ZipLong.getBytes(ze.getSize())); } else { sizeFieldSize = DWORD; writeOut(ZipEightByteInteger.getBytes(ze.getCompressedSize())); writeOut(ZipEightByteInteger.getBytes(ze.getSize())); } written += 2 * WORD + 2 * sizeFieldSize; }
/** * When using random access output, write the local file header and potentiall the ZIP64 extra * containing the correct CRC and compressed/uncompressed sizes. */ private void rewriteSizesAndCrc(boolean actuallyNeedsZip64) throws IOException { long save = raf.getFilePointer(); raf.seek(entry.localDataStart); writeOut(ZipLong.getBytes(entry.entry.getCrc())); if (!hasZip64Extra(entry.entry) || !actuallyNeedsZip64) { writeOut(ZipLong.getBytes(entry.entry.getCompressedSize())); writeOut(ZipLong.getBytes(entry.entry.getSize())); } else { writeOut(ZipLong.ZIP64_MAGIC.getBytes()); writeOut(ZipLong.ZIP64_MAGIC.getBytes()); } if (hasZip64Extra(entry.entry)) { // seek to ZIP64 extra, skip header and size information raf.seek( entry.localDataStart + 3 * WORD + 2 * SHORT + getName(entry.entry).limit() + 2 * SHORT); // inside the ZIP64 extra uncompressed size comes // first, unlike the LFH, CD or data descriptor writeOut(ZipEightByteInteger.getBytes(entry.entry.getSize())); writeOut(ZipEightByteInteger.getBytes(entry.entry.getCompressedSize())); if (!actuallyNeedsZip64) { // do some cleanup: // * rewrite version needed to extract raf.seek(entry.localDataStart - 5 * SHORT); writeOut(ZipShort.getBytes(INITIAL_VERSION)); // * remove ZIP64 extra so it doesn't get written // to the central directory entry.entry.removeExtraField(Zip64ExtendedInformationExtraField.HEADER_ID); entry.entry.setExtra(); // * reset hasUsedZip64 if it has been set because // of this entry if (entry.causedUseOfZip64) { hasUsedZip64 = false; } } } raf.seek(save); }
/** * Writes the "ZIP64 End of central dir record" and "ZIP64 End of central dir * locator". * * @throws IOException on error * @since 1.3 */ protected void writeZip64CentralDirectory() throws IOException { if (zip64Mode == Zip64Mode.Never) { return; } if (!hasUsedZip64 && (cdOffset >= ZIP64_MAGIC || cdLength >= ZIP64_MAGIC || entries.size() >= ZIP64_MAGIC_SHORT)) { // actually "will use" hasUsedZip64 = true; } if (!hasUsedZip64) { return; } long offset = written; writeOut(ZIP64_EOCD_SIG); // size, we don't have any variable length as we don't support // the extensible data sector, yet writeOut( ZipEightByteInteger.getBytes( SHORT /* version made by */ + SHORT /* version needed to extract */ + WORD /* disk number */ + WORD /* disk with central directory */ + DWORD /* number of entries in CD on this disk */ + DWORD /* total number of entries */ + DWORD /* size of CD */ + DWORD /* offset of CD */)); // version made by and version needed to extract writeOut(ZipShort.getBytes(ZIP64_MIN_VERSION)); writeOut(ZipShort.getBytes(ZIP64_MIN_VERSION)); // disk numbers - four bytes this time writeOut(LZERO); writeOut(LZERO); // number of entries byte[] num = ZipEightByteInteger.getBytes(entries.size()); writeOut(num); writeOut(num); // length and location of CD writeOut(ZipEightByteInteger.getBytes(cdLength)); writeOut(ZipEightByteInteger.getBytes(cdOffset)); // no "zip64 extensible data sector" for now // and now the "ZIP64 end of central directory locator" writeOut(ZIP64_EOCD_LOC_SIG); // disk number holding the ZIP64 EOCD record writeOut(LZERO); // relative offset of ZIP64 EOCD record writeOut(ZipEightByteInteger.getBytes(offset)); // total number of disks writeOut(ONE); }