// Модуль app.d // Это основное приложение, демонстрирующее использование обёртки fanotify_wrapper. // Инициализирует fanotify, маркирует директорию /tmp/scripts для мониторинга событий (открытие, модификация и т.д.), // затем в бесконечном цикле читает события и выводит информацию о них в консоль. // Импорты: fanotify_wrapper - обёртка, std.stdio для вывода, std.file для readLink (хотя здесь не используется из-за режима), // std.format для форматирования строк, core.sys.posix для констант. import fanotify_wrapper; // Импорт обёртки для fanotify. import std.stdio; // Импорт для writeln, writefln (вывод в консоль). import std.file : readLink; // Импорт readLink для чтения симлинков (не используется здесь, но оставлено для возможного расширения). import std.format : format; // Импорт format для форматирования строк (хотя здесь используется writefln напрямую). import core.sys.posix.fcntl : AT_FDCWD; // Импорт AT_FDCWD для текущей директории. import core.sys.posix.unistd : close; // Импорт close (не используется здесь, но для возможного расширения с fd). // Функция main: точка входа приложения. void main() { // Инициализация объекта Fanotify с флагами: // FAN_CLASS_NOTIF - режим уведомлений (без контроля доступа), // FAN_CLOEXEC - закрытие дескриптора при exec, // FAN_REPORT_FID | FAN_REPORT_DIR_FID | FAN_REPORT_NAME - отчёт с FID (идентификатор файла) вместо fd, плюс имя файла. // Это позволяет получать имя без реального fd (fd будет FAN_NOFD). auto fan = new Fanotify( FAN_CLASS_NOTIF | FAN_CLOEXEC | FAN_REPORT_FID | FAN_REPORT_DIR_FID | FAN_REPORT_NAME); // Определение маски событий: битовая OR флагов для мониторинга. // FAN_OPEN - открытие, FAN_MODIFY - модификация, FAN_CLOSE - закрытие (включает WRITE и NOWRITE), // FAN_CREATE - создание, FAN_DELETE - удаление, FAN_EVENT_ON_CHILD - события в поддиректориях. auto eventMask = FAN_OPEN | FAN_MODIFY | FAN_CLOSE | FAN_CREATE | FAN_DELETE | FAN_EVENT_ON_CHILD; // Маркировка директории /tmp/scripts: // FAN_MARK_ADD - добавить марку, FAN_MARK_ONLYDIR - только для директории (ошибка, если не директория). // AT_FDCWD - базовая директория текущая, путь "/tmp/scripts". fan.mark(FAN_MARK_ADD | FAN_MARK_ONLYDIR, eventMask, AT_FDCWD, "/tmp/scripts"); writeln("Мониторинг запущен для /tmp/scripts..."); // Вывод сообщения о старте мониторинга. // Бесконечный цикл: постоянно читает события и обрабатывает их. while (true) { auto events = fan.readEvents(); // Чтение событий (блокирующее, ждёт до появления событий). foreach (ref e; events) // Цикл по каждому событию в массиве. { // Определение пути: если name извлечено (из FAN_REPORT_NAME), использовать его; иначе "unknown". // name - относительное имя файла/директории относительно маркированной. string path = e.name.length ? e.name : "unknown"; // Используем извлечённое имя (относительное) // Комментарий: в режиме с FAN_REPORT_FID fd = FAN_NOFD, так что нельзя использовать readLink("/proc/self/fd/" ~ to!string(e.eventFd)) для полного пути. // fd теперь FAN_NOFD, так что пропускаем readLink/close // Вывод общей информации о событии: маска в hex, PID, путь/имя. writefln("Событие: mask=0x%x, pid=%d, name/path=%s", e.mask, e.pid, path); // Проверки и вывод конкретных типов событий с использованием методов структуры. if (e.isOpen) // Если открытие. writeln(" - Открытие файла"); if (e.isModify) // Если модификация. writeln(" - Модификация файла"); if (e.isCloseWrite) // Если закрытие после записи. writeln(" - Закрытие после записи"); if (e.isCloseNoWrite) // Если закрытие без записи. writeln(" - Закрытие без записи"); if (e.isCreate) // Если создание. writeln(" - Создание файла/директории"); if (e.isDelete) // Если удаление. writeln(" - Удаление файла/директории"); } } }