runtime icon indicating copy to clipboard operation
runtime copied to clipboard

Need a point to expose platform specific IO information

Open JeremyKuhne opened this issue 7 years ago • 7 comments
trafficstars

There is a need to get platform specific information regarding files. Some data can be abstracted cross plat relatively easily, but other info cannot.

One possibility is to add interfaces to FileSystemInfo, etc in only the specific platform implementations that expose platform level details that are already internally available. Something like the following:

namespace System.IO.Unix
{
    public interface IUnixFileSystemInfo
    {
        public FileStatus { get; }
    }
    
    public struct FileStatus
    {
        public FileStatusFlags Flags;
        public FileTypes Mode;
        public uint Uid;
        public uint Gid;
        public long Size;
        public long ATime;
        public long MTime;
        public long CTime;
        public long BirthTime;
        public long Dev;
        public long Ino;
    }

    [Flags]
    public enum FileStatusFlags
    {
        None = 0,
        HasBirthTime = 1,
    }
    
    [Flags]
    public enum FileTypes
    {
        S_IFMT = 0xF000;
        S_IFIFO = 0x1000;
        S_IFCHR = 0x2000;
        S_IFDIR = 0x4000;
        S_IFREG = 0x8000;
        S_IFLNK = 0xA000;
        S_IFSOCK = 0xC000;
    }
}

namespace System.IO.Windows
{
    public interface IWindowsFileSystemInfo
    {
        public uint GetReparsePointType();
    }
}

@weshaggard What are the implications of implementing interfaces that we don't expose in the ref assembly? (e.g. FileSystemInfo would not derive from IWindowsFileSystemInfo in the ref assembly) Would it be better to add a method to FSI? Something like T TryGetInterface<T>()?

JeremyKuhne avatar Jan 17 '18 20:01 JeremyKuhne

@pjanotti Fyi

JeremyKuhne avatar Jan 17 '18 21:01 JeremyKuhne

@weshaggard What are the implications of implementing interfaces that we don't expose in the ref assembly?

I assume you mean the interfaces don't show on FileSystemInfo but the interface itself is exposed in the contract? Nothing bad really happens in that case. We just need to be sure whatever is exposed in the contract for FileSystemInfo is implemented on all implementations.

weshaggard avatar Jan 17 '18 22:01 weshaggard

The Unix specific APIs for working with files are available in Mono.Posix library today: http://docs.go-mono.com/?link=T%3aMono.Posix.Stat%2f* Mono team has done the work to build .NET Core-compatible version of Mono.Posix (https://github.com/mono/mono/pull/4774). Is there a reason why the folks who really need these APIs cannot use Mono.Posix?

jkotas avatar Jan 18 '18 06:01 jkotas

In PowerShell we get a file owner too.

iSazonov avatar May 29 '18 09:05 iSazonov

Is there a reason why the folks who really need these APIs cannot use Mono.Posix?

@jkotas

Point here would be to leverage existing logic in CoreFX for relatively simple needs (if (unix) /* one-off logic */) without resorting to p/invoking or taking larger dependencies. It has been brought up to me a few times offline, I wanted a recorded discussion of possible approaches and a place to both get a feel for desirability for getting access to platform specific internals (things we can't abstract) and to point people to who bring it up.

Being built around Windows originally there isn't much Windows specific stuff that we're not already exposing. The one bit (that I've called out above) is the reparse point type.

JeremyKuhne avatar May 29 '18 18:05 JeremyKuhne

Exposing file stats primitives that already exist in CoreFX would be valuable. Regarding Unix file permissions, following APIs can be handy in certain cases for downstream users:

public struct FileStatus
{
    // ... based on the (original) `int Mode` which we get from syscall ...

    // st_mode is typically a 16-bits value, high 4 bits are filetype and low 12
    // bits are permission. we will clear first 20 bits (a byte and a nibble) with
    // the following mask:
    public int Permissions => Mode & 0x1ff;
    // returns 0 to 511 in decimal (i.e. 0 to 777 in octal)

    public string GetPermissionsAsString()
    {
        Span<char> chars = stackalloc char[10];
        
        chars[0] = '-';
        chars[1] = (Mode & 256) != 0 ? 'r' : '-';
        chars[2] = (Mode & 128) != 0 ? 'w' : '-';
        chars[3] = (Mode &  64) != 0 ? 'x' : '-';
        chars[4] = (Mode &  32) != 0 ? 'r' : '-';
        chars[5] = (Mode &  16) != 0 ? 'w' : '-';
        chars[6] = (Mode &   8) != 0 ? 'x' : '-';
        chars[7] = (Mode &   4) != 0 ? 'r' : '-';
        chars[8] = (Mode &   2) != 0 ? 'w' : '-';
        chars[9] = (Mode &   1) != 0 ? 'x' : '-';
        
        return new string(chars);
    }
    // returns -rw-r--r--,  -rwxrwxrwx,  etc.
}

am11 avatar Oct 18 '19 08:10 am11

@tmds has implemented UnixFileMode APIs in https://github.com/dotnet/runtime/pull/69980 for .NET 7. For the remaining file status members (ATime, BirthTime, Device etc.), please update the proposed API in top post.

@tmds, @adamsitnik, any thoughts on this proposal?

am11 avatar Sep 20 '22 08:09 am11