private void Init(Stream stream, ZipArchiveMode mode, bool leaveOpen)
{
Stream extraTempStream = null;
try
{
_backingStream = null;
//check stream against mode
switch (mode)
{
case ZipArchiveMode.Create:
if (!stream.CanWrite)
throw new ArgumentException(SR.CreateModeCapabilities);
break;
case ZipArchiveMode.Read:
if (!stream.CanRead)
throw new ArgumentException(SR.ReadModeCapabilities);
if (!stream.CanSeek)
{
_backingStream = stream;
extraTempStream = stream = new MemoryStream();
_backingStream.CopyTo(stream);
stream.Seek(0, SeekOrigin.Begin);
}
break;
case ZipArchiveMode.Update:
if (!stream.CanRead || !stream.CanWrite || !stream.CanSeek)
throw new ArgumentException(SR.UpdateModeCapabilities);
break;
default:
//still have to throw this, because stream constructor doesn't do mode argument checks
throw new ArgumentOutOfRangeException(nameof(mode));
}
_mode = mode;
if (mode == ZipArchiveMode.Create && !stream.CanSeek)
_archiveStream = new PositionPreservingWriteOnlyStreamWrapper(stream);
else
_archiveStream = stream;
_archiveStreamOwner = null;
if (mode == ZipArchiveMode.Create)
_archiveReader = null;
else
_archiveReader = new BinaryReader(_archiveStream);
_entries = new List<ZipArchiveEntry>();
_entriesCollection = new ReadOnlyCollection<ZipArchiveEntry>(_entries);
_entriesDictionary = new Dictionary<string, ZipArchiveEntry>();
_readEntries = false;
_leaveOpen = leaveOpen;
_centralDirectoryStart = 0; //invalid until ReadCentralDirectory
_isDisposed = false;
_numberOfThisDisk = 0; //invalid until ReadCentralDirectory
_archiveComment = null;
switch (mode)
{
case ZipArchiveMode.Create:
_readEntries = true;
break;
case ZipArchiveMode.Read:
ReadEndOfCentralDirectory();
break;
case ZipArchiveMode.Update:
default:
Debug.Assert(mode == ZipArchiveMode.Update);
if (_archiveStream.Length == 0)
{
_readEntries = true;
}
else
{
ReadEndOfCentralDirectory();
EnsureCentralDirectoryRead();
foreach (ZipArchiveEntry entry in _entries)
{
entry.ThrowIfNotOpenable(false, true);
}
}
break;
}
}
catch
{
if (extraTempStream != null)
extraTempStream.Dispose();
throw;
}
}