module fanotify_wrapper; public import fanotify; import core.sys.posix.unistd : read, close, ssize_t; import core.sys.posix.fcntl : O_RDONLY, O_RDWR, O_LARGEFILE, AT_FDCWD; import std.exception : enforce; import std.string : toStringz; import std.conv : to; import core.stdc.stdint; // uint64_t и т.п. // Структура для представления события (упрощённая) struct FanotifyEvent { fanotify_event_metadata meta; @property uint64_t mask() const { return meta.mask; } @property int eventFd() const { return meta.fd; } @property int pid() const { return meta.pid; } // Проверка конкретных событий для удобства bool isOpen() const { return (mask & FAN_OPEN) != 0; } bool isModify() const { return (mask & FAN_MODIFY) != 0; } bool isCloseWrite() const { return (mask & FAN_CLOSE_WRITE) != 0; } bool isCloseNoWrite() const { return (mask & FAN_CLOSE_NOWRITE) != 0; } bool isAccess() const { return (mask & FAN_ACCESS) != 0; } // Добавьте другие по необходимости } // Класс для работы с fanotify class Fanotify { private int fd = -1; this(uint initFlags, uint eventFFlags = O_RDONLY | O_LARGEFILE) { fd = fanotify_init(initFlags, eventFFlags); enforce(fd >= 0, "Ошибка инициализации fanotify: " ~ to!string(fd)); } ~this() { if (fd >= 0) { close(fd); fd = -1; } } // Маркировка пути (директории или файла) void mark(uint markFlags, uint64_t eventMask, int dirFd = AT_FDCWD, string path = null) { const(char)* cPath = path ? path.toStringz() : null; int res = fanotify_mark(fd, markFlags, eventMask, dirFd, cPath); enforce(res == 0, "Ошибка маркировки fanotify: " ~ to!string(res)); } // Чтение событий (блокирующее или неблокирующее в зависимости от FAN_NONBLOCK) FanotifyEvent[] readEvents(size_t bufferSize = 4096) { ubyte[] buffer = new ubyte[bufferSize]; ssize_t len = read(fd, buffer.ptr, buffer.length); if (len <= 0) { return []; } FanotifyEvent[] events; size_t offset = 0; while (offset + FAN_EVENT_METADATA_LEN <= len) { auto meta = cast(fanotify_event_metadata*)(buffer.ptr + offset); if (meta.event_len < FAN_EVENT_METADATA_LEN || offset + meta.event_len > len) { break; } events ~= FanotifyEvent(*meta); offset += meta.event_len; } return events; } // Получение дескриптора для расширенного использования (если нужно) @property int handle() const { return fd; } }