in src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs [2219:2369]
private int WriteCentralDirectoryHeader(ZipEntry entry)
{
if (entry.CompressedSize < 0)
{
throw new ZipException("Attempt to write central directory entry with unknown csize");
}
if (entry.Size < 0)
{
throw new ZipException("Attempt to write central directory entry with unknown size");
}
if (entry.Crc < 0)
{
throw new ZipException("Attempt to write central directory entry with unknown crc");
}
// Write the central file header
WriteLEInt(ZipConstants.CentralHeaderSignature);
// Version made by
WriteLEShort((entry.HostSystem << 8) | entry.VersionMadeBy);
// Version required to extract
WriteLEShort(entry.Version);
WriteLEShort(entry.Flags);
unchecked
{
WriteLEShort((byte)entry.CompressionMethodForHeader);
WriteLEInt((int)entry.DosTime);
WriteLEInt((int)entry.Crc);
}
bool useExtraCompressedSize = false; //Do we want to store the compressed size in the extra data?
if ((entry.IsZip64Forced()) || (entry.CompressedSize >= 0xffffffff))
{
useExtraCompressedSize = true;
WriteLEInt(-1);
}
else
{
WriteLEInt((int)(entry.CompressedSize & 0xffffffff));
}
bool useExtraUncompressedSize = false; //Do we want to store the uncompressed size in the extra data?
if ((entry.IsZip64Forced()) || (entry.Size >= 0xffffffff))
{
useExtraUncompressedSize = true;
WriteLEInt(-1);
}
else
{
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 is too long.");
}
WriteLEShort(name.Length);
// Central header extra data is different to local header version so regenerate.
var ed = new ZipExtraData(entry.ExtraData);
if (entry.CentralHeaderRequiresZip64)
{
ed.StartNewEntry();
if (useExtraUncompressedSize)
{
ed.AddLeLong(entry.Size);
}
if (useExtraCompressedSize)
{
ed.AddLeLong(entry.CompressedSize);
}
if (entry.Offset >= 0xffffffff)
{
ed.AddLeLong(entry.Offset);
}
// Number of disk on which this file starts isnt supported and is never written here.
ed.AddNewEntry(1);
}
else
{
// Should have already be done when local header was added.
ed.Delete(1);
}
byte[] centralExtraData = ed.GetEntryData();
WriteLEShort(centralExtraData.Length);
WriteLEShort(entry.Comment != null ? entry.Comment.Length : 0);
WriteLEShort(0); // disk number
WriteLEShort(0); // internal file attributes
// External file attributes...
if (entry.ExternalFileAttributes != -1)
{
WriteLEInt(entry.ExternalFileAttributes);
}
else
{
if (entry.IsDirectory)
{
WriteLEUint(16);
}
else
{
WriteLEUint(0);
}
}
if (entry.Offset >= 0xffffffff)
{
WriteLEUint(0xffffffff);
}
else
{
WriteLEUint((uint)(int)entry.Offset);
}
if (name.Length > 0)
{
baseStream_.Write(name, 0, name.Length);
}
if (centralExtraData.Length > 0)
{
baseStream_.Write(centralExtraData, 0, centralExtraData.Length);
}
byte[] rawComment = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : Empty.Array<byte>();
if (rawComment.Length > 0)
{
baseStream_.Write(rawComment, 0, rawComment.Length);
}
return ZipConstants.CentralHeaderBaseSize + name.Length + centralExtraData.Length + rawComment.Length;
}