На основе примеров GNU я придумал следующий код.
Я запускаю этот код в Oracle Enterprise Linux 9 .
С этим кодом есть две проблемы:
- Я не получаю события get для созданных\измененных файлов в «/run»
Возможно, мне нужен отдельный вопрос: у меня сложилось впечатление, что FAN_EVENT_NEXT будет блокироваться. Но, похоже, это не так. Из-за этого мне пришлось поставить Sleep(1)
Код: Выделить всё
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const static int _INIT_FLAGS = FAN_CLOEXEC | FAN_NONBLOCK | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS | FAN_CLASS_CONTENT;
const static int _INIT_FID_FLAGS = FAN_REPORT_FID | FAN_REPORT_DFID_NAME;
const static int INIT_FID_FLAGS = FAN_CLOEXEC | FAN_NONBLOCK | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS | FAN_REPORT_FID | FAN_REPORT_DFID_NAME;
static volatile int keepRunning = 1;
void intHandler(int dummy) {
printf("flaggin..\n");
keepRunning = 0;
}
int main(int argc, char** argv)
{
int fan;
ssize_t len, path_len;
int mount_fd, event_fd;
char buf[4096];
char fdpath[32];
char path[PATH_MAX + 1];
char procfd_path[PATH_MAX];
struct file_handle *file_handle;
char full_path[(PATH_MAX * 2)+ 1];
signal(SIGINT, intHandler);
ssize_t buflen, linklen;
struct fanotify_event_metadata *metadata;
struct fanotify_event_info_fid *fid;
if (argc != 2) {
fprintf(stderr, "Usage: %s /dir\n", argv[0]);
exit(EXIT_FAILURE);
}
mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
if (mount_fd == -1) {
perror(argv[1]);
exit(EXIT_FAILURE);
}
//fan = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, O_RDWR);
fan = fanotify_init(INIT_FID_FLAGS, O_RDWR);
if(fan == -1) {
perror("fanotify_init");
exit(EXIT_FAILURE);
}
int ret = fanotify_mark(fan,
FAN_MARK_ADD | FAN_MARK_FILESYSTEM,
FAN_CREATE | FAN_MODIFY /*| FAN_DELETE | FAN_EVENT_ON_CHILD*/,
mount_fd, //AT_FDCWD,
argv[1]
);
if(ret == -1) {
perror("fanotify_mark");
exit(EXIT_FAILURE);
}
while(1) {
if (0 == keepRunning) {
break;
}
buflen = read(fan, buf, sizeof(buf));
metadata = (struct fanotify_event_metadata*)&buf;
for (; FAN_EVENT_OK(metadata, buflen); metadata = FAN_EVENT_NEXT(metadata, buflen)) {
if (0 == keepRunning) {
break;
}
fid = (struct fanotify_event_info_fid *) (metadata + 1);
file_handle = (struct file_handle *) fid->handle;
/* Ensure that the event info is of the correct type */
const char* file_name = NULL;
if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_DFID_NAME) {
fprintf(stderr, "Received unexpected event info type, ignoring..: %d\n", fid->hdr.info_type);
continue;
}
file_name = file_handle->f_handle +
file_handle->handle_bytes;
event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
if (event_fd == -1) {
if (errno == ESTALE) {
printf("File handle is no longer valid. "
"File has been deleted\n");
continue;
} else {
perror("open_by_handle_at");
//exit(EXIT_FAILURE);
continue;
}
}
snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
event_fd);
/* Retrieve and print the path of the modified dentry. */
path_len = readlink(procfd_path, path, sizeof(path) - 1);
if (path_len == -1) {
perror("readlink");
//exit(EXIT_FAILURE);
continue;
}
path[path_len] = '\0';
if (NULL != file_name) {
printf("Path: %s file_name: %s\n", path, file_name);
}
}
sleep(1);
}
}
Заранее спасибо!
Подробнее здесь: https://stackoverflow.com/questions/791 ... ges-in-run