From e32acb8c0f378af80426f98e60320fb5b6eba6d1 Mon Sep 17 00:00:00 2001 From: David Cantu Date: Fri, 2 Sep 2022 13:14:54 -0700 Subject: [PATCH 1/9] Fix WritePosixName to use a correct size buffer --- .../src/System/Formats/Tar/TarHeader.Write.cs | 10 ++-- .../TarFile.CreateFromDirectory.File.Tests.cs | 54 +++++++++++++++++++ .../System.Formats.Tar/tests/TarTestsBase.cs | 18 +++++++ 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index 2afcfb8a9f23df..55fa60fab0b601 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -374,12 +374,10 @@ private int WritePosixName(Span buffer) if (_name.Length > FieldLengths.Name) { - int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Name); - Span remaining = prefixBytesLength <= 256 ? - stackalloc byte[prefixBytesLength] : - new byte[prefixBytesLength]; - - int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name), remaining); + int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Prefix); + Debug.Assert(prefixBytesLength <= 256); + Span remaining = stackalloc byte[prefixBytesLength]; + int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name, prefixBytesLength), remaining); Debug.Assert(encoded == remaining.Length); checksum += WriteLeftAlignedBytesAndGetChecksum(remaining, buffer.Slice(FieldLocations.Prefix, FieldLengths.Prefix)); diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index 308a9b68ba4def..18d815aaccc53d 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.IO; +using System.IO.Enumeration; using System.Linq; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Formats.Tar.Tests @@ -253,5 +255,57 @@ public void SkipRecursionIntoBaseDirectorySymlink() Assert.Null(reader.GetNextEntry()); } + + [ConditionalTheory] + [PlatformSpecific(TestPlatforms.AnyUnix)] + [MemberData(nameof(GetPaxAndGnuTestCaseNames))] + public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) + { + if (testCaseName == "specialfiles" && !PlatformDetection.IsSuperUser) + { + throw new SkipTestException("specialfiles needs sudo permissions for extraction"); + } + + using TempDirectory root = new TempDirectory(); + + string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.gnu.ToString(), testCaseName); + string tarExtractedPath = Path.Join(root.Path, "tarExtracted"); + Directory.CreateDirectory(tarExtractedPath); // rename to gnuTarExtractedPath et al + + // extract with /usr/bin/tar + ExtractWithTarTool(archivePath, tarExtractedPath); + + // create archive with TarFile + string dotnetTarArchive = Path.Join(root.Path, "dotnetTarArchive"); + TarFile.CreateFromDirectory(tarExtractedPath, dotnetTarArchive, includeBaseDirectory: false); + + // extract TarFile's archive with /usr/bin/tar + string dotnetTarExtractedPath = Path.Join(root.Path, "dotnetTarExtracted"); + Directory.CreateDirectory(dotnetTarExtractedPath); + ExtractWithTarTool(dotnetTarArchive, dotnetTarExtractedPath); + + // compare results + Dictionary expectedEntries = GetFileSystemInfosRecursive(tarExtractedPath).ToDictionary(fsi => fsi.FullName.Substring(tarExtractedPath.Length)); + + foreach (var actualEntry in GetFileSystemInfosRecursive(dotnetTarExtractedPath)) + { + string keyPath = actualEntry.FullName.Substring(dotnetTarExtractedPath.Length); + + Assert.True(expectedEntries.TryGetValue(keyPath, out FileSystemInfo expectedEntry), "Entry not expected."); + Assert.Equal(expectedEntry.Attributes, actualEntry.Attributes); + Assert.Equal(expectedEntry.LinkTarget, actualEntry.LinkTarget); + + expectedEntries.Remove(keyPath); + } + + // All expected entries should've been found and removed. + Assert.Equal(0, expectedEntries.Count); + } + + private static FileSystemEnumerable GetFileSystemInfosRecursive(string path) + { + var enumerationOptions = new EnumerationOptions { RecurseSubdirectories = true }; + return new FileSystemEnumerable(path, (ref FileSystemEntry e) => e.ToFileSystemInfo(), enumerationOptions); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 23dc653c83a165..84c418fba7c661 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -611,5 +612,22 @@ public static IEnumerable GetPaxAndGnuTestCaseNames() yield return new object[] { name }; } } + + public static void ExtractWithTarTool(string source, string destination) + { + Assert.True(!OperatingSystem.IsWindows(), "This method is unsupported on Windows."); + + using Process tarToolProcess = new Process(); + tarToolProcess.StartInfo.FileName = "/usr/bin/tar"; + tarToolProcess.StartInfo.Arguments = $"-xf {source} -C {destination}"; + + tarToolProcess.StartInfo.UseShellExecute = false; + tarToolProcess.StartInfo.RedirectStandardOutput = true; + tarToolProcess.Start(); + + tarToolProcess.WaitForExit(); + + Assert.Equal(0, tarToolProcess.ExitCode); + } } } From 7df093d504635f21ebdd0f76e6521352cda9ce48 Mon Sep 17 00:00:00 2001 From: David Cantu Date: Fri, 2 Sep 2022 14:18:16 -0700 Subject: [PATCH 2/9] Address feedback --- .../src/System/Formats/Tar/TarHeader.Write.cs | 1 - .../tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs | 4 ++-- src/libraries/System.Formats.Tar/tests/TarTestsBase.cs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index 55fa60fab0b601..1de798f25566f2 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -375,7 +375,6 @@ private int WritePosixName(Span buffer) if (_name.Length > FieldLengths.Name) { int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Prefix); - Debug.Assert(prefixBytesLength <= 256); Span remaining = stackalloc byte[prefixBytesLength]; int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name, prefixBytesLength), remaining); Debug.Assert(encoded == remaining.Length); diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index 18d815aaccc53d..b9028eca74b0d2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -270,13 +270,13 @@ public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.gnu.ToString(), testCaseName); string tarExtractedPath = Path.Join(root.Path, "tarExtracted"); - Directory.CreateDirectory(tarExtractedPath); // rename to gnuTarExtractedPath et al + Directory.CreateDirectory(tarExtractedPath); // extract with /usr/bin/tar ExtractWithTarTool(archivePath, tarExtractedPath); // create archive with TarFile - string dotnetTarArchive = Path.Join(root.Path, "dotnetTarArchive"); + string dotnetTarArchive = Path.Join(root.Path, "dotnetTarArchive.tar"); TarFile.CreateFromDirectory(tarExtractedPath, dotnetTarArchive, includeBaseDirectory: false); // extract TarFile's archive with /usr/bin/tar diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 84c418fba7c661..23187d7559d0fd 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -621,10 +621,10 @@ public static void ExtractWithTarTool(string source, string destination) tarToolProcess.StartInfo.FileName = "/usr/bin/tar"; tarToolProcess.StartInfo.Arguments = $"-xf {source} -C {destination}"; - tarToolProcess.StartInfo.UseShellExecute = false; tarToolProcess.StartInfo.RedirectStandardOutput = true; tarToolProcess.Start(); + tarToolProcess.StandardOutput.ReadToEnd(); tarToolProcess.WaitForExit(); Assert.Equal(0, tarToolProcess.ExitCode); From f9666b5c4051d605d5700b10f8284cb13c8a13e2 Mon Sep 17 00:00:00 2001 From: David Cantu Date: Wed, 7 Sep 2022 12:41:55 -0700 Subject: [PATCH 3/9] Enable test for Windows, add CanExtractWithTarTool, and use pax archives as the baseline --- .../TarFile.CreateFromDirectory.File.Tests.cs | 7 +++---- .../System.Formats.Tar/tests/TarTestsBase.cs | 21 ++++++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index b9028eca74b0d2..6446ca3179404d 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -256,19 +256,18 @@ public void SkipRecursionIntoBaseDirectorySymlink() Assert.Null(reader.GetNextEntry()); } - [ConditionalTheory] - [PlatformSpecific(TestPlatforms.AnyUnix)] + [ConditionalTheory(nameof(CanExtractWithTarTool))] [MemberData(nameof(GetPaxAndGnuTestCaseNames))] public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) { if (testCaseName == "specialfiles" && !PlatformDetection.IsSuperUser) { - throw new SkipTestException("specialfiles needs sudo permissions for extraction"); + throw new SkipTestException("specialfiles is only supported on Unix and it needs sudo permissions for extraction"); } using TempDirectory root = new TempDirectory(); - string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.gnu.ToString(), testCaseName); + string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.pax.ToString(), testCaseName); string tarExtractedPath = Path.Join(root.Path, "tarExtracted"); Directory.CreateDirectory(tarExtractedPath); diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 23187d7559d0fd..41a6f5b5cda495 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -613,12 +613,27 @@ public static IEnumerable GetPaxAndGnuTestCaseNames() } } - public static void ExtractWithTarTool(string source, string destination) + public static bool CanExtractWithTarTool = CanExtractWithTarTool_Method(); + + private static bool CanExtractWithTarTool_Method() { - Assert.True(!OperatingSystem.IsWindows(), "This method is unsupported on Windows."); + using Process tarToolProcess = new Process(); + tarToolProcess.StartInfo.FileName = OperatingSystem.IsWindows() ? "tar" : "/usr/bin/tar"; + tarToolProcess.StartInfo.Arguments = "--help"; + tarToolProcess.StartInfo.RedirectStandardOutput = true; + tarToolProcess.Start(); + + tarToolProcess.StandardOutput.ReadToEnd(); + tarToolProcess.WaitForExit(); + + return (tarToolProcess.ExitCode == 0); + } + + public static void ExtractWithTarTool(string source, string destination) + { using Process tarToolProcess = new Process(); - tarToolProcess.StartInfo.FileName = "/usr/bin/tar"; + tarToolProcess.StartInfo.FileName = OperatingSystem.IsWindows() ? "tar" : "/usr/bin/tar"; tarToolProcess.StartInfo.Arguments = $"-xf {source} -C {destination}"; tarToolProcess.StartInfo.RedirectStandardOutput = true; From 99a7381de3472d4477b861793eb53ca14210aaf0 Mon Sep 17 00:00:00 2001 From: David Cantu Date: Wed, 7 Sep 2022 14:04:36 -0700 Subject: [PATCH 4/9] Look for tar in PATH on all OSes --- src/libraries/System.Formats.Tar/tests/TarTestsBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 41a6f5b5cda495..bc3d243caa76f2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -618,7 +618,7 @@ public static IEnumerable GetPaxAndGnuTestCaseNames() private static bool CanExtractWithTarTool_Method() { using Process tarToolProcess = new Process(); - tarToolProcess.StartInfo.FileName = OperatingSystem.IsWindows() ? "tar" : "/usr/bin/tar"; + tarToolProcess.StartInfo.FileName = "tar"; // location varies: find it on the PATH. tarToolProcess.StartInfo.Arguments = "--help"; tarToolProcess.StartInfo.RedirectStandardOutput = true; @@ -633,7 +633,7 @@ private static bool CanExtractWithTarTool_Method() public static void ExtractWithTarTool(string source, string destination) { using Process tarToolProcess = new Process(); - tarToolProcess.StartInfo.FileName = OperatingSystem.IsWindows() ? "tar" : "/usr/bin/tar"; + tarToolProcess.StartInfo.FileName = "tar"; // location varies: find it on the PATH. tarToolProcess.StartInfo.Arguments = $"-xf {source} -C {destination}"; tarToolProcess.StartInfo.RedirectStandardOutput = true; From 7366e0bd5484e49b566a310137ab4673b9ed89e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Wed, 7 Sep 2022 17:13:22 -0500 Subject: [PATCH 5/9] Add try-catch to CanExtractWithTarTool and move GetFileSystemInfosRecursive to base --- .../TarFile.CreateFromDirectory.File.Tests.cs | 9 +----- .../System.Formats.Tar/tests/TarTestsBase.cs | 30 ++++++++++++++----- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index 6446ca3179404d..dbb3c428f9ecc1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; -using System.IO.Enumeration; using System.Linq; using Microsoft.DotNet.XUnitExtensions; using Xunit; @@ -262,7 +261,7 @@ public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) { if (testCaseName == "specialfiles" && !PlatformDetection.IsSuperUser) { - throw new SkipTestException("specialfiles is only supported on Unix and it needs sudo permissions for extraction"); + throw new SkipTestException("specialfiles is only supported on Unix and it needs sudo permissions for extraction."); } using TempDirectory root = new TempDirectory(); @@ -300,11 +299,5 @@ public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) // All expected entries should've been found and removed. Assert.Equal(0, expectedEntries.Count); } - - private static FileSystemEnumerable GetFileSystemInfosRecursive(string path) - { - var enumerationOptions = new EnumerationOptions { RecurseSubdirectories = true }; - return new FileSystemEnumerable(path, (ref FileSystemEntry e) => e.ToFileSystemInfo(), enumerationOptions); - } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index bc3d243caa76f2..cc4ab174ab92aa 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.IO.Enumeration; using System.Linq; using System.Runtime.CompilerServices; using Microsoft.DotNet.RemoteExecutor; @@ -613,21 +614,34 @@ public static IEnumerable GetPaxAndGnuTestCaseNames() } } + protected static FileSystemEnumerable GetFileSystemInfosRecursive(string path) + { + var enumerationOptions = new EnumerationOptions { RecurseSubdirectories = true }; + return new FileSystemEnumerable(path, (ref FileSystemEntry e) => e.ToFileSystemInfo(), enumerationOptions); + } + public static bool CanExtractWithTarTool = CanExtractWithTarTool_Method(); private static bool CanExtractWithTarTool_Method() { - using Process tarToolProcess = new Process(); - tarToolProcess.StartInfo.FileName = "tar"; // location varies: find it on the PATH. - tarToolProcess.StartInfo.Arguments = "--help"; + try + { + using Process tarToolProcess = new Process(); + tarToolProcess.StartInfo.FileName = "tar"; // location varies: find it on the PATH. + tarToolProcess.StartInfo.Arguments = "--help"; - tarToolProcess.StartInfo.RedirectStandardOutput = true; - tarToolProcess.Start(); + tarToolProcess.StartInfo.RedirectStandardOutput = true; + tarToolProcess.Start(); - tarToolProcess.StandardOutput.ReadToEnd(); - tarToolProcess.WaitForExit(); + string output = tarToolProcess.StandardOutput.ReadToEnd(); + tarToolProcess.WaitForExit(); - return (tarToolProcess.ExitCode == 0); + return tarToolProcess.ExitCode == 0; + } + catch + { + return false; + } } public static void ExtractWithTarTool(string source, string destination) From 1b4bf333f81e20c615c0a94e55c5605f750a7252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Wed, 7 Sep 2022 23:19:46 -0500 Subject: [PATCH 6/9] Skip symlink tests when they are not supported. Make CanExtractWithTarTool return false for old Windows versions. --- .../TarFile.CreateFromDirectory.File.Tests.cs | 11 ++++-- .../System.Formats.Tar/tests/TarTestsBase.cs | 37 ++++++++++--------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index dbb3c428f9ecc1..60f722e29648d7 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -264,6 +264,12 @@ public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) throw new SkipTestException("specialfiles is only supported on Unix and it needs sudo permissions for extraction."); } + string[] symlinkTestCases = { "file_symlink", "foldersymlink_folder_subfolder_file", "file_longsymlink" }; + if (symlinkTestCases.Contains(testCaseName) && !MountHelper.CanCreateSymbolicLinks) + { + throw new SkipTestException("Symlinks are not supported on this platform."); + } + using TempDirectory root = new TempDirectory(); string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.pax.ToString(), testCaseName); @@ -285,11 +291,10 @@ public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) // compare results Dictionary expectedEntries = GetFileSystemInfosRecursive(tarExtractedPath).ToDictionary(fsi => fsi.FullName.Substring(tarExtractedPath.Length)); - foreach (var actualEntry in GetFileSystemInfosRecursive(dotnetTarExtractedPath)) + foreach (FileSystemInfo actualEntry in GetFileSystemInfosRecursive(dotnetTarExtractedPath)) { string keyPath = actualEntry.FullName.Substring(dotnetTarExtractedPath.Length); - - Assert.True(expectedEntries.TryGetValue(keyPath, out FileSystemInfo expectedEntry), "Entry not expected."); + Assert.True(expectedEntries.TryGetValue(keyPath, out FileSystemInfo expectedEntry), $"Entry '{keyPath}' not expected."); Assert.Equal(expectedEntry.Attributes, actualEntry.Attributes); Assert.Equal(expectedEntry.LinkTarget, actualEntry.LinkTarget); diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index cc4ab174ab92aa..574250127349ca 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -620,29 +620,32 @@ protected static FileSystemEnumerable GetFileSystemInfosRecursiv return new FileSystemEnumerable(path, (ref FileSystemEntry e) => e.ToFileSystemInfo(), enumerationOptions); } - public static bool CanExtractWithTarTool = CanExtractWithTarTool_Method(); + public static bool CanExtractWithTarTool => s_canExtractWithTarTool.Value; - private static bool CanExtractWithTarTool_Method() + private static readonly Lazy s_canExtractWithTarTool = new Lazy(() => { - try + if (PlatformDetection.IsWindows) { - using Process tarToolProcess = new Process(); - tarToolProcess.StartInfo.FileName = "tar"; // location varies: find it on the PATH. - tarToolProcess.StartInfo.Arguments = "--help"; + Version osVersion = Environment.OSVersion.Version; + bool isAtLeastWin10Build17063 = osVersion.Major >= 11 || osVersion.Major == 10 && osVersion.Build >= 17063; + if (!isAtLeastWin10Build17063) + { + return false; + } + } + + using Process tarToolProcess = new Process(); + tarToolProcess.StartInfo.FileName = "tar"; // location varies: find it on the PATH. + tarToolProcess.StartInfo.Arguments = "--help"; - tarToolProcess.StartInfo.RedirectStandardOutput = true; - tarToolProcess.Start(); + tarToolProcess.StartInfo.RedirectStandardOutput = true; + tarToolProcess.Start(); - string output = tarToolProcess.StandardOutput.ReadToEnd(); - tarToolProcess.WaitForExit(); + string output = tarToolProcess.StandardOutput.ReadToEnd(); + tarToolProcess.WaitForExit(); - return tarToolProcess.ExitCode == 0; - } - catch - { - return false; - } - } + return tarToolProcess.ExitCode == 0; + }); public static void ExtractWithTarTool(string source, string destination) { From f666873586b4a14322ff182862d8e9c19ba91dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Thu, 8 Sep 2022 10:17:32 -0500 Subject: [PATCH 7/9] Fix CI issues --- .../TarFile/TarFile.CreateFromDirectory.File.Tests.cs | 6 ------ src/libraries/System.Formats.Tar/tests/TarTestsBase.cs | 9 +++++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index 60f722e29648d7..8915630bb69f71 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -264,12 +264,6 @@ public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) throw new SkipTestException("specialfiles is only supported on Unix and it needs sudo permissions for extraction."); } - string[] symlinkTestCases = { "file_symlink", "foldersymlink_folder_subfolder_file", "file_longsymlink" }; - if (symlinkTestCases.Contains(testCaseName) && !MountHelper.CanCreateSymbolicLinks) - { - throw new SkipTestException("Symlinks are not supported on this platform."); - } - using TempDirectory root = new TempDirectory(); string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.pax.ToString(), testCaseName); diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 574250127349ca..9412faddd6fff1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -624,6 +624,11 @@ protected static FileSystemEnumerable GetFileSystemInfosRecursiv private static readonly Lazy s_canExtractWithTarTool = new Lazy(() => { + if (PlatformDetection.IsAndroid || PlatformDetection.IsWindowsNanoServer) + { + return false; + } + if (PlatformDetection.IsWindows) { Version osVersion = Environment.OSVersion.Version; @@ -656,10 +661,10 @@ public static void ExtractWithTarTool(string source, string destination) tarToolProcess.StartInfo.RedirectStandardOutput = true; tarToolProcess.Start(); - tarToolProcess.StandardOutput.ReadToEnd(); + string output = tarToolProcess.StandardOutput.ReadToEnd(); tarToolProcess.WaitForExit(); - Assert.Equal(0, tarToolProcess.ExitCode); + Assert.True(tarToolProcess.ExitCode == 0, "Tar process output: " + output); } } } From aab4eadb7c31796926003c0fcd32862f1e5878f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Thu, 8 Sep 2022 10:22:57 -0500 Subject: [PATCH 8/9] Just skip symlink on windows nano --- .../tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs | 6 ++++++ src/libraries/System.Formats.Tar/tests/TarTestsBase.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs index 8915630bb69f71..807af05d3969a7 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.CreateFromDirectory.File.Tests.cs @@ -264,6 +264,12 @@ public void ResultingArchive_CanBeExtractedByOtherTools(string testCaseName) throw new SkipTestException("specialfiles is only supported on Unix and it needs sudo permissions for extraction."); } + string[] symlinkTestCases = { "file_symlink", "foldersymlink_folder_subfolder_file", "file_longsymlink" }; + if (symlinkTestCases.Contains(testCaseName) && PlatformDetection.IsWindowsNanoServer) // Tar version of Windows Nano Server does not support extracting symlinks. + { + throw new SkipTestException("Symlinks are not supported on this platform."); + } + using TempDirectory root = new TempDirectory(); string archivePath = GetTarFilePath(CompressionMethod.Uncompressed, TestTarFormat.pax.ToString(), testCaseName); diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 9412faddd6fff1..45da361c8a0db2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -624,7 +624,7 @@ protected static FileSystemEnumerable GetFileSystemInfosRecursiv private static readonly Lazy s_canExtractWithTarTool = new Lazy(() => { - if (PlatformDetection.IsAndroid || PlatformDetection.IsWindowsNanoServer) + if (PlatformDetection.IsAndroid) // Android reports tar: chown 7913:3579 'file.txt': Operation not permitted. { return false; } From 3b02c6ef1c5f76219adb01280e674c0bc9392782 Mon Sep 17 00:00:00 2001 From: David Cantu Date: Thu, 8 Sep 2022 09:59:32 -0700 Subject: [PATCH 9/9] Exclude Linux_bionic --- src/libraries/System.Formats.Tar/tests/TarTestsBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 45da361c8a0db2..fe29235d40372c 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -624,7 +624,7 @@ protected static FileSystemEnumerable GetFileSystemInfosRecursiv private static readonly Lazy s_canExtractWithTarTool = new Lazy(() => { - if (PlatformDetection.IsAndroid) // Android reports tar: chown 7913:3579 'file.txt': Operation not permitted. + if (PlatformDetection.IsAndroid || PlatformDetection.IsLinuxBionic) // Android reports tar: chown 7913:3579 'file.txt': Operation not permitted. { return false; }