Атрибуты файла C# xattr

Я создаю кроссплатформенное программное обеспечение и хочу знать, есть ли какой-либо (простой) способ чтения / записи расширенных атрибутов файлов Unix (Mac OSX/Linux) в C#. Я только что прочитал о xattr пространства имен, но я не нашел никакой информации о реализации C# или привязках этой функции.

PS Единственное, что я нашел до сих пор, это библиотека python-xattr, но я не хочу использовать ее, потому что:

  • Я не хочу обязывать пользователей устанавливать Python (уже существует зависимость от Mono/.NET)
  • При использовании Python у меня будет снижение производительности (C# компилируется, а Python интерпретируется)
  • Я не хочу полагаться / зависеть от внешних инструментов (если это возможно), потому что это небезопасно

2 ответа

Вы должны использовать системные вызовы в Mono.Unix.Native.Syscall.*attr*.
Сборка nuget называется https://www.nuget.org/packages/Mono.Posix.NETStandard.

Обратите внимание, что имя пары имя-значение имеет префикс пространства имен.
По словам человека 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://stackru.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 

Я думаю, что Mono.Unix.Native.Syscall.setxattr будет лучшим решением, которое находится в модуле Mono.Posix.

Окончательное решение может быть следующим, скажите мне, что вы думаете?

FileAttrsManager - абстрактный класс, используемый для создания 2 производных классов:

  • FileAttrsManagerDos: управляет расширенными атрибутами с помощью DSOFile.dll *
  • FileAttrsManagerUnix: управляет расширенными атрибутами, используя 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) и т.д.) будет управляться в статическом классе (FileAttrsProvider), который инициализирует объект FileAttrsManager одним из двух производных типов, а именно:

public static class FileAttrProvider
{

private static FileAttrReader _reader = null;

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

Хотя производный тип зависит от среды, исходный тип используется для обеспечения автоматической отправки всех вызовов методов объекта _reader).

Другие вопросы по тегам