in src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs [2075:2217]
private void WriteLocalEntryHeader(ZipUpdate update)
{
ZipEntry entry = update.OutEntry;
// TODO: Local offset will require adjusting for multi-disk zip files.
entry.Offset = baseStream_.Position;
// TODO: Need to clear any entry flags that dont make sense or throw an exception here.
if (update.Command != UpdateCommand.Copy)
{
if (entry.CompressionMethod == CompressionMethod.Deflated)
{
if (entry.Size == 0)
{
// No need to compress - no data.
entry.CompressedSize = entry.Size;
entry.Crc = 0;
entry.CompressionMethod = CompressionMethod.Stored;
}
}
else if (entry.CompressionMethod == CompressionMethod.Stored)
{
entry.Flags &= ~(int)GeneralBitFlags.Descriptor;
}
if (HaveKeys)
{
entry.IsCrypted = true;
if (entry.Crc < 0)
{
entry.Flags |= (int)GeneralBitFlags.Descriptor;
}
}
else
{
entry.IsCrypted = false;
}
switch (useZip64_)
{
case UseZip64.Dynamic:
if (entry.Size < 0)
{
entry.ForceZip64();
}
break;
case UseZip64.On:
entry.ForceZip64();
break;
case UseZip64.Off:
// Do nothing. The entry itself may be using Zip64 independently.
break;
}
}
// Write the local file header
WriteLEInt(ZipConstants.LocalHeaderSignature);
WriteLEShort(entry.Version);
WriteLEShort(entry.Flags);
WriteLEShort((byte)entry.CompressionMethodForHeader);
WriteLEInt((int)entry.DosTime);
if (!entry.HasCrc)
{
// Note patch address for updating CRC later.
update.CrcPatchOffset = baseStream_.Position;
WriteLEInt((int)0);
}
else
{
WriteLEInt(unchecked((int)entry.Crc));
}
if (entry.LocalHeaderRequiresZip64)
{
WriteLEInt(-1);
WriteLEInt(-1);
}
else
{
if ((entry.CompressedSize < 0) || (entry.Size < 0))
{
update.SizePatchOffset = baseStream_.Position;
}
WriteLEInt((int)entry.CompressedSize);
WriteLEInt((int)entry.Size);
}
var entryEncoding = _stringCodec.ZipInputEncoding(entry.Flags);
byte[] name = entryEncoding.GetBytes(entry.Name);
if (name.Length > 0xFFFF)
{
throw new ZipException("Entry name too long.");
}
var ed = new ZipExtraData(entry.ExtraData);
if (entry.LocalHeaderRequiresZip64)
{
ed.StartNewEntry();
// Local entry header always includes size and compressed size.
// NOTE the order of these fields is reversed when compared to the normal headers!
ed.AddLeLong(entry.Size);
ed.AddLeLong(entry.CompressedSize);
ed.AddNewEntry(1);
}
else
{
ed.Delete(1);
}
entry.ExtraData = ed.GetEntryData();
WriteLEShort(name.Length);
WriteLEShort(entry.ExtraData.Length);
if (name.Length > 0)
{
baseStream_.Write(name, 0, name.Length);
}
if (entry.LocalHeaderRequiresZip64)
{
if (!ed.Find(1))
{
throw new ZipException("Internal error cannot find extra data");
}
update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex;
}
if (entry.ExtraData.Length > 0)
{
baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length);
}
}