Dispose underlying stream in TarReader.DisposeAsync() as well (#79920)
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Fri, 23 Dec 2022 13:30:06 +0000 (14:30 +0100)
committerGitHub <noreply@github.com>
Fri, 23 Dec 2022 13:30:06 +0000 (14:30 +0100)
* Dispose underlying stream in TarReader.DisposeAsync() as well

Same as https://github.com/dotnet/runtime/pull/79899

* Consolidate duplicated WrappedStream test helpers to Common sources

* Dispose stream passed to WrappedStream

src/libraries/Common/tests/System/IO/WrappedStream.cs [new file with mode: 0644]
src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs
src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj
src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.LongFile.Tests.cs
src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.LongFile.Tests.cs
src/libraries/System.Formats.Tar/tests/WrappedStream.cs [deleted file]
src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj
src/libraries/System.IO.Compression/tests/Utilities/WrappedStream.cs [deleted file]

diff --git a/src/libraries/Common/tests/System/IO/WrappedStream.cs b/src/libraries/Common/tests/System/IO/WrappedStream.cs
new file mode 100644 (file)
index 0000000..71be0b9
--- /dev/null
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.IO
+{
+    public class WrappedStream : Stream
+    {
+        private readonly Stream _baseStream;
+        private readonly EventHandler _onClosed;
+        private bool _canRead, _canWrite, _canSeek;
+
+        public WrappedStream(Stream baseStream, bool canRead, bool canWrite, bool canSeek, EventHandler onClosed = null)
+        {
+            _baseStream = baseStream;
+            _onClosed = onClosed;
+            _canRead = canRead;
+            _canSeek = canSeek;
+            _canWrite = canWrite;
+        }
+
+        public override void Flush() => _baseStream.Flush();
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            if (CanRead)
+            {
+                try
+                {
+                    return _baseStream.Read(buffer, offset, count);
+                }
+                catch (ObjectDisposedException ex)
+                {
+                    throw new InvalidOperationException("This stream does not support reading", ex);
+                }
+            }
+            else throw new InvalidOperationException("This stream does not support reading");
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            if (CanSeek)
+            {
+                try
+                {
+                    return _baseStream.Seek(offset, origin);
+                }
+                catch (ObjectDisposedException ex)
+                {
+                    throw new InvalidOperationException("This stream does not support seeking", ex);
+                }
+            }
+            else throw new InvalidOperationException("This stream does not support seeking");
+        }
+
+        public override void SetLength(long value) { _baseStream.SetLength(value); }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            if (CanWrite)
+            {
+                try
+                {
+                    _baseStream.Write(buffer, offset, count);
+                }
+                catch (ObjectDisposedException ex)
+                {
+                    throw new InvalidOperationException("This stream does not support writing", ex);
+                }
+            }
+            else throw new InvalidOperationException("This stream does not support writing");
+        }
+
+        public override bool CanRead => _canRead && _baseStream.CanRead;
+
+        public override bool CanSeek => _canSeek && _baseStream.CanSeek;
+
+        public override bool CanWrite => _canWrite && _baseStream.CanWrite;
+
+        public override long Length
+        {
+            get
+            {
+                if (!CanSeek)
+                {
+                    throw new InvalidOperationException("This stream does not support seeking.");
+                }
+                return _baseStream.Length;
+            }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                if (!CanSeek)
+                {
+                    throw new InvalidOperationException("This stream does not support seeking");
+                }
+                return _baseStream.Position;
+            }
+            set
+            {
+                if (CanSeek)
+                {
+                    try
+                    {
+                        _baseStream.Position = value;
+                    }
+                    catch (ObjectDisposedException ex)
+                    {
+                        throw new InvalidOperationException("This stream does not support seeking", ex);
+                    }
+                }
+                else throw new InvalidOperationException("This stream does not support seeking");
+            }
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                _onClosed?.Invoke(this, null);
+                _canRead = false;
+                _canWrite = false;
+                _canSeek = false;
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
\ No newline at end of file
index 22c7970644b0b20ed17864167560ccd05f45af2d..1754f2f3bcfe35112d6642ac58070394c11052bb 100644 (file)
@@ -82,11 +82,16 @@ namespace System.Formats.Tar
             {
                 _isDisposed = true;
 
-                if (!_leaveOpen && _dataStreamsToDispose?.Count > 0)
+                if (!_leaveOpen)
                 {
-                    foreach (Stream s in _dataStreamsToDispose)
+                    await _archiveStream.DisposeAsync().ConfigureAwait(false);
+
+                    if (_dataStreamsToDispose?.Count > 0)
                     {
-                        await s.DisposeAsync().ConfigureAwait(false);
+                        foreach (Stream s in _dataStreamsToDispose)
+                        {
+                            await s.DisposeAsync().ConfigureAwait(false);
+                        }
                     }
                 }
             }
index 1d30aa09d0f9707553efbac54cf39fc7625da9ec..7ec67c69fc964bd046ee4de118c5c599f404c938 100644 (file)
@@ -68,9 +68,9 @@
     <Compile Include="TarWriter\TarWriter.WriteEntry.Tests.cs" />
     <Compile Include="TarWriter\TarWriter.WriteEntry.Entry.Ustar.Tests.cs" />
     <Compile Include="TarWriter\TarWriter.WriteEntry.Entry.V7.Tests.cs" />
-    <Compile Include="WrappedStream.cs" Link="WrappedStream.cs" />
     <Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs" Link="Common\DisableRuntimeMarshalling.cs" />
     <Compile Include="$(CommonTestPath)System\IO\ReparsePointUtilities.cs" Link="Common\System\IO\ReparsePointUtilities.cs" />
+    <Compile Include="$(CommonTestPath)System\IO\WrappedStream.cs" Link="Common\System\IO\WrappedStream.cs" />
     <Compile Include="$(CommonTestPath)TestUtilities\System\DisableParallelization.cs" Link="Common\TestUtilities\System\DisableParallelization.cs" />
   </ItemGroup>
   <!-- Windows specific files -->
index 6fd2166e81c35f240725fbc626d5aacbbd877b91..613e30c541d1c4cb70a1b6955fd3e204e69bf70a 100644 (file)
@@ -30,7 +30,7 @@ namespace System.Formats.Tar.Tests
         public void WriteEntry_LongFileSize(TarEntryFormat entryFormat, long size, bool unseekableStream)
         {
             // Write archive with a 8 Gb long entry.
-            FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose });
+            using FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose });
             Stream s = unseekableStream ? new WrappedStream(tarFile, tarFile.CanRead, tarFile.CanWrite, canSeek: false) : tarFile;
 
             using (TarWriter writer = new(s, leaveOpen: true))
