mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-07-20 16:05:31 +00:00
tar fixes
This commit is contained in:
@@ -76,4 +76,30 @@ public class TarEntry : Entry
|
||||
}
|
||||
}
|
||||
}
|
||||
internal static async IAsyncEnumerable<TarEntry> GetEntriesAsync(
|
||||
StreamingMode mode,
|
||||
Stream stream,
|
||||
CompressionType compressionType,
|
||||
IArchiveEncoding archiveEncoding
|
||||
)
|
||||
{
|
||||
await foreach (var header in TarHeaderFactory.ReadHeaderAsync(mode, stream, archiveEncoding))
|
||||
{
|
||||
if (header != null)
|
||||
{
|
||||
if (mode == StreamingMode.Seekable)
|
||||
{
|
||||
yield return new TarEntry(new TarFilePart(header, stream), compressionType);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new TarEntry(new TarFilePart(header, null), compressionType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IncompleteArchiveException("Unexpected EOF reading tar file");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +278,22 @@ public class DeflateStream : Stream, IStreamStack
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugDispose(typeof(DeflateStream));
|
||||
#endif
|
||||
await _baseStream.DisposeAsync().ConfigureAwait(false);
|
||||
_disposed = true;
|
||||
}
|
||||
await base.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Flush the stream.
|
||||
/// </summary>
|
||||
@@ -299,24 +315,6 @@ public class DeflateStream : Stream, IStreamStack
|
||||
await _baseStream.FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_disposed = true;
|
||||
if (_baseStream != null)
|
||||
{
|
||||
await _baseStream.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugDispose(typeof(DeflateStream));
|
||||
#endif
|
||||
await base.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the stream.
|
||||
|
||||
@@ -141,23 +141,23 @@ public class SharpCompressStream : Stream, IStreamStack
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugDispose(typeof(SharpCompressStream));
|
||||
#endif
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (this.LeaveOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ThrowOnDispose)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Attempt to dispose of a {nameof(SharpCompressStream)} when {nameof(ThrowOnDispose)} is {ThrowOnDispose}"
|
||||
);
|
||||
}
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
if (disposing)
|
||||
{
|
||||
Stream.Dispose();
|
||||
@@ -450,5 +450,36 @@ public class SharpCompressStream : Stream, IStreamStack
|
||||
_internalPosition += buffer.Length;
|
||||
}
|
||||
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugDispose(typeof(SharpCompressStream));
|
||||
#endif
|
||||
if (this.LeaveOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (ThrowOnDispose)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Attempt to dispose of a {nameof(SharpCompressStream)} when {nameof(ThrowOnDispose)} is {ThrowOnDispose}"
|
||||
);
|
||||
}
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isDisposed = true;
|
||||
await base.DisposeAsync();
|
||||
|
||||
|
||||
await Stream.DisposeAsync();
|
||||
if (_buffer != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(_buffer);
|
||||
_buffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -119,4 +119,11 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
|
||||
compressionType,
|
||||
Options.ArchiveEncoding
|
||||
);
|
||||
protected override IAsyncEnumerable<TarEntry> GetEntriesAsync(Stream stream) =>
|
||||
TarEntry.GetEntriesAsync(
|
||||
StreamingMode.Streaming,
|
||||
stream,
|
||||
compressionType,
|
||||
Options.ArchiveEncoding
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,9 +63,4 @@ public class AsyncOnlyStream : SharpCompressStream
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) =>
|
||||
Stream.Write(buffer, offset, count);
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Test.Mocks;
|
||||
|
||||
@@ -46,4 +47,13 @@ public class FlushOnDisposeStream(Stream innerStream) : Stream
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await innerStream.FlushAsync();
|
||||
innerStream.Close();
|
||||
await base.DisposeAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -50,6 +50,14 @@ public class TestStream(Stream stream, bool read, bool write, bool seek) : Strea
|
||||
Memory<byte> buffer,
|
||||
CancellationToken cancellationToken = default
|
||||
) => stream.ReadAsync(buffer, cancellationToken);
|
||||
|
||||
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await base.DisposeAsync();
|
||||
await stream.DisposeAsync();
|
||||
IsDisposed = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin) => stream.Seek(offset, origin);
|
||||
|
||||
@@ -160,13 +160,25 @@ public abstract class ReaderTests : TestBase
|
||||
)
|
||||
{
|
||||
using var file = File.OpenRead(testArchive);
|
||||
using var protectedStream = SharpCompressStream.Create(
|
||||
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
await using var protectedStream = SharpCompressStream.Create(
|
||||
new ForwardOnlyStream(file, options.BufferSize),
|
||||
leaveOpen: true,
|
||||
throwOnDispose: true,
|
||||
bufferSize: options.BufferSize
|
||||
);
|
||||
using var testStream = new TestStream(protectedStream);
|
||||
await using var testStream = new TestStream(protectedStream);
|
||||
#else
|
||||
|
||||
using var protectedStream = SharpCompressStream.Create(
|
||||
new ForwardOnlyStream(file, options.BufferSize),
|
||||
leaveOpen: true,
|
||||
throwOnDispose: true,
|
||||
bufferSize: options.BufferSize
|
||||
);
|
||||
using var testStream = new TestStream(protectedStream);
|
||||
#endif
|
||||
await using (
|
||||
var reader = await ReaderFactory.OpenAsyncReader(
|
||||
new AsyncOnlyStream(testStream),
|
||||
|
||||
@@ -163,20 +163,25 @@ public class TarReaderAsyncTests : ReaderTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tar_With_TarGz_With_Flushed_EntryStream_Async()
|
||||
public async ValueTask Tar_With_TarGz_With_Flushed_EntryStream_Async()
|
||||
{
|
||||
var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsTarGz.tar");
|
||||
using Stream stream = File.OpenRead(archiveFullPath);
|
||||
using var reader = ReaderFactory.OpenReader(stream);
|
||||
Assert.True(reader.MoveToNextEntry());
|
||||
await using var reader = await ReaderFactory.OpenAsyncReader(stream);
|
||||
Assert.True(await reader.MoveToNextEntryAsync());
|
||||
Assert.Equal("inner.tar.gz", reader.Entry.Key);
|
||||
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
using var flushingStream = new FlushOnDisposeStream(entryStream);
|
||||
#if !NETFRAMEWORK && !NETSTANDARD2_0
|
||||
await using var entryStream = await reader.OpenEntryStreamAsync();
|
||||
await using var flushingStream = new FlushOnDisposeStream(entryStream);
|
||||
#else
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
using var flushingStream = new FlushOnDisposeStream(entryStream);
|
||||
#endif
|
||||
|
||||
// Extract inner.tar.gz
|
||||
using var innerReader = ReaderFactory.OpenReader(flushingStream);
|
||||
Assert.True(innerReader.MoveToNextEntry());
|
||||
await using var innerReader = await ReaderFactory.OpenAsyncReader(flushingStream);
|
||||
Assert.True(await innerReader.MoveToNextEntryAsync());
|
||||
Assert.Equal("test", innerReader.Entry.Key);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user