in src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs [3012:3162]
private void RunUpdates()
{
long sizeEntries = 0;
long endOfStream = 0;
bool directUpdate = false;
long destinationPosition = 0; // NOT SFX friendly
ZipFile workFile;
if (IsNewArchive)
{
workFile = this;
workFile.baseStream_.Position = 0;
directUpdate = true;
}
else if (archiveStorage_.UpdateMode == FileUpdateMode.Direct)
{
workFile = this;
workFile.baseStream_.Position = 0;
directUpdate = true;
// Sort the updates by offset within copies/modifies, then adds.
// This ensures that data required by copies will not be overwritten.
updates_.Sort(new UpdateComparer());
}
else
{
workFile = ZipFile.Create(archiveStorage_.GetTemporaryOutput());
workFile.UseZip64 = UseZip64;
if (key != null)
{
workFile.key = (byte[])key.Clone();
}
}
try
{
foreach (ZipUpdate update in updates_)
{
if (update != null)
{
switch (update.Command)
{
case UpdateCommand.Copy:
if (directUpdate)
{
CopyEntryDirect(workFile, update, ref destinationPosition);
}
else
{
CopyEntry(workFile, update);
}
break;
case UpdateCommand.Modify:
// TODO: Direct modifying of an entry will take some legwork.
ModifyEntry(workFile, update);
break;
case UpdateCommand.Add:
if (!IsNewArchive && directUpdate)
{
workFile.baseStream_.Position = destinationPosition;
}
AddEntry(workFile, update);
if (directUpdate)
{
destinationPosition = workFile.baseStream_.Position;
}
break;
}
}
}
if (!IsNewArchive && directUpdate)
{
workFile.baseStream_.Position = destinationPosition;
}
long centralDirOffset = workFile.baseStream_.Position;
foreach (ZipUpdate update in updates_)
{
if (update != null)
{
sizeEntries += workFile.WriteCentralDirectoryHeader(update.OutEntry);
}
}
byte[] theComment = newComment_?.RawComment ?? _stringCodec.ZipArchiveCommentEncoding.GetBytes(comment_);
ZipFormat.WriteEndOfCentralDirectory(workFile.baseStream_, updateCount_,
sizeEntries, centralDirOffset, theComment);
endOfStream = workFile.baseStream_.Position;
// And now patch entries...
foreach (ZipUpdate update in updates_)
{
if (update != null)
{
// If the size of the entry is zero leave the crc as 0 as well.
// The calculated crc will be all bits on...
if ((update.CrcPatchOffset > 0) && (update.OutEntry.CompressedSize > 0))
{
workFile.baseStream_.Position = update.CrcPatchOffset;
workFile.WriteLEInt((int)update.OutEntry.Crc);
}
if (update.SizePatchOffset > 0)
{
workFile.baseStream_.Position = update.SizePatchOffset;
if (update.OutEntry.LocalHeaderRequiresZip64)
{
workFile.WriteLeLong(update.OutEntry.Size);
workFile.WriteLeLong(update.OutEntry.CompressedSize);
}
else
{
workFile.WriteLEInt((int)update.OutEntry.CompressedSize);
workFile.WriteLEInt((int)update.OutEntry.Size);
}
}
}
}
}
catch
{
workFile.Close();
if (!directUpdate && (workFile.Name != null))
{
File.Delete(workFile.Name);
}
throw;
}
if (directUpdate)
{
workFile.baseStream_.SetLength(endOfStream);
workFile.baseStream_.Flush();
isNewArchive_ = false;
ReadEntries();
}
else
{
baseStream_.Dispose();
Reopen(archiveStorage_.ConvertTemporaryToFinal());
}
}