index 0f6202662d60978a8d6a7ebaeb63f876dcde8efb..6d260cc9ab7bdc5c177d35faa3c99f8c4249bd30 100644 (file)
@@ -20,7 +20,7 @@ namespace System.Formats.Tar.Tests
         public async Task WriteEntry_LongFileSizeAsync(TarEntryFormat entryFormat, long size, bool unseekableStream)
         {
             // Write archive with a 8 Gb long entry.
-            FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose });
+            await using FileStream tarFile = File.Open(GetTestFilePath(), new FileStreamOptions { Access = FileAccess.ReadWrite, Mode = FileMode.Create, Options = FileOptions.DeleteOnClose });
             Stream s = unseekableStream ? new WrappedStream(tarFile, tarFile.CanRead, tarFile.CanWrite, canSeek: false) : tarFile;
 
             await using (TarWriter writer = new(s, leaveOpen: true))
diff --git a/src/libraries/System.Formats.Tar/tests/WrappedStream.cs b/src/libraries/System.Formats.Tar/tests/WrappedStream.cs
deleted file mode 100644 (file)
index 5697f7c..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.IO;
-
-namespace System.Formats.Tar
-{
-    public class WrappedStream : Stream
-    {
-        private readonly Stream _baseStream;
-        private readonly EventHandler _onClosed;
-        private bool _canRead, _canWrite, _canSeek;
-
-        public WrappedStream(Stream baseStream, bool canRead, bool canWrite, bool canSeek, EventHandler onClosed = null)
-        {
-            _baseStream = baseStream;
-            _onClosed = onClosed;
-            _canRead = canRead;
-            _canSeek = canSeek;
-            _canWrite = canWrite;
-        }
-
-        public override void Flush() => _baseStream.Flush();
-
-        public override int Read(byte[] buffer, int offset, int count)
-        {
-            if (CanRead)
-            {
-                try
-                {
-                    return _baseStream.Read(buffer, offset, count);
-                }
-                catch (ObjectDisposedException ex)
-                {
-                    throw new InvalidOperationException("This stream does not support reading", ex);
-                }
-            }
-            else throw new InvalidOperationException("This stream does not support reading");
-        }
-
-        public override long Seek(long offset, SeekOrigin origin)
-        {
-            if (CanSeek)
-            {
-                try
-                {
-                    return _baseStream.Seek(offset, origin);
-                }
-                catch (ObjectDisposedException ex)
-                {
-                    throw new InvalidOperationException("This stream does not support seeking", ex);
-                }
-            }
-            else throw new InvalidOperationException("This stream does not support seeking");
-        }
-
-        public override void SetLength(long value) { _baseStream.SetLength(value); }
-
-        public override void Write(byte[] buffer, int offset, int count)
-        {
-            if (CanWrite)
-            {
-                try
-                {
-                    _baseStream.Write(buffer, offset, count);
-                }
-                catch (ObjectDisposedException ex)
-                {
-                    throw new InvalidOperationException("This stream does not support writing", ex);
-                }
-            }
-            else throw new InvalidOperationException("This stream does not support writing");
-        }
-
-        public override bool CanRead => _canRead && _baseStream.CanRead;
-
-        public override bool CanSeek => _canSeek && _baseStream.CanSeek;
-
-        public override bool CanWrite => _canWrite && _baseStream.CanWrite;
-
-        public override long Length
-        {
-            get
-            {
-                if (!CanSeek)
-                {
-                    throw new InvalidOperationException("This stream does not support seeking.");
-                }
-                return _baseStream.Length;
-            }
-        }
-
-        public override long Position
-        {
-            get
-            {
-                if (!CanSeek)
-                {
-                    throw new InvalidOperationException("This stream does not support seeking");
-                }
-                return _baseStream.Position;
-            }
-            set
-            {
-                if (CanSeek)
-                {
-                    try
-                    {
-                        _baseStream.Position = value;
-                    }
-                    catch (ObjectDisposedException ex)
-                    {
-                        throw new InvalidOperationException("This stream does not support seeking", ex);
-                    }
-                }
-                else throw new InvalidOperationException("This stream does not support seeking");
-            }
-        }
-
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing)
-            {
-                _onClosed?.Invoke(this, null);
-                _canRead = false;
-                _canWrite = false;
-                _canSeek = false;
-            }
-            base.Dispose(disposing);
-        }
-    }
-}
\ No newline at end of file
index 60a2473e74e17ea30c7539ea986d7c642bbf7578..15afc84fa1c2f374fbc209cde10b27246e95445c 100644 (file)
@@ -18,7 +18,6 @@
     <Compile Include="CompressionStreamUnitTests.Deflate.cs" />
     <Compile Include="CompressionStreamUnitTests.Gzip.cs" />
     <Compile Include="Utilities\StripHeaderAndFooter.cs" />
