1 #define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
8 #include <sys/fanotify.h>
12 /* Read all available fanotify events from the file descriptor 'fd'. */
16 void fanotify_read(int fd)
18 int ret, event_fd, mount_fd;
19 ssize_t len, path_len;
21 char procfd_path[PATH_MAX];
22 char events_buf[BUF_SIZE];
23 struct file_handle *file_handle;
24 struct fanotify_event_metadata *metadata;
25 struct fanotify_event_info_fid *fid;
26 const char *file_name;
29 mount_fd = open("/", O_DIRECTORY | O_RDONLY);
31 perror("cant open mount");
35 printf("Listening for events.\n");
37 /* Read events from the event queue into a buffer. */
39 len = read(fd, events_buf, sizeof(events_buf));
40 if (len == -1 && errno != EAGAIN) {
45 /* Process all events within the buffer. */
47 for (metadata = (struct fanotify_event_metadata *) events_buf;
48 FAN_EVENT_OK(metadata, len);
49 metadata = FAN_EVENT_NEXT(metadata, len)) {
52 fid = (struct fanotify_event_info_fid *) (metadata + 1);
56 file_handle = (struct file_handle *) fid->handle;
58 // Ensure that the event info is of the correct type.
60 if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_FID ||
61 fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID) {
62 printf("Got FID or DFID.\n");
64 } else if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) {
65 file_name = file_handle->f_handle +
66 file_handle->handle_bytes;
67 printf("Got DFID_NAME %s.\n",file_name);
69 fprintf(stderr, "Received unexpected event info type.\n");
73 if (metadata->mask == FAN_CREATE)
74 printf("FAN_CREATE (file created):\n");
76 if (metadata->mask == (FAN_CREATE | FAN_ONDIR))
77 printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\n");
84 https://github.com/GNOME/tracker-miners/blob/38596491ead21b1ee6db99f2623ac6f127b6da34/src/miners/fs/tracker-monitor-fanotify.c#L356
86 seems to create a hashtable for all monitored files?
88 *handle = (HandleData *) &fid->fsid;
89 fid_bytes = create_bytes_for_handle (handle);
90 data = g_hash_table_lookup (monitor->handles, fid_bytes);
91 g_bytes_unref (fid_bytes);
94 /* metadata->fd is set to FAN_NOFD when the group identifies
95 objects by file handles. To obtain a file descriptor for
96 the file object corresponding to an event you can use the
97 struct file_handle that's provided within the
98 fanotify_event_info_fid in conjunction with the
99 open_by_handle_at(2) system call. A check for ESTALE is
100 done to accommodate for the situation where the file handle
101 for the object was deleted prior to this system call. */
104 event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
105 if (event_fd == -1) {
106 if (errno == ESTALE) {
107 printf("File handle is no longer valid. "
108 "File has been deleted\n");
111 perror("open_by_handle_at");
116 snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
119 /* Retrieve and print the path of the modified dentry. */
121 path_len = readlink(procfd_path, path, sizeof(path) - 1);
122 if (path_len == -1) {
127 path[path_len] = '\0';
128 printf("\tDirectory '%s' has been modified.\n", path);
131 ret = fstatat(event_fd, file_name, &sb, 0);
133 if (errno != ENOENT) {
137 printf("\tEntry '%s' does not exist.\n", file_name);
138 } else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
139 printf("\tEntry '%s' is a subdirectory.\n", file_name);
141 printf("\tEntry '%s' is not a subdirectory.\n",
146 /* Close associated file descriptor for this event. */
151 printf("All events processed successfully. Program exiting.\n");