dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.67k stars 4.58k forks source link

[API Proposal]: APIs for working with unix file types #85148

Open tmds opened 1 year ago

tmds commented 1 year ago

Background and motivation

Make it possible for getting Unix file types.

Sometimes it is desired to identify certain types of files. .NET uses an internal enum for this.

This proposal provides a public API, similar in style as the one added for unix file modes in .NET 7.

API Proposal

namespace System.IO;
public enum UnixFileType
{
    RegularFile,
    Directory,
    SymbolicLink,
    CharacterDevice,
    BlockDevice,
    Socket,
    Fifo,
}
class File
{
    public static UnixFileType GetUnixFileType(SafeFileHandle fileHandle);
    public static UnixFileType GetUnixFileType(string path);
}
class FileSystemInfo
{
    public UnixFileType UnixFileType { get; }
}

namespace System.IO.Enumeration;
struct FileSystemEntry
{
    public UnixFileType UnixFileType { get; }
}

API Usage

FileSystemInfo fsi = ...;
switch (fsi.UnixFileType)
{
   case UnixFileType.RegularFile:
        ...
}

Alternative Designs

No response

Risks

No response

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-system-io See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation Make it possible for getting Unix file types. Sometimes it is desired to identify certain types of files. .NET uses an internal enum for this. This proposal provides a public API, similar in style as the one added for unix file modes in .NET 7. ### API Proposal ```cs namespace System.IO; public enum UnixFileType { RegularFile, Directory, SymbolicLink, CharacterDevice, BlockDevice, Socket, Fifo, } class File { public static UnixFileType GetUnixFileType(SafeFileHandle fileHandle) { throw null; } public static UnixFileType GetUnixFileType(string path) { throw null; } } class FileSystemInfo { public UnixFileType UnixFileType { get; } } namespace System.IO.Enumeration; struct FileSystemEntry { public UnixFileType UnixFileType { get; } } ``` ### API Usage ```csharp FileSystemInfo fsi = ...; switch (fsi.UnixFileType) { case UnixFileType.RegularFile: ... } ``` ### Alternative Designs _No response_ ### Risks _No response_
Author: tmds
Assignees: -
Labels: `api-suggestion`, `area-System.IO`, `untriaged`
Milestone: -
tmds commented 1 year ago

cc @eerhardt @stephentoub @carlossanlop @adamsitnik

adamsitnik commented 1 year ago

@tmds Windows offers a very similar set of file types, perhaps we should just call the enum FileType and make it work on every OS?

tmds commented 1 year ago

Can you share some links to the related Windows API docs?

danmoseley commented 1 year ago

https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfiletype gives some.

For differentiating reparse points https://learn.microsoft.com/en-us/windows/win32/fileio/determining-whether-a-directory-is-a-volume-mount-point?source=recommendations

It may be the enumeration will need some Windows-specific entries as well.

https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags

Cc @jeremykuhne

adamsitnik commented 1 year ago

Can you share some links to the related Windows API docs?

@danmoseley provided the right links, we are already using GetFileType in SFH:

https://github.com/dotnet/runtime/blob/ed33e6c1ebfe9ae78a2a01a11a01c575f5dad747/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs#L254-L268

I can see that Windows maps FILE_TYPE_PIPE to not only socket but also anonymous and named pipes. We could most probably check the file path to see if it's a pipe (they all start with \\.\pipe\) and use this hacky way.

adamsitnik commented 1 year ago

Related: https://github.com/dotnet/runtime/issues/62868

tmds commented 11 months ago

I've just looked through these docs, and I wonder if it makes sense to put these in a single enum.

I think the main use-case of UnixFileType is to identify files found in a file system, for example: while enumerating.

Because GetFileType takes a handle, I assume it is more used when already having a handle and for example verifying the type for some operation. The types returned are probably not (commonly) found on a Windows file system.

The reparse point type use-cases seem similar to the UnixFileType, but the lack of overlap doesn't encourage to put them in a single enum.