From 48afb4da92307a079515fe3f94a647eb0d94ca27 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 30 Apr 2026 14:12:47 +0100 Subject: [PATCH] fixed providers in TarWriter and TarArchive. --- .../Archives/Tar/TarArchive.Factory.cs | 28 +++------- src/SharpCompress/Factories/TarFactory.cs | 53 +++--------------- .../Writers/Tar/TarWriter.Async.cs | 9 +++- src/SharpCompress/Writers/Tar/TarWriter.cs | 54 ++++++++++++++++++- 4 files changed, 74 insertions(+), 70 deletions(-) diff --git a/src/SharpCompress/Archives/Tar/TarArchive.Factory.cs b/src/SharpCompress/Archives/Tar/TarArchive.Factory.cs index 3c3caa3f..53f8527a 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.Factory.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.Factory.cs @@ -58,7 +58,7 @@ public partial class TarArchive ); var compressionType = TarFactory.GetCompressionType( sourceStream, - sourceStream.ReaderOptions.Providers + sourceStream.ReaderOptions ); sourceStream.Seek(0, SeekOrigin.Begin); return new TarArchive(sourceStream, compressionType); @@ -78,7 +78,7 @@ public partial class TarArchive ); var compressionType = TarFactory.GetCompressionType( sourceStream, - sourceStream.ReaderOptions.Providers + sourceStream.ReaderOptions ); sourceStream.Seek(0, SeekOrigin.Begin); return new TarArchive(sourceStream, compressionType); @@ -112,11 +112,7 @@ public partial class TarArchive readerOptions ?? new ReaderOptions() ); var compressionType = await TarFactory - .GetCompressionTypeAsync( - sourceStream, - sourceStream.ReaderOptions.Providers, - cancellationToken - ) + .GetCompressionTypeAsync(sourceStream, sourceStream.ReaderOptions, cancellationToken) .ConfigureAwait(false); sourceStream.Seek(0, SeekOrigin.Begin); return new TarArchive(sourceStream, compressionType); @@ -144,11 +140,7 @@ public partial class TarArchive readerOptions ??= new ReaderOptions() { LeaveStreamOpen = false }; var sourceStream = new SourceStream(fileInfo, i => null, readerOptions); var compressionType = await TarFactory - .GetCompressionTypeAsync( - sourceStream, - sourceStream.ReaderOptions.Providers, - cancellationToken - ) + .GetCompressionTypeAsync(sourceStream, sourceStream.ReaderOptions, cancellationToken) .ConfigureAwait(false); sourceStream.Seek(0, SeekOrigin.Begin); return new TarArchive(sourceStream, compressionType); @@ -169,11 +161,7 @@ public partial class TarArchive readerOptions ?? new ReaderOptions() ); var compressionType = await TarFactory - .GetCompressionTypeAsync( - sourceStream, - sourceStream.ReaderOptions.Providers, - cancellationToken - ) + .GetCompressionTypeAsync(sourceStream, sourceStream.ReaderOptions, cancellationToken) .ConfigureAwait(false); sourceStream.Seek(0, SeekOrigin.Begin); return new TarArchive(sourceStream, compressionType); @@ -194,11 +182,7 @@ public partial class TarArchive readerOptions ?? new ReaderOptions() { LeaveStreamOpen = false } ); var compressionType = await TarFactory - .GetCompressionTypeAsync( - sourceStream, - sourceStream.ReaderOptions.Providers, - cancellationToken - ) + .GetCompressionTypeAsync(sourceStream, sourceStream.ReaderOptions, cancellationToken) .ConfigureAwait(false); sourceStream.Seek(0, SeekOrigin.Begin); return new TarArchive(sourceStream, compressionType); diff --git a/src/SharpCompress/Factories/TarFactory.cs b/src/SharpCompress/Factories/TarFactory.cs index 5e506696..719a1b31 100644 --- a/src/SharpCompress/Factories/TarFactory.cs +++ b/src/SharpCompress/Factories/TarFactory.cs @@ -50,7 +50,6 @@ public class TarFactory /// public override bool IsArchive(Stream stream, string? password = null) { - var providers = CompressionProviderRegistry.Default; var sharpCompressStream = new SharpCompressStream(stream); sharpCompressStream.StartRecording(TarWrapper.MaximumRewindBufferSize); foreach (var wrapper in TarWrapper.Wrappers) @@ -61,8 +60,7 @@ public class TarFactory sharpCompressStream.Rewind(); var decompressedStream = CreateProbeDecompressionStream( sharpCompressStream, - wrapper.CompressionType, - providers + wrapper.CompressionType ); if (TarArchive.IsTarFile(decompressedStream)) { @@ -82,7 +80,6 @@ public class TarFactory CancellationToken cancellationToken = default ) { - var providers = CompressionProviderRegistry.Default; var sharpCompressStream = new SharpCompressStream(stream); sharpCompressStream.StartRecording(TarWrapper.MaximumRewindBufferSize); foreach (var wrapper in TarWrapper.Wrappers) @@ -98,7 +95,6 @@ public class TarFactory var decompressedStream = await CreateProbeDecompressionStreamAsync( sharpCompressStream, wrapper.CompressionType, - providers, cancellationToken: cancellationToken ) .ConfigureAwait(false); @@ -122,10 +118,10 @@ public class TarFactory private static Stream CreateProbeDecompressionStream( Stream stream, CompressionType compressionType, - CompressionProviderRegistry providers, IReaderOptions? readerOptions = null ) { + var providers = readerOptions?.Providers ?? CompressionProviderRegistry.Default; var nonDisposingStream = SharpCompressStream.CreateNonDisposing(stream); if (compressionType == CompressionType.None) { @@ -147,7 +143,6 @@ public class TarFactory private static async ValueTask CreateProbeDecompressionStreamAsync( Stream stream, CompressionType compressionType, - CompressionProviderRegistry providers, IReaderOptions? readerOptions = null, CancellationToken cancellationToken = default ) @@ -157,6 +152,7 @@ public class TarFactory { return nonDisposingStream; } + var providers = readerOptions?.Providers ?? CompressionProviderRegistry.Default; if (compressionType == CompressionType.GZip && readerOptions is not null) { @@ -179,10 +175,9 @@ public class TarFactory public static CompressionType GetCompressionType( Stream stream, - CompressionProviderRegistry? providers = null + IReaderOptions? readerOptions = null ) { - providers ??= CompressionProviderRegistry.Default; stream.Seek(0, SeekOrigin.Begin); foreach (var wrapper in TarWrapper.Wrappers) { @@ -193,7 +188,7 @@ public class TarFactory var decompressedStream = CreateProbeDecompressionStream( stream, wrapper.CompressionType, - providers + readerOptions ); if (TarArchive.IsTarFile(decompressedStream)) { @@ -206,11 +201,10 @@ public class TarFactory public static async ValueTask GetCompressionTypeAsync( Stream stream, - CompressionProviderRegistry? providers = null, + IReaderOptions? readerOptions = null, CancellationToken cancellationToken = default ) { - providers ??= CompressionProviderRegistry.Default; stream.Seek(0, SeekOrigin.Begin); foreach (var wrapper in TarWrapper.Wrappers) { @@ -221,7 +215,7 @@ public class TarFactory var decompressedStream = await CreateProbeDecompressionStreamAsync( stream, wrapper.CompressionType, - providers, + readerOptions, cancellationToken: cancellationToken ) .ConfigureAwait(false); @@ -329,7 +323,6 @@ public class TarFactory var decompressedStream = CreateProbeDecompressionStream( sharpCompressStream, wrapper.CompressionType, - options.Providers, options ); if (TarArchive.IsTarFile(decompressedStream)) @@ -366,7 +359,6 @@ public class TarFactory var decompressedStream = await CreateProbeDecompressionStreamAsync( sharpCompressStream, wrapper.CompressionType, - options.Providers, options, cancellationToken ) @@ -409,35 +401,6 @@ public class TarFactory { throw new ArgumentException("Tars require writable streams."); } - if (writerOptions.LeaveStreamOpen) - { - stream = SharpCompressStream.CreateNonDisposing(stream); - } - - var providers = writerOptions.Providers; - - stream = writerOptions.CompressionType switch - { - CompressionType.None => stream, - CompressionType.BZip2 => providers.CreateCompressStream( - CompressionType.BZip2, - stream, - writerOptions.CompressionLevel - ), - CompressionType.GZip => providers.CreateCompressStream( - CompressionType.GZip, - stream, - writerOptions.CompressionLevel - ), - CompressionType.LZip => providers.CreateCompressStream( - CompressionType.LZip, - stream, - writerOptions.CompressionLevel - ), - _ => throw new InvalidFormatException( - "Tar does not support compression: " + writerOptions.CompressionType - ), - }; return new TarWriter(stream, tarOptions); } @@ -501,7 +464,7 @@ public class TarFactory "Tar does not support compression: " + writerOptions.CompressionType ), }; - return new TarWriter(stream, tarOptions); + return new TarWriter(stream, tarOptions, streamIsPrepared: true); } #endregion diff --git a/src/SharpCompress/Writers/Tar/TarWriter.Async.cs b/src/SharpCompress/Writers/Tar/TarWriter.Async.cs index ca220ca1..f66ad7ac 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.Async.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.Async.cs @@ -31,7 +31,14 @@ public partial class TarWriter { await finishable.FinishAsync().ConfigureAwait(false); } - OutputStream?.Dispose(); + if (OutputStream is IAsyncDisposable asyncDisposableOutputStream) + { + await asyncDisposableOutputStream.DisposeAsync().ConfigureAwait(false); + } + else + { + OutputStream?.Dispose(); + } // base.DisposeAsync() is a no-op since _isDisposed is already set await base.DisposeAsync().ConfigureAwait(false); } diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index d456ef2b..00cdc14a 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -2,6 +2,8 @@ using System; using System.IO; using SharpCompress.Common; using SharpCompress.Common.Tar.Headers; +using SharpCompress.Compressors; +using SharpCompress.IO; using SharpCompress.Providers; namespace SharpCompress.Writers.Tar; @@ -12,12 +14,60 @@ public partial class TarWriter : AbstractWriter private readonly TarHeaderWriteFormat _headerFormat; public TarWriter(Stream destination, TarWriterOptions options) - : base(ArchiveType.Tar, options) + : base(ArchiveType.Tar, GetEffectiveOptions(options)) { _finalizeArchiveOnClose = options.FinalizeArchiveOnClose; _headerFormat = options.HeaderFormat; - InitializeStream(destination); + InitializeStream(CreateOutputStream(destination, options)); + } + + internal TarWriter(Stream destination, TarWriterOptions options, bool streamIsPrepared) + : base(ArchiveType.Tar, GetEffectiveOptions(options)) + { + _finalizeArchiveOnClose = options.FinalizeArchiveOnClose; + _headerFormat = options.HeaderFormat; + + InitializeStream(streamIsPrepared ? destination : CreateOutputStream(destination, options)); + } + + private static TarWriterOptions GetEffectiveOptions(TarWriterOptions options) => + options with + { + CompressionType = CompressionType.None, + LeaveStreamOpen = false, + }; + + private static Stream CreateOutputStream(Stream destination, TarWriterOptions options) + { + if (options.LeaveStreamOpen) + { + destination = SharpCompressStream.CreateNonDisposing(destination); + } + + var providers = options.Providers; + return options.CompressionType switch + { + CompressionType.None => destination, + CompressionType.BZip2 => providers.CreateCompressStream( + CompressionType.BZip2, + destination, + options.CompressionLevel + ), + CompressionType.GZip => providers.CreateCompressStream( + CompressionType.GZip, + destination, + options.CompressionLevel + ), + CompressionType.LZip => providers.CreateCompressStream( + CompressionType.LZip, + destination, + options.CompressionLevel + ), + _ => throw new InvalidFormatException( + "Tar does not support compression: " + options.CompressionType + ), + }; } public override void Write(string filename, Stream source, DateTime? modificationTime) =>