如何解决为什么 fanotify_fid Linux 联机帮助页示例代码失败在 open_by_handle_at() 上?
我正在 Linux 5.4 上测试 fanotify(也在 5.8 上测试);对于测试,我使用了 fanotify_fid.c
联机帮助页中的 fanotify(7)
示例。
现在,代码似乎很差——我认为至少有几个错误——但我还是设法让它在一定程度上工作。
有一个我无法解决的问题 - open_by_handle_at()
失败并显示 Invalid argument
。
以下是我用过的示例代码,有注释;它是原始代码的简化和更正版本;它适用于 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);
}
}
解决方法
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 */ }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。