在Linux操作系统中,文件权限的管理是一个常见的需求。在Ubuntu 16.04 i386版本上,可能会遇到使用System.Security.AccessControl.FileSecurity更改文件权限时出现'Not supported on this platform'的错误。为了解决这个问题,可以构建一个简单的chmod命令封装。
这个封装的想法始于需要为自定义生成的Chrome应用桌面启动器提供执行权限。虽然可以使用下面的代码,但还有其他不同的场景需要考虑,这就催生了简单封装。
System.Diagnostic.Process.Start(
"chmod",
"755 $APPNAME$"
);
将要查看的类如下所示。如果不熟悉chmod,可以查看。
1. enum FileAccess.cs
。FileAccess
代表chmod的单个八进制值(3个中的1个)。
using System;
namespace Linux.FileSecurity
{
public enum FileAccess
{
None = 0,
Execute = 1,
Write = 2,
Read = 4,
}
}
2. struct FilePermissionFlag.cs
。FilePermissionFlag
代表chmod所需的3个八进制值U(ser),G(roup),O(ther)。
using System;
namespace Linux.FileSecurity
{
public struct FilePermissionFlag
{
public FileAccess User { get; private set; }
public FileAccess Group { get; private set; }
public FileAccess Others { get; private set; }
internal FilePermissionFlag(FileAccess user, FileAccess group, FileAccess others)
{
this.User = FilePermissionFlag.ToValidAccess(user);
this.Group = FilePermissionFlag.ToValidAccess(group);
this.Others = FilePermissionFlag.ToValidAccess(others);
}
public static FileAccess ToValidAccess(FileAccess access)
{
int num = (int)access;
return (FileAccess)(num < 0 ? 0 : num > 7 ? 7 : num);
}
}
}
3. static class KnownAccess.cs
。KnownAccess
包含已知的FileAccess
值。注意缺失FileAccess.Execute
(写代码时的疏忽)。
using System;
namespace Linux.FileSecurity
{
public static class KnownAccess
{
public static readonly FileAccess None = FileAccess.None;
public static readonly FileAccess Read = FileAccess.Read;
public static readonly FileAccess Write = FileAccess.Write;
public static readonly FileAccess Execute = FileAccess.Execute;
public static readonly FileAccess Read_Write = FileAccess.Read | FileAccess.Write;
public static readonly FileAccess Read_Execute = FileAccess.Read | FileAccess.Execute;
public static readonly FileAccess Write_Execute = FileAccess.Write | FileAccess.Execute;
public static readonly FileAccess Read_Write_Execute = FileAccess.Read | FileAccess.Write | FileAccess.Execute;
}
}
4. sealed class FilePermission.cs
。FilePermission
接受文件路径,并使用给定的FilePermissionFlag
对文件运行chmod。
using System;
namespace Linux.FileSecurity
{
public sealed class FilePermission
{
const string File = "chmod";
public string Process { get; private set; }
public FilePermissionFlag Flags { get; private set; }
public override string ToString()
{
return string.Format("{0}{1}{2} {3}",
(int)FilePermissionFlag.ToValidAccess(Flags.User),
(int)FilePermissionFlag.ToValidAccess(Flags.Group),
(int)FilePermissionFlag.ToValidAccess(Flags.Others),
Process);
}
public FilePermission(string filePath)
{
if (!System.IO.File.Exists(filePath))
throw new System.IO.FileLoadException("error loading " + filePath, filePath);
this.Process = filePath;
}
public FilePermission(FilePermission permission, FileAccess user, FileAccess group, FileAccess others)
: this(permission.Process, user, group, others) { }
public static FilePermission SetPermission(string filePath, FileAccess user, FileAccess group, FileAccess others)
{
FilePermission permission = new FilePermission(filePath);
permission.Flags = new FilePermissionFlag(user, group, others);
return permission.Apply();
}
public void Apply(FileAccess user, FileAccess group, FileAccess others)
{
this.Flags = new FilePermissionFlag(user, group, others);
this.Apply();
}
private FilePermission Apply()
{
if (string.IsNullOrWhiteSpace(Process) || string.IsNullOrEmpty(Process))
{
Console.WriteLine("File name cannot be empty.");
return null;
}
if (!System.IO.File.Exists(Process))
{
Console.WriteLine("Error finding file " + Process + ".");
return null;
}
try
{
string permission = this.ToString();
System.Diagnostics.ProcessStartInfo filePermission = new System.Diagnostics.ProcessStartInfo(FilePermission.File, permission);
System.Diagnostics.Process.Start(filePermission);
return this;
}
catch
{
return null;
}
}
}
}