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(UpdateComparer);
} else {
workFile=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_!=null)
?newComment_.RawComment
:ZipConstants.ConvertToArray(comment_);
using (var zhs=new ZipHelperStream(workFile.baseStream_)) {
zhs.WriteEndOfCentralDirectory(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.Dispose();
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());
}
}