我在Linux5.4(也是在5.8上测试)上测试fanotify;对于测试,我使用fanotify(7)手册页中的fanotify_fid.c示例。
现在,代码看起来非常糟糕--我认为至少有几个bugs -但我还是设法让它在一定程度上正常工作。
不过,有一个我无法解决的问题--使用Invalid argument时open_by_handle_at()会失败。
以下是我使用的带有注释的示例代码;它是原始代码的简化和更正版本;它可以与gcc和clang一起使用。
为了测试它,执行它,然后在另一个终端上执行mktemp (或者只是在/tmp下创建一个文件/目录)。
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/fanotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 512
int main(int argc, char **argv) {
char *filename = "/tmp";
int fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, 0);
if (fd == -1)
exit(EXIT_FAILURE);
int ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR, FAN_CREATE | FAN_ONDIR, AT_FDCWD, filename);
if (ret == -1)
exit(EXIT_FAILURE);
char events_buf[BUF_SIZE];
char path[PATH_MAX], procfd_path[PATH_MAX];
ssize_t len = read(fd, (void *)&events_buf, sizeof(events_buf));
if (len == -1 && errno != EAGAIN)
exit(EXIT_FAILURE);
for (
struct fanotify_event_metadata *metadata = (struct fanotify_event_metadata *)events_buf;
FAN_EVENT_OK(metadata, len);
metadata = FAN_EVENT_NEXT(metadata, len)
) {
struct fanotify_event_info_fid *fid = (struct fanotify_event_info_fid *)(metadata + 1);
// The mangpage `BUF_SIZE` is 256; this causes `info_type` to be 64 instead of 0
// (when running `mktemp`), which causes an error.
if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
fprintf(stderr, "Received unexpected event info type: %i.\n", fid->hdr.info_type);
exit(EXIT_FAILURE);
}
if (metadata->mask == FAN_CREATE)
printf("FAN_CREATE (file/directory created)\n");
struct file_handle *file_handle = (struct file_handle *)fid->handle;
// The manpage condition is `(ret == -1)`, which seems to be a bug.
int event_fd = open_by_handle_at(AT_FDCWD, file_handle, O_RDONLY);
if (event_fd == -1) {
printf("File handle hex: ");
for (int i = 0; i < sizeof(struct file_handle); i++)
printf("%02x ", ((unsigned char *)file_handle)[i]);
printf("\n");
perror("open_by_handle_at");
exit(EXIT_FAILURE);
}
snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d", event_fd);
ssize_t path_len = readlink(procfd_path, path, sizeof(path) - 1);
if (path_len == -1) {
perror("readlink");
exit(EXIT_FAILURE);
}
close(event_fd);
}
}发布于 2021-01-04 00:36:57
5.4 fanotify(7)手册页示例有许多错误,其中之一是open_by_handle_at()的第一个参数应该是挂载/目录fd,而不是AT_FDCWD。
更正的代码片段,来自5.10 man page
mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
if (mount_fd == -1) { /* error handling */ }
// ...
event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
if (event_fd == -1) { /* error handling */ }https://stackoverflow.com/questions/65550231
复制相似问题