-    <Compile Include="Utilities\WrappedStream.cs" />
     <Compile Include="XunitAssemblyAttributes.cs" />
     <Compile Include="ZipArchive\zip_CreateTests.cs" />
     <Compile Include="ZipArchive\zip_CreateTests.Comments.cs" />
@@ -37,6 +36,7 @@
     <Compile Include="$(CommonTestPath)System\IO\Compression\LocalMemoryStream.cs" Link="Common\System\IO\Compression\LocalMemoryStream.cs" />
     <Compile Include="$(CommonTestPath)System\IO\Compression\StreamHelpers.cs" Link="Common\System\IO\Compression\StreamHelpers.cs" />
     <Compile Include="$(CommonTestPath)System\IO\TempFile.cs" Link="Common\System\IO\TempFile.cs" />
+    <Compile Include="$(CommonTestPath)System\IO\WrappedStream.cs" Link="Common\System\IO\WrappedStream.cs" />
     <Compile Include="$(CommonTestPath)System\IO\Compression\ZipTestHelper.cs" Link="Common\System\IO\Compression\ZipTestHelper.cs" />
     <Compile Include="$(CommonTestPath)TestUtilities\System\DisableParallelization.cs" Link="Common\TestUtilities\System\DisableParallelization.cs" />
     <Compile Include="$(CommonPath)System\Threading\Tasks\TaskToApm.cs" Link="Common\System\Threading\Tasks\TaskToApm.cs" />
