private void WriteCrcAndSizesInLocalHeader(bool zip64HeaderUsed)
{
long finalPosition = _archive.ArchiveStream.Position;
BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream);
bool zip64Needed = SizesTooLarge()
#if DEBUG_FORCE_ZIP64
|| _archive._forceZip64
#endif
;
bool pretendStreaming = zip64Needed && !zip64HeaderUsed;
uint compressedSizeTruncated = zip64Needed ? ZipHelper.Mask32Bit : (uint)_compressedSize;
uint uncompressedSizeTruncated = zip64Needed ? ZipHelper.Mask32Bit : (uint)_uncompressedSize;
/* first step is, if we need zip64, but didn't allocate it, pretend we did a stream write, because
* we can't go back and give ourselves the space that the extra field needs.
* we do this by setting the correct property in the bit flag */
if (pretendStreaming)
{
_generalPurposeBitFlag |= BitFlagValues.DataDescriptor;
_archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.OffsetToBitFlagFromHeaderStart,
SeekOrigin.Begin);
writer.Write((ushort)_generalPurposeBitFlag);
}
/* next step is fill out the 32-bit size values in the normal header. we can't assume that
* they are correct. we also write the CRC */
_archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.OffsetToCrcFromHeaderStart,
SeekOrigin.Begin);
if (!pretendStreaming)
{
writer.Write(_crc32);
writer.Write(compressedSizeTruncated);
writer.Write(uncompressedSizeTruncated);
}
else //but if we are pretending to stream, we want to fill in with zeroes
{
writer.Write((uint)0);
writer.Write((uint)0);
writer.Write((uint)0);
}
/* next step: if we wrote the 64 bit header initially, a different implementation might
* try to read it, even if the 32-bit size values aren't masked. thus, we should always put the
* correct size information in there. note that order of uncomp/comp is switched, and these are
* 64-bit values
* also, note that in order for this to be correct, we have to insure that the zip64 extra field
* is always the first extra field that is written */
if (zip64HeaderUsed)
{
_archive.ArchiveStream.Seek(_offsetOfLocalHeader + ZipLocalFileHeader.SizeOfLocalHeader
+ _storedEntryNameBytes.Length + Zip64ExtraField.OffsetToFirstField,
SeekOrigin.Begin);
writer.Write(_uncompressedSize);
writer.Write(_compressedSize);
_archive.ArchiveStream.Seek(finalPosition, SeekOrigin.Begin);
}
// now go to the where we were. assume that this is the end of the data
_archive.ArchiveStream.Seek(finalPosition, SeekOrigin.Begin);
/* if we are pretending we did a stream write, we want to write the data descriptor out
* the data descriptor can have 32-bit sizes or 64-bit sizes. In this case, we always use
* 64-bit sizes */
if (pretendStreaming)
{
writer.Write(_crc32);
writer.Write(_compressedSize);
writer.Write(_uncompressedSize);
}
}