Esempio n. 1
0
		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());
			}
		}
Esempio n. 2
0
		/// <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();
			}
		}