mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-11-15 17:02:03 +00:00
Preserve frozen stream recordings during TAR probing
This commit is contained in:
@@ -15,6 +15,24 @@ public partial class TarReader
|
||||
: IReaderOpenable
|
||||
#endif
|
||||
{
|
||||
private static SharpCompressStream CreateReaderProbeStream(Stream stream, ReaderOptions options)
|
||||
{
|
||||
if (stream is SharpCompressStream { IsPassthrough: false })
|
||||
{
|
||||
// Keep the caller's recording scope and logical position intact, including
|
||||
// frozen recordings whose buffered bytes have not been replayed yet.
|
||||
return new SeekableSharpCompressStream(stream);
|
||||
}
|
||||
|
||||
return SharpCompressStream.Create(
|
||||
stream,
|
||||
bufferSize: Math.Max(
|
||||
options.RewindableBufferSize ?? 0,
|
||||
TarWrapper.MaximumRewindBufferSize
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static Stream CreateProbeDecompressionStream(
|
||||
Stream stream,
|
||||
CompressionType compressionType,
|
||||
@@ -101,20 +119,11 @@ public partial class TarReader
|
||||
stream = SharpCompressStream.CreateNonDisposing(stream);
|
||||
readerOptions = readerOptions with { LeaveStreamOpen = false };
|
||||
}
|
||||
var sharpCompressStream = SharpCompressStream.Create(
|
||||
stream,
|
||||
bufferSize: Math.Max(
|
||||
readerOptions.RewindableBufferSize ?? 0,
|
||||
TarWrapper.MaximumRewindBufferSize
|
||||
)
|
||||
);
|
||||
var sharpCompressStream = CreateReaderProbeStream(stream, readerOptions);
|
||||
var transferred = false;
|
||||
try
|
||||
{
|
||||
if (!sharpCompressStream.IsRecording)
|
||||
{
|
||||
sharpCompressStream.StartRecording();
|
||||
}
|
||||
sharpCompressStream.StartRecording();
|
||||
long pos = sharpCompressStream.Position;
|
||||
foreach (var wrapper in TarWrapper.Wrappers)
|
||||
{
|
||||
@@ -235,17 +244,8 @@ public partial class TarReader
|
||||
stream = SharpCompressStream.CreateNonDisposing(stream);
|
||||
readerOptions = readerOptions with { LeaveStreamOpen = false };
|
||||
}
|
||||
var sharpCompressStream = SharpCompressStream.Create(
|
||||
stream,
|
||||
bufferSize: Math.Max(
|
||||
readerOptions.RewindableBufferSize ?? 0,
|
||||
TarWrapper.MaximumRewindBufferSize
|
||||
)
|
||||
);
|
||||
if (!sharpCompressStream.IsRecording)
|
||||
{
|
||||
sharpCompressStream.StartRecording();
|
||||
}
|
||||
var sharpCompressStream = CreateReaderProbeStream(stream, readerOptions);
|
||||
sharpCompressStream.StartRecording();
|
||||
long pos = sharpCompressStream.Position;
|
||||
foreach (var wrapper in TarWrapper.Wrappers)
|
||||
{
|
||||
|
||||
@@ -46,6 +46,72 @@ public class TarLifetimeTests : TestBase
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, false, false)]
|
||||
[InlineData(false, false, true)]
|
||||
[InlineData(false, true, false)]
|
||||
[InlineData(false, true, true)]
|
||||
[InlineData(true, false, false)]
|
||||
[InlineData(true, false, true)]
|
||||
[InlineData(true, true, false)]
|
||||
[InlineData(true, true, true)]
|
||||
public async Task Reader_Preserves_Frozen_Recording(
|
||||
bool async,
|
||||
bool stopRecording,
|
||||
bool leaveOpen
|
||||
)
|
||||
{
|
||||
using var archive = new MemoryStream();
|
||||
using (
|
||||
var writer = WriterFactory.OpenWriter(
|
||||
archive,
|
||||
ArchiveType.Tar,
|
||||
new WriterOptions(CompressionType.None) { LeaveStreamOpen = true }
|
||||
)
|
||||
)
|
||||
{
|
||||
writer.Write("empty.txt", Stream.Null);
|
||||
}
|
||||
archive.Position = 0;
|
||||
using var input = new ForwardOnlyStream(archive);
|
||||
using var buffered = SharpCompressStream.Create(input, TarWrapper.MaximumRewindBufferSize);
|
||||
buffered.StartRecording();
|
||||
var header = new byte[512];
|
||||
Assert.Equal(header.Length, buffered.Read(header, 0, header.Length));
|
||||
if (stopRecording)
|
||||
{
|
||||
buffered.StopRecording();
|
||||
}
|
||||
else
|
||||
{
|
||||
buffered.Rewind(true);
|
||||
}
|
||||
Assert.Equal(0, buffered.Position);
|
||||
var options = new ReaderOptions { LeaveStreamOpen = leaveOpen };
|
||||
if (async)
|
||||
{
|
||||
await using var reader = await TarReader.OpenAsyncReader(
|
||||
buffered,
|
||||
options,
|
||||
CancellationToken.None
|
||||
);
|
||||
Assert.True(await reader.MoveToNextEntryAsync(CancellationToken.None));
|
||||
Assert.Equal("empty.txt", reader.Entry.Key);
|
||||
Assert.Equal(0, reader.Entry.Size);
|
||||
Assert.False(await reader.MoveToNextEntryAsync(CancellationToken.None));
|
||||
}
|
||||
else
|
||||
{
|
||||
using var reader = TarReader.OpenReader(buffered, options);
|
||||
Assert.True(reader.MoveToNextEntry());
|
||||
Assert.Equal("empty.txt", reader.Entry.Key);
|
||||
Assert.Equal(0, reader.Entry.Size);
|
||||
Assert.False(reader.MoveToNextEntry());
|
||||
}
|
||||
Assert.Equal(leaveOpen, input.CanRead);
|
||||
Assert.Equal(leaveOpen, buffered.CanRead);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("invalid", false)]
|
||||
[InlineData("invalid", true)]
|
||||
|
||||
Reference in New Issue
Block a user