Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

Zip: omit Disk Start Number from the Zip64 Central Directory Entry (when possible) #262

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions src/Zip.Shared/ZipEntry.Write.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,11 @@ this file starts
* that have a header set in Zip64, but doesn't have -1 value in
* appropriate fields of the record itself.
*
* Currently we always set 'Relative Header' and 'Disk Start' inside
* the Extra block for Zip64, meaning that we also need to make sure
* that their non-Zip64 counterparts would be -1 (0xFFFFFFFF
* and 0xFFFF respectively), regardless of the fact if the value fits
* into uint32/uint16 range or not.
* Currently we always set 'Relative Header' inside the Extra block
* for Zip64 and 'Disk Start' when necessary, meaning that we also
* need to make sure that their non-Zip64 counterparts would be -1
* (0xFFFFFFFF and 0xFFFF respectively), regardless of the fact if
* the value fits into uint32/uint16 range or not.
*/
bytes[i++] = 0xFF;
bytes[i++] = 0xFF;
Expand Down Expand Up @@ -384,7 +384,20 @@ private byte[] ConstructExtraField(bool forCentralDirectory)
{
// add extra field for zip64 here
// workitem 7924
int sz = 4 + (forCentralDirectory ? 28 : 16);
int sz = 4 + (forCentralDirectory ? 24 : 16);
// for segmented ZIP, the disk number goes into the extra field
// and ends up as 0xFFFF in the central directory.
// this should match WriteCentralDirectoryEntry to avoid issues
// with tools and libraries that do not fully support Zip64
// (by not putting the disk number in the extra field when
// it can be avoided.)
bool segmented = (this._container.ZipFile != null) &&
(this._container.ZipFile.MaxOutputSegmentSize64 != 0);
bool diskNumberInExtraField = segmented &&
(_presumeZip64 || _diskNumber > 0xFFFF);
if (forCentralDirectory && diskNumberInExtraField)
sz += 4;

block = new byte[sz];
int i = 0;

Expand All @@ -402,7 +415,7 @@ private byte[] ConstructExtraField(bool forCentralDirectory)
}

// DataSize
block[i++] = (byte)(sz - 4); // decimal 28 or 16 (workitem 7924)
block[i++] = (byte)(sz - 4); // decimal 24/28 or 16 (workitem 7924)
block[i++] = 0x00;

// The actual metadata - we may or may not have real values yet...
Expand All @@ -423,8 +436,11 @@ private byte[] ConstructExtraField(bool forCentralDirectory)
Array.Copy(BitConverter.GetBytes(_RelativeOffsetOfLocalHeader), 0, block, i, 8);
i += 8;

// starting disk number
Array.Copy(BitConverter.GetBytes(_diskNumber), 0, block, i, 4);
if (diskNumberInExtraField)
{
// starting disk number
Array.Copy(BitConverter.GetBytes(_diskNumber), 0, block, i, 4);
}
}

listOfBlocks.Add(block);
Expand Down