Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,6 @@ private void GetExpectedTimestampsFromOriginalPaxOrGnu(TarEntry originalEntry, o

}

protected TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targetFormat, TarEntryType entryType, string entryName)
=> targetFormat switch
{
TarEntryFormat.V7 => new V7TarEntry(entryType, entryName),
TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName),
TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName),
TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName),
_ => throw new FormatException($"Unexpected format: {targetFormat}")
};

protected TarEntry InvokeTarEntryConversionConstructor(TarEntryFormat targetFormat, TarEntry other)
=> targetFormat switch
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,35 +94,56 @@ public void Extract_LinkEntry_TargetOutsideDirectory(TarEntryType entryType)
Assert.Equal(0, Directory.GetFileSystemEntries(root.Path).Count());
}

[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
public void Extract_SymbolicLinkEntry_TargetInsideDirectory() => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink);

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))]
public void Extract_HardLinkEntry_TargetInsideDirectory() => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink);

private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entryType)
[ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_SymbolicLinkEntry_TargetInsideDirectory(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink, format, null);

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_HardLinkEntry_TargetInsideDirectory(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink, format, null);

[ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_SymbolicLinkEntry_TargetInsideDirectory_LongBaseDir(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink, format, new string('a', 99));

[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))]
[InlineData(TarEntryFormat.Pax)]
[InlineData(TarEntryFormat.Gnu)]
public void Extract_HardLinkEntry_TargetInsideDirectory_LongBaseDir(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink, format, new string('a', 99));

// This test would not pass for the V7 and Ustar formats in some OSs like MacCatalyst, tvOSSimulator and OSX, because the TempDirectory gets created in
// a folder with a path longer than 100 bytes, and those tar formats have no way of handling pathnames and linknames longer than that length.
// The rest of the OSs create the TempDirectory in a path that does not surpass the 100 bytes, so the 'subfolder' parameter gives a chance to extend
// the base directory past that length, to ensure this scenario is tested everywhere.
private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entryType, TarEntryFormat format, string subfolder)
{
using TempDirectory root = new TempDirectory();

string baseDir = string.IsNullOrEmpty(subfolder) ? root.Path : Path.Join(root.Path, subfolder);
Directory.CreateDirectory(baseDir);

string linkName = "link";
string targetName = "target";
string targetPath = Path.Join(root.Path, targetName);
string targetPath = Path.Join(baseDir, targetName);

File.Create(targetPath).Dispose();

using MemoryStream archive = new MemoryStream();
using (TarWriter writer = new TarWriter(archive, TarEntryFormat.Ustar, leaveOpen: true))
using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true))
{
UstarTarEntry entry = new UstarTarEntry(entryType, linkName);
TarEntry entry= InvokeTarEntryCreationConstructor(format, entryType, linkName);
entry.LinkName = targetPath;
writer.WriteEntry(entry);
}

archive.Seek(0, SeekOrigin.Begin);

TarFile.ExtractToDirectory(archive, root.Path, overwriteFiles: false);
TarFile.ExtractToDirectory(archive, baseDir, overwriteFiles: false);

Assert.Equal(2, Directory.GetFileSystemEntries(root.Path).Count());
Assert.Equal(2, Directory.GetFileSystemEntries(baseDir).Count());
}
}
}
11 changes: 11 additions & 0 deletions src/libraries/System.Formats.Tar/tests/TarTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,5 +323,16 @@ protected Type GetTypeForFormat(TarEntryFormat expectedFormat)
_ => throw new FormatException($"Unrecognized format: {expectedFormat}"),
};
}

protected TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targetFormat, TarEntryType entryType, string entryName)
=> targetFormat switch
{
TarEntryFormat.V7 => new V7TarEntry(entryType, entryName),
TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName),
TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName),
TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName),
_ => throw new FormatException($"Unexpected format: {targetFormat}")
};

}
}