C# xattr 文件属性

发布于 2024-12-06 16:25:09 字数 342 浏览 5 评论 0原文

我正在创建一个跨平台软件,我想知道是否有任何(简单)方法可以在 C# 中读取/写入 Unix (Mac OSX/Linux) 扩展文件属性。 我刚刚阅读了有关 xattr 命名空间的内容,但尚未找到有关此功能的 C# 实现或绑定的任何信息。

PS 到目前为止我发现的唯一的东西是 python-xattr 库,但我不想使用它,因为:

  • 我不想强迫用户安装 Python (已经有 Mono/.NET 依赖项需要处理)
  • 通过使用Python,我的性能会下降(C#是编译的,而Python是解释的)
  • 我不想依赖/依赖外部工具(如果可能的话),因为它不安全

I'm creating a cross-platform software and I want to know if there is any (easy) way to read/write Unix (Mac OSX/Linux) extended file attributes in C#.
I've just read about xattr namespaces, but I haven't found any information about C# implementation or bindings of this feature.

P.S. The only thing I found so far is python-xattr library, but I don't want to use it because:

  • I don't want to obligate the users to install Python (there is already Mono/.NET dependency to deal with)
  • By using Python I will have a performance decrease (C# is compiled, while Python is interpreted)
  • I don't want to rely/depend on external tools (if it's possible), because it's not safe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

忆梦 2024-12-13 16:25:09

您应该使用 Mono.Unix.Native.Syscall.*attr* 中的系统调用。
nuget 程序集名为 Mono.Posix.NETStandard

请注意,名称-值对以名称空间为前缀。
根据man 7 xattr

目前,安全、系统、可信和用户扩展属性
类的定义如下所述。额外的课程可能是
将来添加。

public static void Test()
{
    string path = "/root/Desktop/CppSharp.txt";

    // Mono.Unix.Native.Syscall.getxattr()
    // Mono.Unix.Native.Syscall.fgetxattr()
    // Mono.Unix.Native.Syscall.lgetxattr()

    // Mono.Unix.Native.Syscall.setxattr()
    // Mono.Unix.Native.Syscall.fsetxattr()
    // Mono.Unix.Native.Syscall.lsetxattr

    // Mono.Unix.Native.Syscall.llistxattr()
    // Mono.Unix.Native.Syscall.flistxattr()
    // Mono.Unix.Native.Syscall.llistxattr()

    // Mono.Unix.Native.Syscall.removexattr()
    // Mono.Unix.Native.Syscall.fremovexattr()
    // Mono.Unix.Native.Syscall.lremovexattr()

    if (System.IO.File.Exists(path))
        System.Console.WriteLine("path exists");
    else
        System.Console.WriteLine("path doesn't exists");

    System.Text.Encoding enc = new System.Text.UTF8Encoding(false);
    string[] values = null;

    int setXattrSucceeded = Mono.Unix.Native.Syscall.setxattr(path, "user.foobar",
        enc.GetBytes("Hello World äöüÄÖÜ"), Mono.Unix.Native.XattrFlags.XATTR_CREATE);

    if (setXattrSucceeded == -1)
    {
        Mono.Unix.Native.Errno er = Mono.Unix.Native.Stdlib.GetLastError();
        string message = Mono.Unix.Native.Stdlib.strerror(er);
        // https://stackoverflow.com/questions/12662765/how-can-i-get-error-message-for-errno-value-c-language
        System.Console.WriteLine(message);
    } // End if (setXattrSucceeded == -1)

    byte[] data = null;
    long szLen = Mono.Unix.Native.Syscall.getxattr(path, "user.foobar", out data);

    string value = enc.GetString(data);
    System.Console.WriteLine(value);

    Mono.Unix.Native.Syscall.listxattr(path, System.Text.Encoding.UTF8, out values);
    System.Console.WriteLine(values);

    // https://man7.org/linux/man-pages/man2/getxattr.2.html
} // End Sub TestExtendedAttributes 

You should use the syscalls in Mono.Unix.Native.Syscall.*attr*.
The nuget assembly is called Mono.Posix.NETStandard

Note that the name of the name-value pair is prefixed with a namespace.
According to man 7 xattr

Currently, the security, system, trusted, and user extended attribute
classes are defined as described below. Additional classes may be
added in the future.

public static void Test()
{
    string path = "/root/Desktop/CppSharp.txt";

    // Mono.Unix.Native.Syscall.getxattr()
    // Mono.Unix.Native.Syscall.fgetxattr()
    // Mono.Unix.Native.Syscall.lgetxattr()

    // Mono.Unix.Native.Syscall.setxattr()
    // Mono.Unix.Native.Syscall.fsetxattr()
    // Mono.Unix.Native.Syscall.lsetxattr

    // Mono.Unix.Native.Syscall.llistxattr()
    // Mono.Unix.Native.Syscall.flistxattr()
    // Mono.Unix.Native.Syscall.llistxattr()

    // Mono.Unix.Native.Syscall.removexattr()
    // Mono.Unix.Native.Syscall.fremovexattr()
    // Mono.Unix.Native.Syscall.lremovexattr()

    if (System.IO.File.Exists(path))
        System.Console.WriteLine("path exists");
    else
        System.Console.WriteLine("path doesn't exists");

    System.Text.Encoding enc = new System.Text.UTF8Encoding(false);
    string[] values = null;

    int setXattrSucceeded = Mono.Unix.Native.Syscall.setxattr(path, "user.foobar",
        enc.GetBytes("Hello World äöüÄÖÜ"), Mono.Unix.Native.XattrFlags.XATTR_CREATE);

    if (setXattrSucceeded == -1)
    {
        Mono.Unix.Native.Errno er = Mono.Unix.Native.Stdlib.GetLastError();
        string message = Mono.Unix.Native.Stdlib.strerror(er);
        // https://stackoverflow.com/questions/12662765/how-can-i-get-error-message-for-errno-value-c-language
        System.Console.WriteLine(message);
    } // End if (setXattrSucceeded == -1)

    byte[] data = null;
    long szLen = Mono.Unix.Native.Syscall.getxattr(path, "user.foobar", out data);

    string value = enc.GetString(data);
    System.Console.WriteLine(value);

    Mono.Unix.Native.Syscall.listxattr(path, System.Text.Encoding.UTF8, out values);
    System.Console.WriteLine(values);

    // https://man7.org/linux/man-pages/man2/getxattr.2.html
} // End Sub TestExtendedAttributes 
扛起拖把扫天下 2024-12-13 16:25:09

我认为 Mono.Unix.Native.Syscall.setxattr 将是一个更好的解决方案,它位于 Mono.Posix 模块中。

I think Mono.Unix.Native.Syscall.setxattr would be a better solution, which is in Mono.Posix module.

山有枢 2024-12-13 16:25:09

最终的解决方案可能如下,请告诉我你的想法是什么?

FileAttrsManager 是一个抽象类,用于创建 2 个派生类:

  • FileAttrsManagerDos:使用 DSOFile.dll* 管理高级属性
  • FileAttrsManagerUnix:使用 DSOFile.dll 管理高级属性IronPython* 和 python-xattr**

[ * ] http:\\www.microsoft.com/download/en/details.aspx?displaylang=en&id=8422
[ ** ] http:\\ironpython.codeplex.com
[ ** * ] http:\\pypi.python.org/pypi/xatt

扩展属性操作(如SetPropery(string key, object value)GetProperty(string key) code> 等)将在静态类 (FileAttrsProvider) 中进行管理,该静态类将 FileAttrsManager 对象初始化为两种派生类型之一,即:

public static class FileAttrProvider
{

    private static FileAttrReader _reader = null;

    public static void Initialize()
    {
        switch (Environment.OSVersion.Platform)
        {
            case PlatformID.MacOSX:
            case PlatformID.Unix:
                _reader = new FileAttrReaderUnix();
                break;
            case PlatformID.Win32NT:
                _reader = new FileAttrReaderDos();
                break;
        }
    }
}

虽然派生类型取决于环境,原来的使用类型是为了确保自动调度 _reader 对象上的所有方法调用)。

The final solution might be the following, tell me what do you think?

FileAttrsManager is an abstract class, used to create 2 derived classes:

  • FileAttrsManagerDos: manages advanced attributes using DSOFile.dll*
  • FileAttrsManagerUnix: manages advanced attributes using IronPython* and python-xattr**

[ * ] http:\\www.microsoft.com/download/en/details.aspx?displaylang=en&id=8422
[ ** ] http:\\ironpython.codeplex.com
[ ** * ] http:\\pypi.python.org/pypi/xatt

Extended attributes operation (such as SetPropery(string key, object value) and GetProperty(string key) etc) will be managed in a static class (FileAttrsProvider) that initializes a FileAttrsManager object to one of two derived types i.e.:

public static class FileAttrProvider
{

    private static FileAttrReader _reader = null;

    public static void Initialize()
    {
        switch (Environment.OSVersion.Platform)
        {
            case PlatformID.MacOSX:
            case PlatformID.Unix:
                _reader = new FileAttrReaderUnix();
                break;
            case PlatformID.Win32NT:
                _reader = new FileAttrReaderDos();
                break;
        }
    }
}

While the derived type depends on the environment, the original type is used in order to ensure an automatic dispatch of all the methods call on _reader object).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文