Ответ 1
Эта статья LWN часто цитируется как источник документации для fanotify. Но описание, похоже, устарело. fanotify больше не работает, используя соединение сокета. Вместо этого есть две новые функции libc, обертывающие системные вызовы, объявленные в sys/fanotify.h
. Один называется fanotify_init
, другой - fanotify_mark
. На момент написания этой статьи эти системные вызовы по-прежнему включены в список отсутствующих страниц руководства . Существует, однако, письмо, содержащее черновики для этих страниц руководства. С комбинацией этих страниц руководства, взглядом на заголовки, о которых идет речь, и немного проб и ошибок, вы должны иметь возможность добиться этого.
Похоже, что некоторые функции, изначально предусмотренные для фанатифики, больше не поддерживаются подобным образом. Например, статья LWN описывает флаг FAN_GLOBAL_LISTENER
, который будет неявно отмечать все дерево файловой системы, если части не будут явно немаркированы. Текущий интерфейс не имеет такого положения, но аналогичный результат может быть достигнут с использованием следующей метки:
fanotify_mark(fan,
FAN_MARK_ADD | FAN_MARK_MOUNT,
FAN_OPEN | FAN_EVENT_ON_CHILD,
AT_FDCWD, "/")
Если inotify события предоставляют путь к объекту, доступному как часть события, fanotify открывает для него дескриптор файла. Чтобы превратить этот дескриптор в имя пути, можно использовать соответствующую запись из файловой системы proc, как описано здесь.
Вот простой пример, который просто печатает имя каждого открытого файла:
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/fanotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#define CHK(expr, errcode) if((expr)==errcode) perror(#expr), exit(EXIT_FAILURE)
int main(int argc, char** argv) {
int fan;
char buf[4096];
char fdpath[32];
char path[PATH_MAX + 1];
ssize_t buflen, linklen;
struct fanotify_event_metadata *metadata;
CHK(fan = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY), -1);
CHK(fanotify_mark(fan, FAN_MARK_ADD | FAN_MARK_MOUNT,
FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, "/"), -1);
for (;;) {
CHK(buflen = read(fan, buf, sizeof(buf)), -1);
metadata = (struct fanotify_event_metadata*)&buf;
while(FAN_EVENT_OK(metadata, buflen)) {
if (metadata->mask & FAN_Q_OVERFLOW) {
printf("Queue overflow!\n");
continue;
}
sprintf(fdpath, "/proc/self/fd/%d", metadata->fd);
CHK(linklen = readlink(fdpath, path, sizeof(path) - 1), -1);
path[linklen] = '\0';
printf("%s opened by process %d.\n", path, (int)metadata->pid);
close(metadata->fd);
metadata = FAN_EVENT_NEXT(metadata, buflen);
}
}
}