diff --git a/src/SharpCompress/Factories/GZipFactory.cs b/src/SharpCompress/Factories/GZipFactory.cs index 4649f0fc..7dfdd313 100644 --- a/src/SharpCompress/Factories/GZipFactory.cs +++ b/src/SharpCompress/Factories/GZipFactory.cs @@ -185,14 +185,25 @@ public class GZipFactory } sharpCompressStream.Rewind(); - var tarReader = await new TarFactory() - .TryOpenReaderAsync(sharpCompressStream, options, cancellationToken) + using var testStream = SharpCompressStream.CreateNonDisposing( + await options + .Providers.CreateDecompressStreamAsync( + CompressionType.GZip, + SharpCompressStream.CreateNonDisposing(sharpCompressStream), + CompressionContext.FromStream(sharpCompressStream).WithReaderOptions(options), + cancellationToken + ) + .ConfigureAwait(false) + ); + var isTarArchive = await TarArchive + .IsTarFileAsync(testStream, cancellationToken) .ConfigureAwait(false); + sharpCompressStream.Rewind(); sharpCompressStream.StopRecording(); - if (tarReader is not null) + if (isTarArchive) { - return tarReader; + return new TarReader(sharpCompressStream, options, CompressionType.GZip); } return await OpenAsyncReader(sharpCompressStream, options, cancellationToken) diff --git a/src/SharpCompress/Factories/LzwFactory.cs b/src/SharpCompress/Factories/LzwFactory.cs index da475d8a..098ec002 100644 --- a/src/SharpCompress/Factories/LzwFactory.cs +++ b/src/SharpCompress/Factories/LzwFactory.cs @@ -100,14 +100,24 @@ public class LzwFactory : Factory, IReaderFactory } sharpCompressStream.Rewind(); - var tarReader = await new TarFactory() - .TryOpenReaderAsync(sharpCompressStream, options, cancellationToken) + using var testStream = SharpCompressStream.CreateNonDisposing( + await options + .Providers.CreateDecompressStreamAsync( + CompressionType.Lzw, + SharpCompressStream.CreateNonDisposing(sharpCompressStream), + cancellationToken + ) + .ConfigureAwait(false) + ); + var isTarArchive = await TarArchive + .IsTarFileAsync(testStream, cancellationToken) .ConfigureAwait(false); + sharpCompressStream.Rewind(); sharpCompressStream.StopRecording(); - if (tarReader is not null) + if (isTarArchive) { - return tarReader; + return new TarReader(sharpCompressStream, options, CompressionType.Lzw); } return await OpenAsyncReader(sharpCompressStream, options, cancellationToken) diff --git a/tests/SharpCompress.Test/LargeArchiveTests.cs b/tests/SharpCompress.Test/LargeArchiveTests.cs index 761abda6..09090f6a 100644 --- a/tests/SharpCompress.Test/LargeArchiveTests.cs +++ b/tests/SharpCompress.Test/LargeArchiveTests.cs @@ -84,6 +84,22 @@ public class LargeArchiveTests : TestBase Assert.False(await reader.MoveToNextEntryAsync()); } + [Fact] + public async Task OpenAsyncReader_WithGZipExtensionHint_ShouldStreamLargeTarEntry() + { + using var file = File.OpenRead(GetFixturePath("Large/Large.tar.gz")); + await using var stream = new AsyncOnlyStream(new ForwardOnlyStream(file)); + var options = new ReaderOptions { ExtensionHint = "gz" }; + + await using var reader = await ReaderFactory.OpenAsyncReader(stream, options); + + Assert.True(await reader.MoveToNextEntryAsync()); + Assert.False(reader.Entry.IsDirectory); + await using var entryStream = await reader.OpenEntryStreamAsync(); + await VerifyContentAsync(reader.Entry.Key, entryStream); + Assert.False(await reader.MoveToNextEntryAsync()); + } + private static string GetFixturePath(string fixtureName) => Path.Combine(TEST_ARCHIVES_PATH, fixtureName); diff --git a/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs b/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs index 90bce78e..c329d9d2 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs @@ -47,22 +47,38 @@ public class TarReaderAsyncTests : ReaderTests await ReadAsync("Tar.tar.Z", CompressionType.Lzw); [Theory] - [InlineData("Tar.tar.gz", "gz", CompressionType.GZip)] - [InlineData("Tar.tar.Z", "z", CompressionType.Lzw)] + [InlineData("Tar.tar.gz", "gz", CompressionType.GZip, false)] + [InlineData("Tar.tar.gz", "gz", CompressionType.GZip, true)] + [InlineData("Tar.tar.Z", "z", CompressionType.Lzw, false)] + [InlineData("Tar.tar.Z", "z", CompressionType.Lzw, true)] public async ValueTask ReaderFactory_ExtensionHint_PreservesCompressedTarDetection_Async( string archiveName, string extensionHint, - CompressionType compressionType + CompressionType compressionType, + bool useForwardOnlyStream ) { - using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archiveName)); + using var file = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archiveName)); + Stream source = useForwardOnlyStream ? new ForwardOnlyStream(file) : file; + await using var stream = new AsyncOnlyStream(source); var options = ReaderOptions.ForExternalStream.WithExtensionHint(extensionHint); await using var reader = await ReaderFactory.OpenAsyncReader(stream, options); Assert.Equal(ArchiveType.Tar, reader.Type); - Assert.True(await reader.MoveToNextEntryAsync()); - Assert.Equal(compressionType, reader.Entry.CompressionType); + var entryCount = 0; + while (await reader.MoveToNextEntryAsync()) + { + entryCount++; + Assert.Equal(compressionType, reader.Entry.CompressionType); + if (!reader.Entry.IsDirectory) + { + await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH); + } + } + + Assert.True(entryCount > 0); + VerifyFiles(); } [Fact]