diff --git a/src/libraries/System.IO.Compression/tests/Utilities/WrappedStream.cs b/src/libraries/System.IO.Compression/tests/Utilities/WrappedStream.cs
deleted file mode 100644 (file)
index c93e666..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.IO;
-
-internal class WrappedStream : Stream
-{
-    private readonly Stream _baseStream;
-    private readonly EventHandler _onClosed;
-    private bool _canRead, _canWrite, _canSeek;
-
-    internal WrappedStream(Stream baseStream, bool canRead, bool canWrite, bool canSeek, EventHandler onClosed)
-    {
-        _baseStream = baseStream;
-        _onClosed = onClosed;
-        _canRead = canRead;
-        _canSeek = canSeek;
-        _canWrite = canWrite;
-    }
-
-    internal WrappedStream(Stream baseStream, EventHandler onClosed)
-        : this(baseStream, true, true, true, onClosed) { }
-
-    internal WrappedStream(Stream baseStream) : this(baseStream, null) { }
-
-    public override void Flush() => _baseStream.Flush();
-
-    public override int Read(byte[] buffer, int offset, int count)
-    {
-        if (CanRead)
-        {
-            try
-            {
-                return _baseStream.Read(buffer, offset, count);
-            }
-            catch (ObjectDisposedException ex)
-            {
-                throw new NotSupportedException("This stream does not support reading", ex);
-            }
-        }
-        else throw new NotSupportedException("This stream does not support reading");
-    }
-
-    public override long Seek(long offset, SeekOrigin origin)
-    {
-        if (CanSeek)
-        {
-            try
-            {
-                return _baseStream.Seek(offset, origin);
-            }
-            catch (ObjectDisposedException ex)
-            {
-                throw new NotSupportedException("This stream does not support seeking", ex);
-            }
-        }
-        else throw new NotSupportedException("This stream does not support seeking");
-    }
-
-    public override void SetLength(long value) { _baseStream.SetLength(value); }
-
-    public override void Write(byte[] buffer, int offset, int count)
-    {
-        if (CanWrite)
-        {
-            try
-            {
-                _baseStream.Write(buffer, offset, count);
-            }
-            catch (ObjectDisposedException ex)
-            {
-                throw new NotSupportedException("This stream does not support writing", ex);
-            }
-        }
-        else throw new NotSupportedException("This stream does not support writing");
-    }
-
-    public override bool CanRead => _canRead && _baseStream.CanRead;
-
-    public override bool CanSeek => _canSeek && _baseStream.CanSeek;
-
-    public override bool CanWrite => _canWrite && _baseStream.CanWrite;
-
-    public override long Length => _baseStream.Length;
-
-    public override long Position
-    {
-        get
-        {
-            if (CanSeek)
-                return _baseStream.Position;
-            throw new NotSupportedException("This stream does not support seeking");
-        }
-        set
-        {
-            if (CanSeek)
-            {
-                try
-                {
-                    _baseStream.Position = value;
-                }
-                catch (ObjectDisposedException ex)
-                {
-                    throw new NotSupportedException("This stream does not support seeking", ex);
-                }
-            }
-            else throw new NotSupportedException("This stream does not support seeking");
-        }
-    }
-
-    protected override void Dispose(bool disposing)
-    {
-        if (disposing)
-        {
-            _onClosed?.Invoke(this, null);
-            _canRead = false;
-            _canWrite = false;
-            _canSeek = false;
-        }
-        base.Dispose(disposing);
-    }
-}