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_ != null) ? newComment_.RawComment : ZipConstants.ConvertToArray(comment_); using ( ZipHelperStream 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.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_.Close(); Reopen(archiveStorage_.ConvertTemporaryToFinal()); } }
/// <summary> /// Commit current updates, updating this archive. /// </summary> /// <seealso cref="BeginUpdate()"></seealso> /// <seealso cref="AbortUpdate"></seealso> /// <exception cref="ObjectDisposedException">ZipFile has been closed.</exception> public void CommitUpdate() { if ( isDisposed_ ) { throw new ObjectDisposedException("ZipFile"); } CheckUpdating(); try { updateIndex_.Clear(); updateIndex_=null; if( contentsEdited_ ) { RunUpdates(); } else if( commentEdited_ ) { UpdateCommentOnly(); } else { // Create an empty archive if none existed originally. if( entries_.Length==0 ) { byte[] theComment=(newComment_!=null)?newComment_.RawComment:ZipConstants.ConvertToArray(comment_); using( ZipHelperStream zhs=new ZipHelperStream(baseStream_) ) { zhs.WriteEndOfCentralDirectory(0, 0, 0, theComment); } } } } finally { PostUpdateCleanup(); } }