-
Notifications
You must be signed in to change notification settings - Fork 5
Polyfill File.GetUnixFileMode, File.SetUnixFileMode, and Directory.CreateDirectory(path, UnixFileMode) #111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
4b6ca3e
Add File.Open(FileStreamOptions), FileStreamOptions, and UnixFileMode…
Copilot d8d1bc9
Add File.GetUnixFileMode, File.SetUnixFileMode, Directory.CreateDirec…
Copilot 1547be1
Use SkippableFact instead of #if PLATFORM_WINDOWS guards in Unix-only…
Copilot ff5342c
Dispose stream on throw, use field keyword, extract NativeMethods class
Copilot be9f4f8
Extract NativeMethods in File.cs, add UnsupportedOSPlatform, remove r…
Copilot c4a7d04
Update FileTests.cs
Tyrrrz 3c3ec1a
Update DirectoryTests.cs
Tyrrrz 12336bf
Update FileTests.cs
Tyrrrz 238bbe1
Update File.cs
Tyrrrz 73ede09
Make BufferSize and PreallocationSize setters arrow-bodied one-liners
Copilot d16a0ad
Add [UnsupportedOSPlatform("windows")] to Directory.CreateDirectory(p…
Copilot 3c28e53
Potential fix for pull request finding
Tyrrrz 16a5da0
Fix File.Open: only apply UnixCreateMode when file is newly created
Copilot 20e99db
Update File.cs
Tyrrrz b494632
Simplify File.Open pre-check: existed = File.Exists(path)
Copilot 7b422eb
Update Directory.cs
Tyrrrz 9538da5
Update File.cs
Tyrrrz ad182b9
Potential fix for pull request finding
Tyrrrz 8a0bf70
Fix formatting in Net60/File.cs: move class inside NETSTANDARD guard
Copilot 92e84b3
Update File.cs
Tyrrrz 1160e48
Apply umask-respecting chmod in File.Open UnixCreateMode handling
Copilot 4f08d31
Merge branch 'prime' into copilot/add-polyfill-file-open-methods
Tyrrrz 64ee3ef
Move FileStreamOptions.UnixCreateMode to Net70 extension member (poly…
Copilot 76ce4f5
Potential fix for pull request finding
Tyrrrz 79aaeb1
Update File.cs
Tyrrrz 6827c94
Update Directory.cs
Tyrrrz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| using System; | ||
| using System.IO; | ||
| using System.Runtime.Versioning; | ||
| using FluentAssertions; | ||
| using PolyShim.Tests.Utils.Extensions; | ||
| using Xunit; | ||
|
|
||
| namespace PolyShim.Tests.Net60; | ||
|
|
||
| public class FileTests | ||
| { | ||
| [Fact] | ||
| public void Open_Test() | ||
| { | ||
| // Arrange | ||
| var tempFilePath = Path.GetTempFileName(); | ||
| File.WriteAllBytes(tempFilePath, [0x00, 0x01, 0x02]); | ||
|
|
||
| try | ||
| { | ||
| var options = new FileStreamOptions(); | ||
|
|
||
| // Act | ||
| using var stream = File.Open(tempFilePath, options); | ||
|
|
||
| // Assert | ||
| stream.CanRead.Should().BeTrue(); | ||
| stream.Length.Should().Be(3); | ||
| } | ||
| finally | ||
| { | ||
| File.TryDelete(tempFilePath); | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Open_Write_Test() | ||
| { | ||
| // Arrange | ||
| var tempFilePath = Path.GetTempFileName(); | ||
|
|
||
| try | ||
| { | ||
| var options = new FileStreamOptions | ||
| { | ||
| Mode = FileMode.Create, | ||
| Access = FileAccess.Write, | ||
| Share = FileShare.None, | ||
| }; | ||
|
|
||
| // Act | ||
| using var stream = File.Open(tempFilePath, options); | ||
| stream.Write([0x0A, 0x0B, 0x0C], 0, 3); | ||
|
|
||
| // Assert | ||
| stream.CanWrite.Should().BeTrue(); | ||
| stream.Position.Should().Be(3); | ||
| } | ||
| finally | ||
| { | ||
| File.TryDelete(tempFilePath); | ||
| } | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Open_ReadWrite_Test() | ||
| { | ||
| // Arrange | ||
| var tempFilePath = Path.GetTempFileName(); | ||
| File.WriteAllBytes(tempFilePath, [0x00, 0x01, 0x02]); | ||
|
|
||
| try | ||
| { | ||
| var options = new FileStreamOptions | ||
| { | ||
| Mode = FileMode.Open, | ||
| Access = FileAccess.ReadWrite, | ||
| Share = FileShare.None, | ||
| }; | ||
|
|
||
| // Act | ||
| using var stream = File.Open(tempFilePath, options); | ||
|
|
||
| // Assert | ||
| stream.CanRead.Should().BeTrue(); | ||
| stream.CanWrite.Should().BeTrue(); | ||
| } | ||
| finally | ||
| { | ||
| File.TryDelete(tempFilePath); | ||
| } | ||
| } | ||
|
|
||
| [SkippableFact] | ||
| [UnsupportedOSPlatform("windows")] | ||
| public void Open_UnixFileMode_Test() | ||
| { | ||
| Skip.If(OperatingSystem.IsWindows()); | ||
|
|
||
| // Arrange | ||
| var tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); | ||
|
|
||
| try | ||
| { | ||
| var expectedMode = UnixFileMode.UserRead | UnixFileMode.UserWrite; | ||
|
|
||
| var options = new FileStreamOptions | ||
| { | ||
| Mode = FileMode.Create, | ||
| Access = FileAccess.Write, | ||
| Share = FileShare.None, | ||
| UnixCreateMode = expectedMode, | ||
| }; | ||
|
|
||
| // Act | ||
| using (var stream = File.Open(tempFilePath, options)) | ||
| stream.Write([0x0A, 0x0B], 0, 2); | ||
|
|
||
| // Assert | ||
| var actualMode = File.GetUnixFileMode(tempFilePath); | ||
| actualMode.Should().Be(expectedMode); | ||
| } | ||
| finally | ||
| { | ||
| File.TryDelete(tempFilePath); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| using System; | ||
| using System.IO; | ||
| using System.Runtime.Versioning; | ||
| using FluentAssertions; | ||
| using Xunit; | ||
|
|
||
| namespace PolyShim.Tests.Net70; | ||
|
|
||
| public class DirectoryTests | ||
| { | ||
| [SkippableFact] | ||
| [UnsupportedOSPlatform("windows")] | ||
| public void CreateDirectory_UnixFileMode_Test() | ||
| { | ||
| Skip.If(OperatingSystem.IsWindows()); | ||
|
|
||
| // Arrange | ||
| var tempDirPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); | ||
|
|
||
| try | ||
| { | ||
| var expectedMode = | ||
| UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute; | ||
|
|
||
| // Act | ||
| var info = Directory.CreateDirectory(tempDirPath, expectedMode); | ||
|
|
||
| // Assert | ||
| info.Should().NotBeNull(); | ||
| info.Exists.Should().BeTrue(); | ||
| File.GetUnixFileMode(tempDirPath).Should().Be(expectedMode); | ||
| } | ||
|
Tyrrrz marked this conversation as resolved.
|
||
| finally | ||
| { | ||
| if (Directory.Exists(tempDirPath)) | ||
| Directory.Delete(tempDirPath); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #if (NETCOREAPP && !NET6_0_OR_GREATER) || (NETFRAMEWORK) || (NETSTANDARD) | ||
| #nullable enable | ||
| #pragma warning disable CS0436 | ||
|
|
||
| // No file I/O on .NET Standard prior to 1.3 | ||
| #if !NETSTANDARD || NETSTANDARD1_3_OR_GREATER | ||
|
|
||
| using System; | ||
| using System.IO; | ||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| #if !POLYSHIM_INCLUDE_COVERAGE | ||
| [ExcludeFromCodeCoverage] | ||
| #endif | ||
| internal static class MemberPolyfills_Net60_File | ||
| { | ||
| extension(File) | ||
| { | ||
| // https://learn.microsoft.com/dotnet/api/system.io.file.open#system-io-file-open(system-string-system-io-filestreamoptions) | ||
| public static FileStream Open(string path, FileStreamOptions options) | ||
| { | ||
| var existed = File.Exists(path); | ||
|
|
||
| var stream = new FileStream( | ||
| path, | ||
| options.Mode, | ||
| options.Access, | ||
| options.Share, | ||
| options.BufferSize, | ||
| options.Options | ||
| ); | ||
|
|
||
| try | ||
| { | ||
| #if !NETFRAMEWORK || NET40_OR_GREATER | ||
| if ( | ||
| !existed | ||
| && !OperatingSystem.IsWindows() | ||
| && options.UnixCreateMode is { } unixCreateMode | ||
| && options.Mode | ||
| is FileMode.CreateNew | ||
| or FileMode.Create | ||
| or FileMode.OpenOrCreate | ||
| or FileMode.Append | ||
| ) | ||
| { | ||
| File.SetUnixFileMode(path, unixCreateMode & File.GetUnixFileMode(path)); | ||
| } | ||
| #endif | ||
| } | ||
| catch | ||
| { | ||
| stream.Dispose(); | ||
| throw; | ||
| } | ||
|
|
||
| return stream; | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| #if (NETCOREAPP && !NET6_0_OR_GREATER) || (NETFRAMEWORK) || (NETSTANDARD) | ||
| #nullable enable | ||
| #pragma warning disable CS0436 | ||
|
|
||
| // No file I/O on .NET Standard prior to 1.3 | ||
| #if !NETSTANDARD || NETSTANDARD1_3_OR_GREATER | ||
|
|
||
| using System; | ||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| namespace System.IO; | ||
|
|
||
| // https://learn.microsoft.com/dotnet/api/system.io.filestreamoptions | ||
| #if !POLYSHIM_INCLUDE_COVERAGE | ||
| [ExcludeFromCodeCoverage] | ||
| #endif | ||
| internal class FileStreamOptions | ||
| { | ||
| public FileMode Mode { get; set; } = FileMode.Open; | ||
|
|
||
| public FileAccess Access { get; set; } = FileAccess.Read; | ||
|
|
||
| public FileShare Share { get; set; } = FileShare.Read; | ||
|
|
||
| public int BufferSize | ||
| { | ||
| get; | ||
| set => field = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(value)); | ||
| } = 4096; | ||
|
|
||
| public FileOptions Options { get; set; } = FileOptions.None; | ||
|
|
||
| public long PreallocationSize | ||
| { | ||
| get; | ||
| set => field = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(value)); | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #if (NETCOREAPP && !NET7_0_OR_GREATER) || (NETFRAMEWORK) || (NETSTANDARD) | ||
| #nullable enable | ||
| #pragma warning disable CS0436 | ||
|
|
||
| using System; | ||
| using System.IO; | ||
| using System.Runtime.InteropServices; | ||
| using System.Runtime.Versioning; | ||
| using System.Diagnostics.CodeAnalysis; | ||
|
|
||
| // No file I/O on .NET Standard prior to 1.3 | ||
| #if !NETSTANDARD || NETSTANDARD1_3_OR_GREATER | ||
|
|
||
| file static class NativeMethods | ||
| { | ||
| [DllImport("libc", EntryPoint = "chmod", SetLastError = true)] | ||
| public static extern int Chmod(string path, uint mode); | ||
| } | ||
|
|
||
| #if !POLYSHIM_INCLUDE_COVERAGE | ||
| [ExcludeFromCodeCoverage] | ||
| #endif | ||
| internal static class MemberPolyfills_Net70_Directory | ||
| { | ||
| extension(Directory) | ||
| { | ||
| // https://learn.microsoft.com/dotnet/api/system.io.directory.createdirectory#system-io-directory-createdirectory(system-string-system-io-unixfilemode) | ||
| [UnsupportedOSPlatform("windows")] | ||
| public static DirectoryInfo CreateDirectory(string path, UnixFileMode unixCreateMode) | ||
|
Tyrrrz marked this conversation as resolved.
|
||
| { | ||
| if (OperatingSystem.IsWindows()) | ||
| throw new PlatformNotSupportedException(); | ||
|
|
||
| var existed = Directory.Exists(path); | ||
| var info = Directory.CreateDirectory(path); | ||
|
|
||
| if (!existed) | ||
| { | ||
| var effectiveMode = unixCreateMode & File.GetUnixFileMode(info.FullName); | ||
| if (NativeMethods.Chmod(info.FullName, (uint)effectiveMode) != 0) | ||
| { | ||
| throw new IOException( | ||
| $"Could not set Unix file mode for '{path}' (errno={Marshal.GetLastWin32Error()})." | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| return info; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
| #endif | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.