Skip to content

Commit

Permalink
Do not read position when tar archive stream is unseekable (#70178)
Browse files Browse the repository at this point in the history
* src: Do not set length nor read position when stream is unseekable.

* tests: Verify can write and read tar.gz archives.

* tests: Add TarWriter test to write to generic unseekable stream.
  • Loading branch information
carlossanlop authored Jun 3, 2022
1 parent 45589f2 commit 1d6f23a
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ private void WriteFinalRecords()
byte[] emptyRecord = new byte[TarHelpers.RecordSize];
_archiveStream.Write(emptyRecord);
_archiveStream.Write(emptyRecord);
_archiveStream.SetLength(_archiveStream.Position);
}

// Partial method for reading an entry from disk and writing it into the archive stream.
Expand Down
80 changes: 80 additions & 0 deletions src/libraries/System.Formats.Tar/tests/CompressedTar.Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 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.Compression;
using System.IO;
using Xunit;

namespace System.Formats.Tar.Tests
{
public class CompressedTar_Tests : TarTestsBase
{
[Fact]
public void TarGz_TarWriter_TarReader()
{
using TempDirectory root = new TempDirectory();

string archivePath = Path.Join(root.Path, "compressed.tar.gz");

string fileName = "file.txt";
string filePath = Path.Join(root.Path, fileName);
File.Create(filePath).Dispose();

// Create tar.gz archive
using (FileStream streamToCompress = File.Create(archivePath))
{
using GZipStream compressorStream = new GZipStream(streamToCompress, CompressionMode.Compress);
using TarWriter writer = new TarWriter(compressorStream);
writer.WriteEntry(fileName: filePath, entryName: fileName);
}
FileInfo fileInfo = new FileInfo(archivePath);
Assert.True(fileInfo.Exists);
Assert.True(fileInfo.Length > 0);

// Verify tar.gz archive contents
using (FileStream streamToDecompress = File.OpenRead(archivePath))
{
using GZipStream decompressorStream = new GZipStream(streamToDecompress, CompressionMode.Decompress);
using TarReader reader = new TarReader(decompressorStream);
TarEntry entry = reader.GetNextEntry();
Assert.Equal(TarFormat.Pax, reader.Format);
Assert.Equal(fileName, entry.Name);
Assert.Null(reader.GetNextEntry());
}
}

[Fact]
public void TarGz_TarFile_CreateFromDir_ExtractToDir()
{
using TempDirectory root = new TempDirectory();

string archivePath = Path.Join(root.Path, "compressed.tar.gz");

string sourceDirectory = Path.Join(root.Path, "source");
Directory.CreateDirectory(sourceDirectory);

string destinationDirectory = Path.Join(root.Path, "destination");
Directory.CreateDirectory(destinationDirectory);

string fileName = "file.txt";
string filePath = Path.Join(sourceDirectory, fileName);
File.Create(filePath).Dispose();

using (FileStream streamToCompress = File.Create(archivePath))
{
using GZipStream compressorStream = new GZipStream(streamToCompress, CompressionMode.Compress);
TarFile.CreateFromDirectory(sourceDirectory, compressorStream, includeBaseDirectory: false);
}
FileInfo fileInfo = new FileInfo(archivePath);
Assert.True(fileInfo.Exists);
Assert.True(fileInfo.Length > 0);

using (FileStream streamToDecompress = File.OpenRead(archivePath))
{
using GZipStream decompressorStream = new GZipStream(streamToDecompress, CompressionMode.Decompress);
TarFile.ExtractToDirectory(decompressorStream, destinationDirectory, overwriteFiles: true);
Assert.True(File.Exists(filePath));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(CommonTestPath)System\IO\TempDirectory.cs" Link="Common\System\IO\TempDirectory.cs" />
<Compile Include="CompressedTar.Tests.cs" />
<Compile Include="TarEntry\TarEntryV7.Tests.cs" />
<Compile Include="TarEntry\TarEntryUstar.Tests.cs" />
<Compile Include="TarEntry\TarEntryPax.Tests.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,29 @@ public void Constructor_NoEntryInsertion_WritesNothing()
Assert.Equal(0, archiveStream.Length);
}

[Fact]
public void Write_To_UnseekableStream()
{
using MemoryStream inner = new MemoryStream();
using WrappedStream wrapped = new WrappedStream(inner, canRead: true, canWrite: true, canSeek: false);

using (TarWriter writer = new TarWriter(wrapped, leaveOpen: true))
{
PaxTarEntry paxEntry = new PaxTarEntry(TarEntryType.RegularFile, "file.txt");
writer.WriteEntry(paxEntry);
} // The final records should get written, and the length should not be set because position cannot be read

inner.Seek(0, SeekOrigin.Begin); // Rewind the base stream (wrapped cannot be rewound)

using (TarReader reader = new TarReader(wrapped))
{
TarEntry entry = reader.GetNextEntry();
Assert.Equal(TarFormat.Pax, reader.Format);
Assert.Equal(TarEntryType.RegularFile, entry.EntryType);
Assert.Null(reader.GetNextEntry());
}
}

[Fact]
public void VerifyChecksumV7()
{
Expand Down

0 comments on commit 1d6f23a

Please sign in to comment.