// Low-level wrapper over the C API fanotify for D. // All values are taken from uapi // Низкоуровневая обёртка над C API fanotify для D. // Все значения взяты из uapi module fanotify; import core.stdc.stdint; // uint64_t and similar // uint64_t и т.п. // FLAGS FOR fanotify_init(flags, event_f_flags) // ФЛАГИ ДЛЯ fanotify_init(flags, event_f_flags) // File descriptor group behavior // Поведение файлового дескриптора группы // Close fd on exec() enum FAN_CLOEXEC = 0x0000_0001; // Закрывать fd при exec() // Non-blocking read() enum FAN_NONBLOCK = 0x0000_0002; // Неблокирующие read() // Group class (defines the type of issued events) // Класс группы (определяет тип выдаваемых событий) // Notifications only (not PERM) enum FAN_CLASS_NOTIF = 0x0000_0000; // Только уведомления (не PERM) // Permissions for access to CONTENT enum FAN_CLASS_CONTENT = 0x0000_0004; // Разрешения на доступ к СОДЕРЖИМОМУ (CONTENT) // Permissions BEFORE access to content (PRE_CONTENT) enum FAN_CLASS_PRE_CONTENT = 0x0000_0008; // Разрешения ДО доступа к содержимому (PRE_CONTENT) deprecated enum FAN_ALL_CLASS_BITS = (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT); // Queue/mark limits // Лимиты очереди/меток // Unlimited event queue enum FAN_UNLIMITED_QUEUE = 0x0000_0010; // Неограниченная очередь событий // Unlimited number of marks enum FAN_UNLIMITED_MARKS = 0x0000_0020; // Неограниченное число меток // Enable audit enum FAN_ENABLE_AUDIT = 0x0000_0040; // Включить аудит // Reporting format in event metadata // Формат отчётности в метаданных события // Add PIDFD (if supported by kernel) enum FAN_REPORT_PIDFD = 0x0000_0080; // Добавлять PIDFD (если поддерживается ядром) // Report TID instead of PID enum FAN_REPORT_TID = 0x0000_0100; // Сообщать TID вместо PID // Report file-id (handle) instead of fd enum FAN_REPORT_FID = 0x0000_0200; // Сообщать file-id (handle) вместо fd // Report dir file-id enum FAN_REPORT_DIR_FID = 0x0000_0400; // Сообщать dir file-id // Report name (previously FAN_REPORT_DFID_NAME) enum FAN_REPORT_NAME = 0x0000_0800; // Сообщать имя (ранее FAN_REPORT_DFID_NAME) // Report target file-id enum FAN_REPORT_TARGET_FID = 0x0000_1000; // Сообщать target file-id // event->fd can report errors enum FAN_REPORT_FD_ERROR = 0x0000_2000; // event->fd может сообщать ошибки // Report mount events enum FAN_REPORT_MNT = 0x0000_4000; // Сообщать события монтирования // Convenient summary macros // Удобные сводные макросы enum FAN_REPORT_DFID_NAME = (FAN_REPORT_DIR_FID | FAN_REPORT_NAME); enum FAN_REPORT_DFID_NAME_TARGET = (FAN_REPORT_DFID_NAME | FAN_REPORT_FID | FAN_REPORT_TARGET_FID); deprecated enum FAN_ALL_INIT_FLAGS = (FAN_CLOEXEC | FAN_NONBLOCK | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS); // The event_f_flags parameter for fanotify_init() — these are open(2) flags: // O_RDONLY / O_WRONLY / O_RDWR | O_LARGEFILE etc. (from ). // Параметр event_f_flags для fanotify_init() — это флаги open(2): // O_RDONLY / O_WRONLY / O_RDWR | O_LARGEFILE и т.п. (из ). // FLAGS FOR fanotify_mark(fanfd, flags, mask, dirfd, path) // ФЛАГИ ДЛЯ fanotify_mark(fanfd, flags, mask, dirfd, path) // Add/update mark enum FAN_MARK_ADD = 0x0000_0001; // Добавить/обновить метку // Remove mark enum FAN_MARK_REMOVE = 0x0000_0002; // Удалить метку // Do not follow symlinks (on path) enum FAN_MARK_DONT_FOLLOW = 0x0000_0004; // Не переходить по симлинкам (на path) // Path must be a directory enum FAN_MARK_ONLYDIR = 0x0000_0008; // Path должен быть каталогом // Attach to mount point enum FAN_MARK_MOUNT = 0x0000_0010; // Навесить на точку монтирования // Set ignored events enum FAN_MARK_IGNORED_MASK = 0x0000_0020; // Задать игнорируемые события // Ignore survives modification enum FAN_MARK_IGNORED_SURV_MODIFY = 0x0000_0040; // Игнор сохраняется при модификации // Remove all marks from group enum FAN_MARK_FLUSH = 0x0000_0080; // Снять все метки у группы // Attach to entire filesystem enum FAN_MARK_FILESYSTEM = 0x0000_0100; // Навесить на всю ФС // Mark can be evicted enum FAN_MARK_EVICTABLE = 0x0000_0200; // Метка может быть evicted // Ignore (mutually exclusive with IGNORED_MASK, new) enum FAN_MARK_IGNORE = 0x0000_0400; // Игнорировать (взаимоисключающе с IGNORED_MASK, новое) // These are NOT bitwise flags. Both bits can be used together. // Это НЕ битовые флаги. Оба бита могут использоваться вместе. // On inode enum FAN_MARK_INODE = 0x0000_0000; // На inode // On mount namespace enum FAN_MARK_MNTNS = 0x0000_0110; // На mount namespace // Convenient macro // Удобный макрос enum FAN_MARK_IGNORE_SURV = (FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY); deprecated enum FAN_ALL_MARK_FLAGS = (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_DONT_FOLLOW | FAN_MARK_ONLYDIR | FAN_MARK_MOUNT | FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY | FAN_MARK_FLUSH); // EVENT MASK BITS (mask) FOR fanotify_mark() // БИТЫ МАСКИ СОБЫТИЙ (mask) ДЛЯ fanotify_mark() // "Regular" events // «Обычные» события // Read (read) enum FAN_ACCESS = 0x0000_0001; // Чтение (read) // Write/modify enum FAN_MODIFY = 0x0000_0002; // Запись/изменение // Metadata (chmod/chown/utime) enum FAN_ATTRIB = 0x0000_0004; // Метаданные (chmod/chown/utime) // Closed after write enum FAN_CLOSE_WRITE = 0x0000_0008; // Закрыт после записи // Closed without write enum FAN_CLOSE_NOWRITE = 0x0000_0010; // Закрыт без записи // Opened enum FAN_OPEN = 0x0000_0020; // Открыт // Moved "from" enum FAN_MOVED_FROM = 0x0000_0040; // Перемещён «из» // Moved "to" enum FAN_MOVED_TO = 0x0000_0080; // Перемещён «в» // Created enum FAN_CREATE = 0x0000_0100; // Создан // Deleted enum FAN_DELETE = 0x0000_0200; // Удалён // Observed object deleted itself enum FAN_DELETE_SELF = 0x0000_0400; // Удалён сам наблюдаемый объект // Observed object moved itself enum FAN_MOVE_SELF = 0x0000_0800; // Перемещён сам наблюдаемый объект // Opened for execution enum FAN_OPEN_EXEC = 0x0000_1000; // Открыт для исполнения // Queue overflow enum FAN_Q_OVERFLOW = 0x0000_4000; // Переполнение очереди // Filesystem errors enum FAN_FS_ERROR = 0x0000_8000; // Ошибки ФС // Pre-content access hook enum FAN_PRE_ACCESS = 0x0010_0000; // pre-content access hook // Mount attached enum FAN_MNT_ATTACH = 0x0100_0000; // mount attached // Mount detached enum FAN_MNT_DETACH = 0x0200_0000; // mount detached // File renamed enum FAN_RENAME = 0x1000_0000; // file renamed // "Permission" events (require CLASS_CONTENT/PRE_CONTENT) // События «разрешения» (требуют CLASS_CONTENT/PRE_CONTENT) // Request for open() (fixed name/value) enum FAN_OPEN_PERM = 0x0001_0000; // Запрос на open() (исправлено имя/значение) // Request for content access (fixed name/value) enum FAN_ACCESS_PERM = 0x0002_0000; // Запрос на доступ к содержимому (исправлено имя/значение) // Request for open(O_EXEC) enum FAN_OPEN_EXEC_PERM = 0x0004_0000; // Запрос на open(O_EXEC) // Mask scope modifiers // Модификаторы области действия маски // Events on child objects of directory enum FAN_EVENT_ON_CHILD = 0x0800_0000; // События на дочерние объекты каталога // Event relates to directory enum FAN_ONDIR = 0x4000_0000; // Событие относится к каталогу // Composite convenient masks // Составные удобные маски enum FAN_CLOSE = (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE); enum FAN_MOVE = (FAN_MOVED_FROM | FAN_MOVED_TO); deprecated enum FAN_ALL_EVENTS = (FAN_ACCESS | FAN_MODIFY | FAN_CLOSE | FAN_OPEN); deprecated enum FAN_ALL_PERM_EVENTS = (FAN_OPEN_PERM | FAN_ACCESS_PERM); deprecated enum FAN_ALL_OUTGOING_EVENTS = (FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_Q_OVERFLOW); // EVENT METADATA // МЕТАДАННЫЕ СОБЫТИЯ struct fanotify_event_metadata { // Total record length uint event_len; // Общая длина записи // Version (FANOTIFY_METADATA_VERSION) ubyte vers; // Версия (FANOTIFY_METADATA_VERSION) // Reserved ubyte reserved; // Зарезервировано // Length of this structure ushort metadata_len; // Длина этой структуры // __aligned_u64: Event/modifier bits uint64_t mask; // __aligned_u64: Биты события/модификаторов // File descriptor (or FAN_NOFD) int fd; // Файловый дескриптор (или FAN_NOFD) // PID or TID (if FAN_REPORT_TID) int pid; // PID или TID (если FAN_REPORT_TID) } enum FANOTIFY_METADATA_VERSION = 3; enum FAN_NOFD = -1; enum FAN_NOPIDFD = FAN_NOFD; enum FAN_EPIDFD = -2; // ADDITIONAL INFO (FID / PIDFD / ERROR / etc.) IN EVENT TAIL // ДОП. ИНФОРМАЦИЯ (FID / PIDFD / ERROR / etc.) В ХВОСТЕ СОБЫТИЯ struct fanotify_event_info_header { // Type of records below ubyte info_type; // Тип записей ниже // Alignment ubyte pad; // Выравнивание // Length of this record ushort len; // Длина этой записи } // Info record types (follow metadata) // Типы info-записей (идут после metadata) // File handle only enum FAN_EVENT_INFO_TYPE_FID = 1; // Только file handle // Dir handle + object name enum FAN_EVENT_INFO_TYPE_DFID_NAME = 2; // Dir handle + имя объекта // Dir handle enum FAN_EVENT_INFO_TYPE_DFID = 3; // Dir handle // PIDFD (if FAN_REPORT_PIDFD) enum FAN_EVENT_INFO_TYPE_PIDFD = 4; // PIDFD (если FAN_REPORT_PIDFD) // Error info enum FAN_EVENT_INFO_TYPE_ERROR = 5; // Error info // Range info enum FAN_EVENT_INFO_TYPE_RANGE = 6; // Range info // Mount info enum FAN_EVENT_INFO_TYPE_MNT = 7; // Mount info // Special info types for FAN_RENAME enum FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 10; enum FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 12; struct __kernel_fsid_t { int[2] val; } // Common header for FID records // Общий заголовок для FID-записей struct fanotify_event_info_fid { fanotify_event_info_header hdr; // Filesystem __kernel_fsid_t fsid; // Файловая система // Followed by variable length: unsigned char handle[]; (opaque struct file_handle) } // Compatible with open_by_handle_at() // Совместимо с open_by_handle_at() struct file_handle { // Length of f_handle uint handle_bytes; // Длина f_handle // Handle type int handle_type; // Тип handle // Flexible tail (actual handle bytes follow the structure) ubyte[0] f_handle; // Гибкий хвост (реальные байты handle идут сразу за структурой) } // Structure for PIDFD // Структура для PIDFD struct fanotify_event_info_pidfd { fanotify_event_info_header hdr; // __s32 int pidfd; // __s32 } // Structure for ERROR // Структура для ERROR struct fanotify_event_info_error { fanotify_event_info_header hdr; // __s32 int error; // __s32 // __u32 uint error_count; // __u32 } // Structure for RANGE // Структура для RANGE struct fanotify_event_info_range { fanotify_event_info_header hdr; // __u32 uint pad; // __u32 // __u64 uint64_t offset; // __u64 // __u64 uint64_t count; // __u64 } // Structure for MNT // Структура для MNT struct fanotify_event_info_mnt { fanotify_event_info_header hdr; // __u64 uint64_t mnt_id; // __u64 } // STRUCTURES FOR RESPONSE (for PERM events) // СТРУКТУРЫ ДЛЯ RESPONSE (для PERM-событий) struct fanotify_response { // __s32 int fd; // __s32 // __u32 uint response; // __u32 } // Additional information in response // Дополнительная информация в response enum FAN_RESPONSE_INFO_NONE = 0; enum FAN_RESPONSE_INFO_AUDIT_RULE = 1; struct fanotify_response_info_header { ubyte type; ubyte pad; ushort len; } struct fanotify_response_info_audit_rule { fanotify_response_info_header hdr; // __u32 uint rule_number; // __u32 // __u32 uint subj_trust; // __u32 // __u32 uint obj_trust; // __u32 } // Legit responses enum FAN_ALLOW = 0x01; enum FAN_DENY = 0x02; // Bitmask to create audit record enum FAN_AUDIT = 0x10; // Bitmask to create audit record // Bitmask to indicate additional information enum FAN_INFO = 0x20; // Bitmask to indicate additional information // For DENY with errno // Для DENY с errno enum FAN_ERRNO_BITS = 8; enum FAN_ERRNO_SHIFT = (32 - FAN_ERRNO_BITS); enum FAN_ERRNO_MASK = ((1 << FAN_ERRNO_BITS) - 1); // C API FUNCTION PROTOTYPES // ПРОТОТИПЫ ФУНКЦИЙ C API extern (C) int fanotify_init(uint flags, uint event_f_flags); extern (C) int fanotify_mark( int fanotify_fd, uint flags, uint64_t mask,// AT_FDCWD or directory fd int dirfd, // AT_FDCWD или fd каталога // Path or null for INODE/FILESYSTEM/MOUNT const(char)* pathname // Путь или null при INODE/FILESYSTEM/MOUNT ); // For working with FID: open object by handle (requires CAP_DAC_READ_SEARCH) // Для работы с FID: открыть объект по handle (требует CAP_DAC_READ_SEARCH) extern (C) int open_by_handle_at(int mount_fd, const(file_handle)* handle, int flags); // HELPER FUNCTIONS (macros for working with metadata buffer) // HELPER FUNCTIONS (макросы для работы с буфером metadata) enum FAN_EVENT_METADATA_LEN = fanotify_event_metadata.sizeof; // FAN_EVENT_NEXT(meta, len): len -= meta.event_len; return cast(fanotify_event_metadata*) (cast(char*) meta + meta.event_len); // FAN_EVENT_OK(meta, len): (len >= FAN_EVENT_METADATA_LEN) && (meta.event_len >= FAN_EVENT_METADATA_LEN) && (meta.event_len <= len)