0.1.0
This commit is contained in:
		
						commit
						9e3e657996
					
				
					 8 changed files with 370 additions and 0 deletions
				
			
		
							
								
								
									
										272
									
								
								source/fanotify.d
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								source/fanotify.d
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,272 @@
 | 
			
		|||
// Низкоуровневая обёртка над 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 0x0008_0000 /* 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
 | 
			
		||||
// ------------------------------------------------------------
 | 
			
		||||
// Инициализирует новую группу fanotify и возвращает файловый дескриптор для очереди событий
 | 
			
		||||
extern (C) int fanotify_init(
 | 
			
		||||
	uint flags, // Битовая маска, определяющая класс уведомлений и другие поведения
 | 
			
		||||
	uint event_f_flags // Флаги состояния файлов, применяемые к дескрипторам файлов, возвращаемым в событиях
 | 
			
		||||
	
 | 
			
		||||
);
 | 
			
		||||
// Добавляет, удаляет или модифицирует метку fanotify на объекте файловой системы
 | 
			
		||||
extern (C) int fanotify_mark(
 | 
			
		||||
	int fanotify_fd, // Файловый дескриптор fanotify, возвращенный fanotify_init()
 | 
			
		||||
	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)
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue