fanotify/source/fanotify.d
2025-08-21 20:09:16 +03:00

250 lines
13 KiB
D
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Низкоуровневая обёртка над C API fanotify для D.
// Все значения взяты из uapi <linux/fanotify.h> (актуальная версия на основе предоставленного заголовка).
module fanotify;
import core.stdc.stdint; // uint64_t и т.п.
// ------------------------------------------------------------
// ФЛАГИ ДЛЯ fanotify_init(flags, event_f_flags)
// ------------------------------------------------------------
// Поведение файлового дескриптора группы
enum FAN_CLOEXEC = 0x0000_0001; // закрывать fd при exec()
enum FAN_NONBLOCK = 0x0000_0002; // неблокирующие read()
// Класс группы (определяет тип выдаваемых событий)
enum FAN_CLASS_NOTIF = 0x0000_0000; // только уведомления (не PERM)
enum FAN_CLASS_CONTENT = 0x0000_0004; // разрешения на доступ к СОДЕРЖИМОМУ (CONTENT)
enum FAN_CLASS_PRE_CONTENT = 0x0000_0008; // разрешения ДО доступа к содержимому (PRE_CONTENT)
// Deprecated - do not use this in programs and do not add new flags here!
deprecated enum FAN_ALL_CLASS_BITS = (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT);
// Лимиты очереди/меток
enum FAN_UNLIMITED_QUEUE = 0x0000_0010; // неограниченная очередь событий
enum FAN_UNLIMITED_MARKS = 0x0000_0020; // неограниченное число меток
enum FAN_ENABLE_AUDIT = 0x0000_0040; // включить аудит
// Формат отчётности в метаданных события
enum FAN_REPORT_PIDFD = 0x0000_0080; // добавлять PIDFD (если поддерживается ядром)
enum FAN_REPORT_TID = 0x0000_0100; // сообщать TID вместо PID
enum FAN_REPORT_FID = 0x0000_0200; // сообщать file-id (handle) вместо fd
enum FAN_REPORT_DIR_FID = 0x0000_0400; // сообщать dir file-id
enum FAN_REPORT_NAME = 0x0000_0800; // сообщать имя (ранее FAN_REPORT_DFID_NAME)
enum FAN_REPORT_TARGET_FID = 0x0000_1000; // сообщать target file-id
enum FAN_REPORT_FD_ERROR = 0x0000_2000; // event->fd может сообщать ошибки
enum FAN_REPORT_MNT = 0x0000_4000; // сообщать события монтирования
// Удобные сводные макросы
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 - do not use this in programs and do not add new flags here!
deprecated enum FAN_ALL_INIT_FLAGS =
(FAN_CLOEXEC | FAN_NONBLOCK | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |
FAN_UNLIMITED_MARKS);
// Параметр event_f_flags для fanotify_init() — это флаги open(2):
// O_RDONLY / O_WRONLY / O_RDWR | O_LARGEFILE и т.п. (из <fcntl.h>).
// ------------------------------------------------------------
// ФЛАГИ ДЛЯ fanotify_mark(fanfd, flags, mask, dirfd, path)
// ------------------------------------------------------------
enum FAN_MARK_ADD = 0x0000_0001; // добавить/обновить метку
enum FAN_MARK_REMOVE = 0x0000_0002; // удалить метку
enum FAN_MARK_DONT_FOLLOW = 0x0000_0004; // не переходить по симлинкам (на path)
enum FAN_MARK_ONLYDIR = 0x0000_0008; // path должен быть каталогом
enum FAN_MARK_MOUNT = 0x0000_0010; // навесить на точку монтирования
enum FAN_MARK_IGNORED_MASK = 0x0000_0020; // задать игнорируемые события
enum FAN_MARK_IGNORED_SURV_MODIFY = 0x0000_0040; // игнор сохраняется при модификации
enum FAN_MARK_FLUSH = 0x0000_0080; // снять все метки у группы
enum FAN_MARK_FILESYSTEM = 0x0000_0100; // навесить на всю ФС
enum FAN_MARK_EVICTABLE = 0x0000_0200; // метка может быть evicted
enum FAN_MARK_IGNORE = 0x0000_0400; // игнорировать (взаимоисключающе с IGNORED_MASK, новое)
// These are NOT bitwise flags. Both bits can be used together.
enum FAN_MARK_INODE = 0x0000_0000; // на inode
enum FAN_MARK_MNTNS = 0x0000_0110; // на mount namespace
// Удобный макрос
enum FAN_MARK_IGNORE_SURV = (FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY);
// Deprecated - do not use this in programs and do not add new flags here!
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);
// ------------------------------------------------------------
// БИТЫ МАСКИ СОБЫТИЙ (mask) ДЛЯ fanotify_mark()
// ------------------------------------------------------------
// «Обычные» события
enum FAN_ACCESS = 0x0000_0001; // чтение (read)
enum FAN_MODIFY = 0x0000_0002; // запись/изменение
enum FAN_ATTRIB = 0x0000_0004; // метаданные (chmod/chown/utime)
enum FAN_CLOSE_WRITE = 0x0000_0008; // закрыт после записи
enum FAN_CLOSE_NOWRITE = 0x0000_0010; // закрыт без записи
enum FAN_OPEN = 0x0000_0020; // открыт
enum FAN_MOVED_FROM = 0x0000_0040; // перемещён «из»
enum FAN_MOVED_TO = 0x0000_0080; // перемещён «в»
enum FAN_CREATE = 0x0000_0100; // создан
enum FAN_DELETE = 0x0000_0200; // удалён
enum FAN_DELETE_SELF = 0x0000_0400; // удалён сам наблюдаемый объект
enum FAN_MOVE_SELF = 0x0000_0800; // перемещён сам наблюдаемый объект
enum FAN_OPEN_EXEC = 0x0000_1000; // открыт для исполнения
enum FAN_Q_OVERFLOW = 0x0000_4000; // переполнение очереди
enum FAN_FS_ERROR = 0x0000_8000; // ошибки ФС
// deprecated #define FAN_DIR_MODIFY 0x00080000 /* Deprecated (reserved) */
enum FAN_PRE_ACCESS = 0x0010_0000; // pre-content access hook
enum FAN_MNT_ATTACH = 0x0100_0000; // mount attached
enum FAN_MNT_DETACH = 0x0200_0000; // mount detached
enum FAN_RENAME = 0x1000_0000; // file renamed
// События «разрешения» (требуют CLASS_CONTENT/PRE_CONTENT)
enum FAN_OPEN_PERM = 0x0001_0000; // запрос на open() (исправлено имя/значение)
enum FAN_ACCESS_PERM = 0x0002_0000; // запрос на доступ к содержимому (исправлено имя/значение)
enum FAN_OPEN_EXEC_PERM = 0x0004_0000; // запрос на open(O_EXEC)
// Модификаторы области действия маски
enum FAN_EVENT_ON_CHILD = 0x0800_0000; // события на дочерние объекты каталога
enum FAN_ONDIR = 0x4000_0000; // событие относится к каталогу
// Составные удобные маски
enum FAN_CLOSE = (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE);
enum FAN_MOVE = (FAN_MOVED_FROM | FAN_MOVED_TO);
// Deprecated - do not use this in programs and do not add new flags here!
deprecated enum FAN_ALL_EVENTS =
(FAN_ACCESS | FAN_MODIFY | FAN_CLOSE | FAN_OPEN);
// Deprecated - do not use this in programs and do not add new flags here!
deprecated enum FAN_ALL_PERM_EVENTS =
(FAN_OPEN_PERM | FAN_ACCESS_PERM);
// Deprecated - do not use this in programs and do not add new flags here!
deprecated enum FAN_ALL_OUTGOING_EVENTS =
(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_Q_OVERFLOW);
// ------------------------------------------------------------
// МЕТАДАННЫЕ СОБЫТИЯ
// ------------------------------------------------------------
struct fanotify_event_metadata {
uint event_len; // общая длина записи
ubyte vers; // версия (FANOTIFY_METADATA_VERSION)
ubyte reserved; // зарезервировано
ushort metadata_len; // длина этой структуры
uint64_t mask; // __aligned_u64: биты события/модификаторов
int fd; // файловый дескриптор (или FAN_NOFD)
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;
// ------------------------------------------------------------
// ДОП. ИНФОРМАЦИЯ (FID / PIDFD / ERROR / etc.) В ХВОСТЕ СОБЫТИЯ
// ------------------------------------------------------------
struct fanotify_event_info_header {
ubyte info_type; // тип записей ниже
ubyte pad; // выравнивание
ushort len; // длина этой записи
}
// Типы info-записей (идут после metadata)
enum FAN_EVENT_INFO_TYPE_FID = 1; // только file handle
enum FAN_EVENT_INFO_TYPE_DFID_NAME = 2; // dir handle + имя объекта
enum FAN_EVENT_INFO_TYPE_DFID = 3; // dir handle
enum FAN_EVENT_INFO_TYPE_PIDFD = 4; // PIDFD (если FAN_REPORT_PIDFD)
enum FAN_EVENT_INFO_TYPE_ERROR = 5; // error info
enum FAN_EVENT_INFO_TYPE_RANGE = 6; // range 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;
// (Reserved: 11 и 13 для OLD_DFID и NEW_DFID)
struct __kernel_fsid_t { int[2] val; }
// Общий заголовок для FID-записей
struct fanotify_event_info_fid {
fanotify_event_info_header hdr;
__kernel_fsid_t fsid; // файловая система
// далее переменной длины: unsigned char handle[]; (opaque struct file_handle)
}
// Совместимо с open_by_handle_at()
struct file_handle {
uint handle_bytes; // длина f_handle
int handle_type; // тип handle
ubyte[0] f_handle; // гибкий хвост (реальные байты handle идут сразу за структурой)
}
// Структура для PIDFD
struct fanotify_event_info_pidfd {
fanotify_event_info_header hdr;
int pidfd; // __s32
}
// Структура для ERROR
struct fanotify_event_info_error {
fanotify_event_info_header hdr;
int error; // __s32
uint error_count; // __u32
}
// Структура для RANGE
struct fanotify_event_info_range {
fanotify_event_info_header hdr;
uint pad; // __u32
uint64_t offset; // __u64
uint64_t count; // __u64
}
// Структура для MNT
struct fanotify_event_info_mnt {
fanotify_event_info_header hdr;
uint64_t mnt_id; // __u64
}
// ------------------------------------------------------------
// СТРУКТУРЫ ДЛЯ RESPONSE (для PERM-событий)
// ------------------------------------------------------------
struct fanotify_response {
int fd; // __s32
uint response; // __u32
}
// Дополнительная информация в 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;
uint rule_number; // __u32
uint subj_trust; // __u32
uint obj_trust; // __u32
}
// Legit responses
enum FAN_ALLOW = 0x01;
enum FAN_DENY = 0x02;
enum FAN_AUDIT = 0x10; // Bitmask to create audit record
enum FAN_INFO = 0x20; // Bitmask to indicate additional information
// Для DENY с errno
enum FAN_ERRNO_BITS = 8;
enum FAN_ERRNO_SHIFT = (32 - FAN_ERRNO_BITS);
enum FAN_ERRNO_MASK = ((1 << FAN_ERRNO_BITS) - 1);
// Макрос: FAN_DENY_ERRNO(err) = (FAN_DENY | ((((__u32)(err)) & FAN_ERRNO_MASK) << FAN_ERRNO_SHIFT))
// ------------------------------------------------------------
// ПРОТОТИПЫ ФУНКЦИЙ 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,
int dirfd, // AT_FDCWD или fd каталога
const(char)* pathname // путь или null при INODE/FILESYSTEM/MOUNT
);
// Для работы с FID: открыть объект по handle (требует CAP_DAC_READ_SEARCH)
extern(C) int open_by_handle_at(int mount_fd, const(file_handle)* handle, int flags);
// ------------------------------------------------------------
// HELPER FUNCTIONS (макросы для работы с буфером metadata)
// ------------------------------------------------------------
enum FAN_EVENT_METADATA_LEN = fanotify_event_metadata.sizeof;
// Макросы в D-стиле (как функции или шаблоны, но для простоты как enum/комментарии)
// 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)