Tar symlink extraction

Extended SharpCompress.Common.ExtractionOptions with a delegate to write symbolic links. If not is null, and a symbolic link is encountered, an exception is thrown.
Removed Mono.Posix.NETStandard from the library, but added to the .NET Core 2.1 test application.
Extended the test to implement the delegate.
This commit is contained in:
Mark Final
2018-11-03 09:45:09 +00:00
parent 3f4338489c
commit 70bafa653b
5 changed files with 47 additions and 18 deletions

View File

@@ -68,18 +68,15 @@ namespace SharpCompress.Common
ExtractionOptions options,
Action<string, FileMode> openAndWrite)
{
#if NETSTANDARD2_0
if (entry.LinkTarget != null)
{
var link = new Mono.Unix.UnixSymbolicLinkInfo(destinationFileName);
if (System.IO.File.Exists(destinationFileName))
if (null == options.WriteSymbolicLink)
{
link.Delete(); // equivalent to ln -s -f
throw new ExtractionException("Entry is a symbolic link but ExtractionOptions.WriteSymbolicLink delegate is null");
}
link.CreateSymbolicLinkTo(entry.LinkTarget);
options.WriteSymbolicLink(destinationFileName, entry.LinkTarget);
}
else
#endif
{
FileMode fm = FileMode.Create;
options = options ?? new ExtractionOptions()

View File

@@ -21,5 +21,14 @@
/// preserve windows file attributes
/// </summary>
public bool PreserveAttributes { get; set; }
/// <summary>
/// Delegate for writing symbolic links to disk.
/// sourcePath is where the symlink is created.
/// targetPath is what the symlink refers to.
/// </summary>
public delegate void SymbolicLinkWriterDelegate(string sourcePath, string targetPath);
public SymbolicLinkWriterDelegate WriteSymbolicLink;
}
}

View File

@@ -34,7 +34,6 @@
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
</ItemGroup>
</Project>

View File

@@ -16,5 +16,6 @@
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="Xunit.SkippableFact" Version="1.3.6" />
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -190,6 +190,8 @@ namespace SharpCompress.Test.Tar
[Fact]
public void Tar_GZip_With_Symlink_Entries()
{
var isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(
System.Runtime.InteropServices.OSPlatform.Windows);
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "TarWithSymlink.tar.gz")))
using (var reader = TarReader.Open(stream))
{
@@ -204,21 +206,42 @@ namespace SharpCompress.Test.Tar
new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
Overwrite = true,
WriteSymbolicLink = (sourcePath, targetPath) =>
{
if (!isWindows)
{
var link = new Mono.Unix.UnixSymbolicLinkInfo(sourcePath);
if (System.IO.File.Exists(sourcePath))
{
link.Delete(); // equivalent to ln -s -f
}
link.CreateSymbolicLinkTo(targetPath);
}
}
});
if (reader.Entry.LinkTarget != null)
if (!isWindows)
{
#if NETSTANDARD2_0
var link = new Mono.Unix.UnixSymbolicLinkInfo(reader.Entry.Key);
if (link.HasContents)
if (reader.Entry.LinkTarget != null)
{
Assert.Equal(link.GetContents(), reader.Entry.LinkTarget);
var path = System.IO.Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key);
var link = new Mono.Unix.UnixSymbolicLinkInfo(path);
if (link.HasContents)
{
// need to convert the link to an absolute path for comparison
var target = reader.Entry.LinkTarget;
var realTarget = System.IO.Path.GetFullPath(
System.IO.Path.Combine($"{System.IO.Path.GetDirectoryName(path)}",
target)
);
Assert.Equal(realTarget, link.GetContents().ToString());
}
else
{
Assert.True(false, "Symlink has no target");
}
}
else
{
Assert.True(false);
}
#endif
}
}
}