首页 > 解决方案 > 使用 .NET Core 在 Linux 上更改文件所有者

问题描述

获取文件所有者使用

new System.Security.AccessControl.FileSecurity(filename, AccessControlSections.Owner);

System.PlatformNotSupportedException:访问控制列表 (ACL) API 是 Windows 资源管理的一部分,在此平台上不受支持

所以改变也不能以这种方式进行。

标签: linux.net-core

解决方案


添加包

Mono.Posix.NETStandard

并使用包装器chown(3)

注意:如果调用 not as 则chown失败,因为所有 linux 限制都有效)。EPERMroot

using Mono.Unix.Native;
...

var passwd = Syscall.getpwnam("nobody");
if (passwd == null)
{
    var errno = Syscall.GetLastError();   
    switch (errno)
    {
        case Errno.ENOENT:
            throw new KeyNotFoundException("No user corresponding to uid.");
        case Errno.ESRCH:
            throw new IOException("ESRCH");
        case Errno.EBADF:
            throw new IOException("EBADF");
        case Errno.EPERM:
            throw new UnauthorizedAccessException("The effective user ID does not match the owner of the file, or the calling process does not have appropriate privileges and _POSIX_CHOWN_RESTRICTED indicates that such privilege is required.");
        case Errno.EIO:
            throw new IOException("An I/O error occurred while reading or writing to the file system.");
        case Errno.EMFILE:
            throw new IOException("The maximum number (OPEN_MAX) of files was open already in the calling process.");
        case Errno.ENFILE:
            throw new KeyNotFoundException("The maximum number of files was open already in the system.");
        case Errno.ENOMEM:
            throw new InsufficientMemoryException("Insufficient memory to allocate passwd structure.");
        case Errno.ERANGE:
            throw new Exception("Insufficient buffer space supplied.");
        case Errno.EINTR:
            throw new IOException("The getpwnam() function was interrupted by a signal which was caught.");
        default:
            throw new Exception($"Unknown exception during chown, errno: {errno}.");
    }
}
if (0 != Syscall.chown(fileInfo.FullName, passwd.pw_uid, passwd.pw_gid))
{
    var errno = Syscall.GetLastError();
    switch (errno)
    {
        case Errno.EACCES:
            throw new UnauthorizedAccessException("Search permission is denied on a component of the path prefix.");
        case Errno.ELOOP:
            throw new IOException("A loop exists in symbolic links encountered during resolution of the path argument. More than {SYMLOOP_MAX} symbolic links were encountered during resolution of the path argument.");
        case Errno.ENAMETOOLONG:
            throw new PathTooLongException("The length of the path argument exceeds {PATH_MAX} or a pathname component is longer than {NAME_MAX}. As a result of encountering a symbolic link in resolution of the path argument, the length of the substituted pathname string exceeded {PATH_MAX}.");
        case Errno.ENOTDIR:
            throw new DirectoryNotFoundException("A component of the path prefix is not a directory.");
        case Errno.ENOENT:
            throw new FileNotFoundException("A component of path does not name an existing file or path is an empty string.");
        case Errno.EPERM:
            throw new UnauthorizedAccessException("The effective user ID does not match the owner of the file, or the calling process does not have appropriate privileges and _POSIX_CHOWN_RESTRICTED indicates that such privilege is required.");
        case Errno.EROFS:
            throw new IOException("The named file resides on a read-only file system.");
        case Errno.EIO:
            throw new IOException("An I/O error occurred while reading or writing to the file system.");
        case Errno.EINTR:
            throw new IOException("The chown() function was interrupted by a signal which was caught.");
        case Errno.EINVAL:
            throw new NotSupportedException("The owner or group ID supplied is not a value supported by the implementation.");
        default:
            throw new Exception($"Unknown exception during getpwnam, errno: {errno}.");
    }
}

推荐阅读