Crisis.Ionic.Zip.ZipEntry.Write C# (CSharp) Method

Write() private method

private Write ( Stream s ) : void
s Stream
return void
        internal void Write(Stream s)
        {
            var cs1 = s as CountingStream;
            var zss1 = s as ZipSegmentedStream;

            bool done = false;
            do
            {
                try
                {
                    // When the app is updating a zip file, it may be possible to
                    // just copy data for a ZipEntry from the source zipfile to the
                    // destination, as a block, without decompressing and
                    // recompressing, etc.  But, in some cases the app modifies the
                    // properties on a ZipEntry prior to calling Save(). A change to
                    // any of the metadata - the FileName, CompressioLeve and so on,
                    // means DotNetZip cannot simply copy through the existing
                    // ZipEntry data unchanged.
                    //
                    // There are two cases:
                    //
                    //  1. Changes to only metadata, which means the header and
                    //     central directory must be changed.
                    //
                    //  2. Changes to the properties that affect the compressed
                    //     stream, such as CompressionMethod, CompressionLevel, or
                    //     EncryptionAlgorithm. In this case, DotNetZip must
                    //     "re-stream" the data: the old entry data must be maybe
                    //     decrypted, maybe decompressed, then maybe re-compressed
                    //     and maybe re-encrypted.
                    //
                    // This test checks if the source for the entry data is a zip file, and
                    // if a restream is necessary.  If NOT, then it just copies through
                    // one entry, potentially changing the metadata.

                    if (_Source == ZipEntrySource.ZipFile && !_restreamRequiredOnSave)
                    {
                        CopyThroughOneEntry(s);
                        return;
                    }

                    // Is the entry a directory?  If so, the write is relatively simple.
                    if (IsDirectory)
                    {
                        WriteHeader(s, 1);
                        StoreRelativeOffset();
                        _entryRequiresZip64 = new Nullable<bool>(_RelativeOffsetOfLocalHeader >= 0xFFFFFFFF);
                        _OutputUsesZip64 = new Nullable<bool>(_container.Zip64 == Zip64Option.Always || _entryRequiresZip64.Value);
                        // handle case for split archives
                        if (zss1 != null)
                            _diskNumber = zss1.CurrentSegment;

                        return;
                    }

                    // At this point, the source for this entry is not a directory, and
                    // not a previously created zip file, or the source for the entry IS
                    // a previously created zip but the settings whave changed in
                    // important ways and therefore we will need to process the
                    // bytestream (compute crc, maybe compress, maybe encrypt) in order
                    // to write the content into the new zip.
                    //
                    // We do this in potentially 2 passes: The first time we do it as
                    // requested, maybe with compression and maybe encryption.  If that
                    // causes the bytestream to inflate in size, and if compression was
                    // on, then we turn off compression and do it again.


                    bool readAgain = true;
                    int nCycles = 0;
                    do
                    {
                        nCycles++;

                        WriteHeader(s, nCycles);

                        // write the encrypted header
                        WriteSecurityMetadata(s);

                        // write the (potentially compressed, potentially encrypted) file data
                        _WriteEntryData(s);

                        // track total entry size (including the trailing descriptor and MAC)
                        _TotalEntrySize = _LengthOfHeader + _CompressedFileDataSize + _LengthOfTrailer;

                        // The file data has now been written to the stream, and
                        // the file pointer is positioned directly after file data.

                        if (nCycles > 1) readAgain = false;
                        else if (!s.CanSeek) readAgain = false;
                        else readAgain = WantReadAgain();

                        if (readAgain)
                        {
                            // Seek back in the raw output stream, to the beginning of the file
                            // data for this entry.

                            // handle case for split archives
                            if (zss1 != null)
                            {
                                // Console.WriteLine("***_diskNumber/first: {0}", _diskNumber);
                                // Console.WriteLine("***_diskNumber/current: {0}", zss.CurrentSegment);
                                zss1.TruncateBackward(_diskNumber, _RelativeOffsetOfLocalHeader);
                            }
                            else
                                // workitem 8098: ok (output).
                                s.Seek(_RelativeOffsetOfLocalHeader, SeekOrigin.Begin);

                            // If the last entry expands, we read again; but here, we must
                            // truncate the stream to prevent garbage data after the
                            // end-of-central-directory.

                            // workitem 8098: ok (output).
                            s.SetLength(s.Position);

                            // Adjust the count on the CountingStream as necessary.
                            if (cs1 != null) cs1.Adjust(_TotalEntrySize);
                        }
                    }
                    while (readAgain);
                    _skippedDuringSave = false;
                    done = true;
                }
                catch (System.Exception exc1)
                {
                    ZipErrorAction orig = this.ZipErrorAction;
                    int loop = 0;
                    do
                    {
                        if (ZipErrorAction == ZipErrorAction.Throw)
                            throw;

                        if (ZipErrorAction == ZipErrorAction.Skip ||
                            ZipErrorAction == ZipErrorAction.Retry)
                        {
                            // must reset file pointer here.
                            // workitem 13903 - seek back only when necessary
                            long p1 = (cs1 != null)
                                ? cs1.ComputedPosition
                                : s.Position;
                            long delta = p1 - _future_ROLH;
                            if (delta > 0)
                            {
                                s.Seek(delta, SeekOrigin.Current); // may throw
                                long p2 = s.Position;
                                s.SetLength(s.Position);  // to prevent garbage if this is the last entry
                                if (cs1 != null) cs1.Adjust(p1 - p2);
                            }
                            if (ZipErrorAction == ZipErrorAction.Skip)
                            {
                                WriteStatus("Skipping file {0} (exception: {1})", LocalFileName, exc1.ToString());

                                _skippedDuringSave = true;
                                done = true;
                            }
                            else
                                this.ZipErrorAction = orig;
                            break;
                        }

                        if (loop > 0) throw;

                        if (ZipErrorAction == ZipErrorAction.InvokeErrorEvent)
                        {
                            OnZipErrorWhileSaving(exc1);
                            if (_ioOperationCanceled)
                            {
                                done = true;
                                break;
                            }
                        }
                        loop++;
                    }
                    while (true);
                }
            }
            while (!done);
        }
ZipEntry