From 90dda987828f24f511148284b1d724de82f65ce9 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Tue, 5 Jul 2022 18:41:30 +0200 Subject: [PATCH 1/5] Tar, Zip: respect umask when creating files. --- .../src/System/Formats/Tar/TarEntry.Unix.cs | 18 ---------- .../System/Formats/Tar/TarEntry.Windows.cs | 8 ----- .../src/System/Formats/Tar/TarEntry.cs | 27 ++++++++++++--- .../src/System.IO.Compression.ZipFile.csproj | 1 - ...Extensions.ZipArchiveEntry.Extract.Unix.cs | 33 ------------------- ...pFileExtensions.ZipArchiveEntry.Extract.cs | 27 +++++++++++---- .../tests/ZipFile.Unix.cs | 4 +-- 7 files changed, 45 insertions(+), 73 deletions(-) delete mode 100644 src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.Unix.cs diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Unix.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Unix.cs index 120f8a41da389..87a45ba14d6f5 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Unix.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Unix.cs @@ -39,23 +39,5 @@ private void ExtractAsHardLink(string targetFilePath, string hardLinkFilePath) Debug.Assert(!string.IsNullOrEmpty(hardLinkFilePath)); Interop.CheckIo(Interop.Sys.Link(targetFilePath, hardLinkFilePath), hardLinkFilePath); } - - // Unix specific implementation of the method that specifies the file permissions of the extracted file. - private void SetModeOnFile(SafeFileHandle handle) - { - // Only extract USR, GRP, and OTH file permissions, and ignore - // S_ISUID, S_ISGID, and S_ISVTX bits. - // It is off by default because it's possible that a file in an archive could have - // one of these bits set and, unknown to the person extracting, could allow others to - // execute the file as the user or group. - const int ExtractPermissionMask = 0x1FF; - int permissions = (int)Mode & ExtractPermissionMask; - - // If the permissions weren't set at all, don't write the file's permissions. - if (permissions != 0) - { - File.SetUnixFileMode(handle, (UnixFileMode)permissions); - } - } } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Windows.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Windows.cs index 491e51d7cd022..8b0c5ff4a04d2 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Windows.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.Windows.cs @@ -38,13 +38,5 @@ private void ExtractAsHardLink(string targetFilePath, string hardLinkFilePath) Debug.Assert(!string.IsNullOrEmpty(hardLinkFilePath)); Interop.Kernel32.CreateHardLink(hardLinkFilePath, targetFilePath); } - - // Mode is not used on Windows. -#pragma warning disable CA1822 // Member 'SetModeOnFile' does not access instance data and can be marked as static - private void SetModeOnFile(SafeFileHandle handle) -#pragma warning restore CA1822 - { - // TODO: Verify that executables get their 'executable' permission applied on Windows when extracted, if applicable. https://github.com/dotnet/runtime/issues/68230 - } } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index d77cd1de184d6..39e80e84a5db8 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -545,9 +545,19 @@ private void ExtractAsRegularFile(string destinationFileName) { Access = FileAccess.Write, Mode = FileMode.CreateNew, - Share = FileShare.None, - PreallocationSize = Length, + Share = FileShare.None }; + if (OperatingSystem.IsWindows()) + { + // On Windows, PreallocationSize gives a perf improvement. + fileStreamOptions.PreallocationSize = Length; + } + else + { + // Restore permissions. + // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). + fileStreamOptions.UnixCreateMode = Mode & (UnixFileMode)0x1FF; + } // Rely on FileStream's ctor for further checking destinationFileName parameter using (FileStream fs = new FileStream(destinationFileName, fileStreamOptions)) { @@ -556,7 +566,6 @@ private void ExtractAsRegularFile(string destinationFileName) // Important: The DataStream will be written from its current position DataStream.CopyTo(fs); } - SetModeOnFile(fs.SafeFileHandle); } ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime); @@ -578,6 +587,17 @@ private async Task ExtractAsRegularFileAsync(string destinationFileName, Cancell PreallocationSize = Length, Options = FileOptions.Asynchronous }; + if (OperatingSystem.IsWindows()) + { + // On Windows, PreallocationSize gives a perf improvement. + fileStreamOptions.PreallocationSize = Length; + } + else + { + // Restore permissions. + // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). + fileStreamOptions.UnixCreateMode = Mode & (UnixFileMode)0x1FF; + } // Rely on FileStream's ctor for further checking destinationFileName parameter FileStream fs = new FileStream(destinationFileName, fileStreamOptions); await using (fs) @@ -587,7 +607,6 @@ private async Task ExtractAsRegularFileAsync(string destinationFileName, Cancell // Important: The DataStream will be written from its current position await DataStream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } - SetModeOnFile(fs.SafeFileHandle); } ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime); diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj b/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj index b573949d69995..94999191663fa 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj +++ b/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj @@ -24,7 +24,6 @@ - diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.Unix.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.Unix.cs deleted file mode 100644 index adcf474853aa9..0000000000000 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.Unix.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; - -namespace System.IO.Compression -{ - public static partial class ZipFileExtensions - { - static partial void ExtractExternalAttributes(FileStream fs, ZipArchiveEntry entry) - { - Debug.Assert(!OperatingSystem.IsWindows()); - - // Only extract USR, GRP, and OTH file permissions, and ignore - // S_ISUID, S_ISGID, and S_ISVTX bits. This matches unzip's default behavior. - // It is off by default because of this comment: - - // "It's possible that a file in an archive could have one of these bits set - // and, unknown to the person unzipping, could allow others to execute the - // file as the user or group. The new option -K bypasses this check." - const int ExtractPermissionMask = 0x1FF; - int permissions = (entry.ExternalAttributes >> 16) & ExtractPermissionMask; - - // If the permissions weren't set at all, don't write the file's permissions, - // since the .zip could have been made using a previous version of .NET, which didn't - // include the permissions, or was made on Windows. - if (permissions != 0) - { - File.SetUnixFileMode(fs.SafeFileHandle, (UnixFileMode)permissions); - } - } - } -} diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs index c393c4e1e11c6..1499c28baacf7 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs @@ -65,22 +65,35 @@ public static void ExtractToFile(this ZipArchiveEntry source, string destination ArgumentNullException.ThrowIfNull(source); ArgumentNullException.ThrowIfNull(destinationFileName); - // Rely on FileStream's ctor for further checking destinationFileName parameter - FileMode fMode = overwrite ? FileMode.Create : FileMode.CreateNew; + FileStreamOptions fileStreamOptions = new() + { + Access = FileAccess.Write, + Mode = overwrite ? FileMode.Create : FileMode.CreateNew, + Share = FileShare.None, + BufferSize = 0x1000 + }; - using (FileStream fs = new FileStream(destinationFileName, fMode, FileAccess.Write, FileShare.None, bufferSize: 0x1000, useAsync: false)) + // Restore Unix permissions. + if (!OperatingSystem.IsWindows() && source.ExternalAttributes != 0) + { + // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). + UnixFileMode mode = (UnixFileMode)((source.ExternalAttributes >> 16) & 0x1FF); + + if (mode != UnixFileMode.None) // .zip files created on Windows don't include permissions. + { + fileStreamOptions.UnixCreateMode = mode; + } + } + + using (FileStream fs = new FileStream(destinationFileName, fileStreamOptions)) { using (Stream es = source.Open()) es.CopyTo(fs); - - ExtractExternalAttributes(fs, source); } ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, source.LastWriteTime); } - static partial void ExtractExternalAttributes(FileStream fs, ZipArchiveEntry entry); - internal static void ExtractRelativeToDirectory(this ZipArchiveEntry source, string destinationDirectoryName) => ExtractRelativeToDirectory(source, destinationDirectoryName, overwrite: false); diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs index 2bca01e0c5c00..c0b3a2dc114fb 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs +++ b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs @@ -15,7 +15,7 @@ public partial class ZipFile_Unix : ZipFileTestBase public void UnixCreateSetsPermissionsInExternalAttributes() { // '7600' tests that S_ISUID, S_ISGID, and S_ISVTX bits get preserved in ExternalAttributes - string[] testPermissions = new[] { "777", "755", "644", "600", "7600" }; + string[] testPermissions = new[] { "700", "755", "644", "600", "7600" }; using (var tempFolder = new TempDirectory(Path.Combine(GetTestFilePath(), "testFolder"))) { @@ -60,7 +60,7 @@ void EnsureExternalAttributes(string permissions, ZipArchiveEntry entry) public void UnixExtractSetsFilePermissionsFromExternalAttributes() { // '7600' tests that S_ISUID, S_ISGID, and S_ISVTX bits don't get extracted to file permissions - string[] testPermissions = new[] { "777", "755", "644", "754", "7600" }; + string[] testPermissions = new[] { "700", "755", "644", "754", "7600" }; string archivePath = GetTestFilePath(); using (FileStream fileStream = new FileStream(archivePath, FileMode.CreateNew)) From bf0cb4cb7dda01bbf458dd1681a3fd60bcdab2cb Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Tue, 5 Jul 2022 22:19:51 +0200 Subject: [PATCH 2/5] Update UnixExtractFilePermissionsCompat --- .../tests/ZipFile.Unix.cs | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs index c0b3a2dc114fb..a7a39f149a2c7 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs +++ b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs @@ -199,23 +199,22 @@ await Task.WhenAll( private static string GetExpectedPermissions(string expectedPermissions) { - if (string.IsNullOrEmpty(expectedPermissions)) + using (var tempFolder = new TempDirectory()) { - // Create a new file, and get its permissions to get the current system default permissions - - using (var tempFolder = new TempDirectory()) + string filename = Path.Combine(tempFolder.Path, Path.GetRandomFileName()); + FileStreamOptions fileStreamOptions = new() { - string filename = Path.Combine(tempFolder.Path, Path.GetRandomFileName()); - File.WriteAllText(filename, "contents"); - - Interop.Sys.FileStatus status; - Assert.Equal(0, Interop.Sys.Stat(filename, out status)); - - expectedPermissions = Convert.ToString(status.Mode & 0xFFF, 8); + Access = FileAccess.Write, + Mode = FileMode.CreateNew + }; + if (expectedPermissions != null) + { + fileStreamOptions.UnixCreateMode = (UnixFileMode)Convert.ToInt32(expectedPermissions, 8); } - } + new FileStream(filename, fileStreamOptions).Dispose(); - return expectedPermissions; + return Convert.ToString((int)File.GetUnixFileMode(filename), 8); + } } [LibraryImport("libc", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] From d540d8fc1365f30294f640d94375a33f572c40c3 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 7 Jul 2022 12:50:31 +0200 Subject: [PATCH 3/5] PR feedback. --- .../src/System/Formats/Tar/TarEntry.cs | 64 ++++++++----------- ...pFileExtensions.ZipArchiveEntry.Extract.cs | 14 ++-- .../tests/ZipFile.Unix.cs | 6 +- 3 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index 39e80e84a5db8..5ee75900cf6e4 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -541,25 +541,8 @@ private void ExtractAsRegularFile(string destinationFileName) { Debug.Assert(!Path.Exists(destinationFileName)); - FileStreamOptions fileStreamOptions = new() - { - Access = FileAccess.Write, - Mode = FileMode.CreateNew, - Share = FileShare.None - }; - if (OperatingSystem.IsWindows()) - { - // On Windows, PreallocationSize gives a perf improvement. - fileStreamOptions.PreallocationSize = Length; - } - else - { - // Restore permissions. - // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). - fileStreamOptions.UnixCreateMode = Mode & (UnixFileMode)0x1FF; - } // Rely on FileStream's ctor for further checking destinationFileName parameter - using (FileStream fs = new FileStream(destinationFileName, fileStreamOptions)) + using (FileStream fs = new FileStream(destinationFileName, CreateFileStreamOptions(isAsync: false))) { if (DataStream != null) { @@ -579,37 +562,44 @@ private async Task ExtractAsRegularFileAsync(string destinationFileName, Cancell cancellationToken.ThrowIfCancellationRequested(); + // Rely on FileStream's ctor for further checking destinationFileName parameter + FileStream fs = new FileStream(destinationFileName, CreateFileStreamOptions(isAsync: true)); + await using (fs) + { + if (DataStream != null) + { + // Important: The DataStream will be written from its current position + await DataStream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); + } + } + + ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime); + } + + private FileStreamOptions CreateFileStreamOptions(bool isAsync) + { FileStreamOptions fileStreamOptions = new() { Access = FileAccess.Write, Mode = FileMode.CreateNew, Share = FileShare.None, PreallocationSize = Length, - Options = FileOptions.Asynchronous + Options = isAsync ? FileOptions.Asynchronous : FileOptions.None }; - if (OperatingSystem.IsWindows()) - { - // On Windows, PreallocationSize gives a perf improvement. - fileStreamOptions.PreallocationSize = Length; - } - else + + if (!OperatingSystem.IsWindows()) { + const UnixFileMode OwnershipPermissions = + UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | + UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | + UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute; + // Restore permissions. // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). - fileStreamOptions.UnixCreateMode = Mode & (UnixFileMode)0x1FF; - } - // Rely on FileStream's ctor for further checking destinationFileName parameter - FileStream fs = new FileStream(destinationFileName, fileStreamOptions); - await using (fs) - { - if (DataStream != null) - { - // Important: The DataStream will be written from its current position - await DataStream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); - } + fileStreamOptions.UnixCreateMode = Mode & OwnershipPermissions; } - ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime); + return fileStreamOptions; } } } diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs index 1499c28baacf7..c51c2075ff7da 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs @@ -74,15 +74,13 @@ public static void ExtractToFile(this ZipArchiveEntry source, string destination }; // Restore Unix permissions. - if (!OperatingSystem.IsWindows() && source.ExternalAttributes != 0) + // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). + // We don't apply UnixFileMode.None because .zip files created on Windows and .zip files created + // with previous versions of .NET don't include permissions. + UnixFileMode mode = (UnixFileMode)((source.ExternalAttributes >> 16) & 0x1FF); + if (mode != UnixFileMode.None && !OperatingSystem.IsWindows()) { - // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). - UnixFileMode mode = (UnixFileMode)((source.ExternalAttributes >> 16) & 0x1FF); - - if (mode != UnixFileMode.None) // .zip files created on Windows don't include permissions. - { - fileStreamOptions.UnixCreateMode = mode; - } + fileStreamOptions.UnixCreateMode = mode; } using (FileStream fs = new FileStream(destinationFileName, fileStreamOptions)) diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs index a7a39f149a2c7..37197ea4cfb02 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs +++ b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs @@ -15,7 +15,7 @@ public partial class ZipFile_Unix : ZipFileTestBase public void UnixCreateSetsPermissionsInExternalAttributes() { // '7600' tests that S_ISUID, S_ISGID, and S_ISVTX bits get preserved in ExternalAttributes - string[] testPermissions = new[] { "700", "755", "644", "600", "7600" }; + string[] testPermissions = new[] { "777", "755", "644", "600", "7600" }; using (var tempFolder = new TempDirectory(Path.Combine(GetTestFilePath(), "testFolder"))) { @@ -60,7 +60,7 @@ void EnsureExternalAttributes(string permissions, ZipArchiveEntry entry) public void UnixExtractSetsFilePermissionsFromExternalAttributes() { // '7600' tests that S_ISUID, S_ISGID, and S_ISVTX bits don't get extracted to file permissions - string[] testPermissions = new[] { "700", "755", "644", "754", "7600" }; + string[] testPermissions = new[] { "777", "755", "644", "754", "7600" }; string archivePath = GetTestFilePath(); using (FileStream fileStream = new FileStream(archivePath, FileMode.CreateNew)) @@ -126,6 +126,8 @@ private static string[] CreateFiles(string folderPath, string[] testPermissions) private static void EnsureFilePermissions(string filename, string permissions) { + permissions = GetExpectedPermissions(permissions); + Interop.Sys.FileStatus status; Assert.Equal(0, Interop.Sys.Stat(filename, out status)); From ae5d39b62d78833284a638807b3a6040e1445e48 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 7 Jul 2022 13:00:57 +0200 Subject: [PATCH 4/5] Replace const int with const UnixFileMode. --- .../ZipFileExtensions.ZipArchiveEntry.Extract.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs index c51c2075ff7da..f8152033f9477 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs @@ -73,11 +73,16 @@ public static void ExtractToFile(this ZipArchiveEntry source, string destination BufferSize = 0x1000 }; + const UnixFileMode OwnershipPermissions = + UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | + UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | + UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute; + // Restore Unix permissions. // For security, limit to ownership permissions, and respect umask (through UnixCreateMode). // We don't apply UnixFileMode.None because .zip files created on Windows and .zip files created // with previous versions of .NET don't include permissions. - UnixFileMode mode = (UnixFileMode)((source.ExternalAttributes >> 16) & 0x1FF); + UnixFileMode mode = (UnixFileMode)(source.ExternalAttributes >> 16) & OwnershipPermissions; if (mode != UnixFileMode.None && !OperatingSystem.IsWindows()) { fileStreamOptions.UnixCreateMode = mode; From 0e419e470ca307f0af20196e99839919cb6c8d92 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Fri, 8 Jul 2022 11:01:31 +0200 Subject: [PATCH 5/5] Also run tests with zero umask --- ...System.IO.Compression.ZipFile.Tests.csproj | 1 + .../tests/ZipFile.Unix.cs | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj b/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj index 7035c42d23e12..29c88cb2f9ce2 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj +++ b/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj @@ -2,6 +2,7 @@ true true + true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs index 37197ea4cfb02..25c41ead025d1 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs +++ b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Unix.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.IO.Compression.Tests @@ -56,6 +57,16 @@ void EnsureExternalAttributes(string permissions, ZipArchiveEntry entry) } } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void UnixCreateSetsPermissionsInExternalAttributesUMaskZero() + { + RemoteExecutor.Invoke(() => + { + umask(0); + new ZipFile_Unix().UnixCreateSetsPermissionsInExternalAttributes(); + }).Dispose(); + } + [Fact] public void UnixExtractSetsFilePermissionsFromExternalAttributes() { @@ -90,6 +101,16 @@ public void UnixExtractSetsFilePermissionsFromExternalAttributes() } } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void UnixExtractSetsFilePermissionsFromExternalAttributesUMaskZero() + { + RemoteExecutor.Invoke(() => + { + umask(0); + new ZipFile_Unix().UnixExtractSetsFilePermissionsFromExternalAttributes(); + }).Dispose(); + } + private static string[] CreateFiles(string folderPath, string[] testPermissions) { string[] expectedPermissions = new string[testPermissions.Length]; @@ -221,5 +242,8 @@ private static string GetExpectedPermissions(string expectedPermissions) [LibraryImport("libc", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] private static partial int mkfifo(string path, int mode); + + [LibraryImport("libc", StringMarshalling = StringMarshalling.Utf8)] + private static partial int umask(int umask); } }