コード例 #1
0
ファイル: ZipFile.cs プロジェクト: IntegralLee/fomm
    private void RunUpdates()
    {
      long sizeEntries = 0;
      long endOfStream = 0;
      var allOk = true;
      var 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 = 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;
        }

        var centralDirOffset = workFile.baseStream_.Position;

        foreach (ZipUpdate update in updates_)
        {
          if (update != null)
          {
            sizeEntries += workFile.WriteCentralDirectoryHeader(update.OutEntry);
          }
        }

        var theComment = 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 (Exception)
      {
        allOk = false;
      }
      finally
      {
        if (directUpdate)
        {
          if (allOk)
          {
            workFile.baseStream_.Flush();
            workFile.baseStream_.SetLength(endOfStream);
          }
        }
        else
        {
          workFile.Close();
        }
      }

      if (allOk)
      {
        if (directUpdate)
        {
          IsNewArchive = false;
          workFile.baseStream_.Flush();
          ReadEntries();
        }
        else
        {
          baseStream_.Close();
          Reopen(archiveStorage_.ConvertTemporaryToFinal());
        }
      }
      else
      {
        workFile.Close();
        if (!directUpdate && (workFile.Name != null))
        {
          File.Delete(workFile.Name);
        }
      }
    }
コード例 #2
0
ファイル: ZipFile.cs プロジェクト: IntegralLee/fomm
    /// <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
        {
          // Create an empty archive if none existed originally.
          if (entries_.Length == 0)
          {
            var theComment = ZipConstants.ConvertToArray(comment_);
            using (var zhs = new ZipHelperStream(baseStream_))
            {
              zhs.WriteEndOfCentralDirectory(0, 0, 0, theComment);
            }
          }
        }
      }
      finally
      {
        PostUpdateCleanup();
      }
    }
コード例 #3
0
ファイル: ZipOutputStream.cs プロジェクト: IntegralLee/fomm
    /// <summary>
    ///   Finishes the stream.  This will write the central directory at the
    ///   end of the zip file and flush the stream.
    /// </summary>
    /// <remarks>
    ///   This is automatically called when the stream is closed.
    /// </remarks>
    /// <exception cref="System.IO.IOException">
    ///   An I/O error occurs.
    /// </exception>
    /// <exception cref="ZipException">
    ///   Comment exceeds the maximum length<br />
    ///   Entry name exceeds the maximum length
    /// </exception>
    public override void Finish()
    {
      if (entries == null)
      {
        return;
      }

      if (curEntry != null)
      {
        CloseEntry();
      }

      long numEntries = entries.Count;
      long sizeEntries = 0;

      foreach (ZipEntry entry in entries)
      {
        WriteLeInt(ZipConstants.CentralHeaderSignature);
        WriteLeShort(ZipConstants.VersionMadeBy);
        WriteLeShort(entry.Version);
        WriteLeShort(entry.Flags);
        WriteLeShort((short) entry.CompressionMethod);
        WriteLeInt((int) entry.DosTime);
        WriteLeInt((int) entry.Crc);

        if (entry.IsZip64Forced() ||
            (entry.CompressedSize >= uint.MaxValue))
        {
          WriteLeInt(-1);
        }
        else
        {
          WriteLeInt((int) entry.CompressedSize);
        }

        if (entry.IsZip64Forced() ||
            (entry.Size >= uint.MaxValue))
        {
          WriteLeInt(-1);
        }
        else
        {
          WriteLeInt((int) entry.Size);
        }

        var name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

        if (name.Length > 0xffff)
        {
          throw new ZipException("Name too long.");
        }

        var ed = new ZipExtraData(entry.ExtraData);

        if (entry.CentralHeaderRequiresZip64)
        {
          ed.StartNewEntry();
          if (entry.IsZip64Forced() ||
              (entry.Size >= 0xffffffff))
          {
            ed.AddLeLong(entry.Size);
          }

          if (entry.IsZip64Forced() ||
              (entry.CompressedSize >= 0xffffffff))
          {
            ed.AddLeLong(entry.CompressedSize);
          }

          if (entry.Offset >= 0xffffffff)
          {
            ed.AddLeLong(entry.Offset);
          }

          ed.AddNewEntry(1);
        }
        else
        {
          ed.Delete(1);
        }

        var extra = ed.GetEntryData();

        var entryComment =
          (entry.Comment != null)
            ? ZipConstants.ConvertToArray(entry.Flags, entry.Comment)
            : new byte[0];

        if (entryComment.Length > 0xffff)
        {
          throw new ZipException("Comment too long.");
        }

        WriteLeShort(name.Length);
        WriteLeShort(extra.Length);
        WriteLeShort(entryComment.Length);
        WriteLeShort(0); // disk number
        WriteLeShort(0); // internal file attributes
        // external file attributes

        if (entry.ExternalFileAttributes != -1)
        {
          WriteLeInt(entry.ExternalFileAttributes);
        }
        else
        {
          WriteLeInt(entry.IsDirectory ? 16 : 0);
        }

        if (entry.Offset >= uint.MaxValue)
        {
          WriteLeInt(-1);
        }
        else
        {
          WriteLeInt((int) entry.Offset);
        }

        if (name.Length > 0)
        {
          baseOutputStream_.Write(name, 0, name.Length);
        }

        if (extra.Length > 0)
        {
          baseOutputStream_.Write(extra, 0, extra.Length);
        }

        if (entryComment.Length > 0)
        {
          baseOutputStream_.Write(entryComment, 0, entryComment.Length);
        }

        sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length;
      }

      using (var zhs = new ZipHelperStream(baseOutputStream_))
      {
        zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment);
      }

      entries = null;
    }