[API Proposal]: Add SafeFileHandle constructor with isLocked and deleteOnClose
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Background and motivation
I'm creating custom methods to open files/directories - the reason is to support opening a file by a root directory handle and a relative path (`openat` on Unix, `NtCreateFile` on Windows), and I'd like these methods to return a `SafeFileHandle`, not a custom handle type. On Windows, since all the options and flags are directly supported by the operating system, there is no problem with using `new SafeFileHandle(handle, ownsHandle: true)`, but on Unix, if I create a handle this way, `_isLocked` and `_deleteOnClose` will always be false, meaning that if I lock the file for `FileShare` the same way .NET does, the disposal won't unlock the file, and `DeleteOnClose` won't be supported either. In previous .NET versions such as .NET 5, `SafeFileHandle` disposal on Unix unlocked the file unconditionally, but now, `_isLocked` defaults to false, which is a regression. In any case, the only solution currently is to use reflection/unsafe access to set these fields.
To fully support this scenario, I need a new constructor on `SafeFileHandle` that accepts whether the file is locked and whether it should be deleted on close. This constructor would only be supported on Unix.
### API Proposal
```csharp
namespace Microsoft.Win32.SafeHandles;
public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
{
[UnsupportedOSPlatform("windows")]
public SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle, bool isLocked, bool deleteOnClose);
}
```
### API Usage
```csharp
// Create a file handle using custom PInvoke and set the appropriate locking, and check if `DeleteOnClose` is true;
var handle = new SafeFileHandle(handle, ownsHandle: true, isLocked, (options & FileOptions.DeleteOnClose) != 0);
````
### Alternative Designs
The only alternative is to unseal the class, so that I can do everything appropriately on my own.
```diff
namespace Microsoft.Win32.SafeHandles;
-public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
+public partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
{
}
```
### Risks
I don't know.
Contributor guide
Assessment
This issue has not been assessed yet.