1FANOTIFY(7) Linux Programmer's Manual FANOTIFY(7)
2
3
4
6 fanotify - monitoring filesystem events
7
9 The fanotify API provides notification and interception of filesystem
10 events. Use cases include virus scanning and hierarchical storage man‐
11 agement. In the original fanotify API, only a limited set of events
12 was supported. In particular, there was no support for create, delete,
13 and move events. The support for those events was added in Linux 5.1.
14 (See inotify(7) for details of an API that did notify those events pre
15 Linux 5.1.)
16
17 Additional capabilities compared to the inotify(7) API include the
18 ability to monitor all of the objects in a mounted filesystem, the
19 ability to make access permission decisions, and the possibility to
20 read or modify files before access by other applications.
21
22 The following system calls are used with this API: fanotify_init(2),
23 fanotify_mark(2), read(2), write(2), and close(2).
24
25 fanotify_init(), fanotify_mark(), and notification groups
26 The fanotify_init(2) system call creates and initializes an fanotify
27 notification group and returns a file descriptor referring to it.
28
29 An fanotify notification group is a kernel-internal object that holds a
30 list of files, directories, filesystems, and mounts for which events
31 shall be created.
32
33 For each entry in an fanotify notification group, two bit masks exist:
34 the mark mask and the ignore mask. The mark mask defines file activi‐
35 ties for which an event shall be created. The ignore mask defines ac‐
36 tivities for which no event shall be generated. Having these two types
37 of masks permits a filesystem, mount, or directory to be marked for re‐
38 ceiving events, while at the same time ignoring events for specific ob‐
39 jects under a mount or directory.
40
41 The fanotify_mark(2) system call adds a file, directory, filesystem, or
42 mount to a notification group and specifies which events shall be re‐
43 ported (or ignored), or removes or modifies such an entry.
44
45 A possible usage of the ignore mask is for a file cache. Events of in‐
46 terest for a file cache are modification of a file and closing of the
47 same. Hence, the cached directory or mount is to be marked to receive
48 these events. After receiving the first event informing that a file
49 has been modified, the corresponding cache entry will be invalidated.
50 No further modification events for this file are of interest until the
51 file is closed. Hence, the modify event can be added to the ignore
52 mask. Upon receiving the close event, the modify event can be removed
53 from the ignore mask and the file cache entry can be updated.
54
55 The entries in the fanotify notification groups refer to files and di‐
56 rectories via their inode number and to mounts via their mount ID. If
57 files or directories are renamed or moved within the same mount, the
58 respective entries survive. If files or directories are deleted or
59 moved to another mount or if filesystems or mounts are unmounted, the
60 corresponding entries are deleted.
61
62 The event queue
63 As events occur on the filesystem objects monitored by a notification
64 group, the fanotify system generates events that are collected in a
65 queue. These events can then be read (using read(2) or similar) from
66 the fanotify file descriptor returned by fanotify_init(2).
67
68 Two types of events are generated: notification events and permission
69 events. Notification events are merely informative and require no ac‐
70 tion to be taken by the receiving application with one exception: if a
71 valid file descriptor is provided within a generic event, the file de‐
72 scriptor must be closed. Permission events are requests to the receiv‐
73 ing application to decide whether permission for a file access shall be
74 granted. For these events, the recipient must write a response which
75 decides whether access is granted or not.
76
77 An event is removed from the event queue of the fanotify group when it
78 has been read. Permission events that have been read are kept in an
79 internal list of the fanotify group until either a permission decision
80 has been taken by writing to the fanotify file descriptor or the fan‐
81 otify file descriptor is closed.
82
83 Reading fanotify events
84 Calling read(2) for the file descriptor returned by fanotify_init(2)
85 blocks (if the flag FAN_NONBLOCK is not specified in the call to fan‐
86 otify_init(2)) until either a file event occurs or the call is inter‐
87 rupted by a signal (see signal(7)).
88
89 The use of one of the flags FAN_REPORT_FID, FAN_REPORT_DIR_FID in fan‐
90 otify_init(2) influences what data structures are returned to the event
91 listener for each event. Events reported to a group initialized with
92 one of these flags will use file handles to identify filesystem objects
93 instead of file descriptors.
94
95 After a successful read(2), the read buffer contains one or more of the
96 following structures:
97
98 struct fanotify_event_metadata {
99 __u32 event_len;
100 __u8 vers;
101 __u8 reserved;
102 __u16 metadata_len;
103 __aligned_u64 mask;
104 __s32 fd;
105 __s32 pid;
106 };
107
108 In case of an fanotify group that identifies filesystem objects by file
109 handles, you should also expect to receive one or more additional in‐
110 formation records of the structure detailed below following the generic
111 fanotify_event_metadata structure within the read buffer:
112
113 struct fanotify_event_info_header {
114 __u8 info_type;
115 __u8 pad;
116 __u16 len;
117 };
118
119 struct fanotify_event_info_fid {
120 struct fanotify_event_info_header hdr;
121 __kernel_fsid_t fsid;
122 unsigned char file_handle[0];
123 };
124
125 For performance reasons, it is recommended to use a large buffer size
126 (for example, 4096 bytes), so that multiple events can be retrieved by
127 a single read(2).
128
129 The return value of read(2) is the number of bytes placed in the buf‐
130 fer, or -1 in case of an error (but see BUGS).
131
132 The fields of the fanotify_event_metadata structure are as follows:
133
134 event_len
135 This is the length of the data for the current event and the
136 offset to the next event in the buffer. Unless the group iden‐
137 tifies filesystem objects by file handles, the value of
138 event_len is always FAN_EVENT_METADATA_LEN. For a group that
139 identifies filesystem objects by file handles, event_len also
140 includes the variable length file identifier records.
141
142 vers This field holds a version number for the structure. It must be
143 compared to FANOTIFY_METADATA_VERSION to verify that the struc‐
144 tures returned at run time match the structures defined at com‐
145 pile time. In case of a mismatch, the application should aban‐
146 don trying to use the fanotify file descriptor.
147
148 reserved
149 This field is not used.
150
151 metadata_len
152 This is the length of the structure. The field was introduced
153 to facilitate the implementation of optional headers per event
154 type. No such optional headers exist in the current implementa‐
155 tion.
156
157 mask This is a bit mask describing the event (see below).
158
159 fd This is an open file descriptor for the object being accessed,
160 or FAN_NOFD if a queue overflow occurred. With an fanotify
161 group that identifies filesystem objects by file handles, appli‐
162 cations should expect this value to be set to FAN_NOFD for each
163 event that is received. The file descriptor can be used to ac‐
164 cess the contents of the monitored file or directory. The read‐
165 ing application is responsible for closing this file descriptor.
166
167 When calling fanotify_init(2), the caller may specify (via the
168 event_f_flags argument) various file status flags that are to be
169 set on the open file description that corresponds to this file
170 descriptor. In addition, the (kernel-internal) FMODE_NONOTIFY
171 file status flag is set on the open file description. This flag
172 suppresses fanotify event generation. Hence, when the receiver
173 of the fanotify event accesses the notified file or directory
174 using this file descriptor, no additional events will be cre‐
175 ated.
176
177 pid If flag FAN_REPORT_TID was set in fanotify_init(2), this is the
178 TID of the thread that caused the event. Otherwise, this the
179 PID of the process that caused the event.
180
181 A program listening to fanotify events can compare this PID to the PID
182 returned by getpid(2), to determine whether the event is caused by the
183 listener itself, or is due to a file access by another process.
184
185 The bit mask in mask indicates which events have occurred for a single
186 filesystem object. Multiple bits may be set in this mask, if more than
187 one event occurred for the monitored filesystem object. In particular,
188 consecutive events for the same filesystem object and originating from
189 the same process may be merged into a single event, with the exception
190 that two permission events are never merged into one queue entry.
191
192 The bits that may appear in mask are as follows:
193
194 FAN_ACCESS
195 A file or a directory (but see BUGS) was accessed (read).
196
197 FAN_OPEN
198 A file or a directory was opened.
199
200 FAN_OPEN_EXEC
201 A file was opened with the intent to be executed. See NOTES in
202 fanotify_mark(2) for additional details.
203
204 FAN_ATTRIB
205 A file or directory metadata was changed.
206
207 FAN_CREATE
208 A child file or directory was created in a watched parent.
209
210 FAN_DELETE
211 A child file or directory was deleted in a watched parent.
212
213 FAN_DELETE_SELF
214 A watched file or directory was deleted.
215
216 FAN_MOVED_FROM
217 A file or directory has been moved from a watched parent direc‐
218 tory.
219
220 FAN_MOVED_TO
221 A file or directory has been moved to a watched parent direc‐
222 tory.
223
224 FAN_MOVE_SELF
225 A watched file or directory was moved.
226
227 FAN_MODIFY
228 A file was modified.
229
230 FAN_CLOSE_WRITE
231 A file that was opened for writing (O_WRONLY or O_RDWR) was
232 closed.
233
234 FAN_CLOSE_NOWRITE
235 A file or directory that was opened read-only (O_RDONLY) was
236 closed.
237
238 FAN_Q_OVERFLOW
239 The event queue exceeded the limit of 16384 entries. This limit
240 can be overridden by specifying the FAN_UNLIMITED_QUEUE flag
241 when calling fanotify_init(2).
242
243 FAN_ACCESS_PERM
244 An application wants to read a file or directory, for example
245 using read(2) or readdir(2). The reader must write a response
246 (as described below) that determines whether the permission to
247 access the filesystem object shall be granted.
248
249 FAN_OPEN_PERM
250 An application wants to open a file or directory. The reader
251 must write a response that determines whether the permission to
252 open the filesystem object shall be granted.
253
254 FAN_OPEN_EXEC_PERM
255 An application wants to open a file for execution. The reader
256 must write a response that determines whether the permission to
257 open the filesystem object for execution shall be granted. See
258 NOTES in fanotify_mark(2) for additional details.
259
260 To check for any close event, the following bit mask may be used:
261
262 FAN_CLOSE
263 A file was closed. This is a synonym for:
264
265 FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE
266
267 To check for any move event, the following bit mask may be used:
268
269 FAN_MOVE
270 A file or directory was moved. This is a synonym for:
271
272 FAN_MOVED_FROM | FAN_MOVED_TO
273
274 The following bits may appear in mask only in conjunction with other
275 event type bits:
276
277 FAN_ONDIR
278 The events described in the mask have occurred on a directory
279 object. Reporting events on directories requires setting this
280 flag in the mark mask. See fanotify_mark(2) for additional de‐
281 tails. The FAN_ONDIR flag is reported in an event mask only if
282 the fanotify group identifies filesystem objects by file han‐
283 dles.
284
285 The fields of the fanotify_event_info_fid structure are as follows:
286
287 hdr This is a structure of type fanotify_event_info_header. It is a
288 generic header that contains information used to describe an ad‐
289 ditional information record attached to the event. For example,
290 when an fanotify file descriptor is created using FAN_RE‐
291 PORT_FID, a single information record is expected to be attached
292 to the event with info_type field value of
293 FAN_EVENT_INFO_TYPE_FID. When an fanotify file descriptor is
294 created using the combination of FAN_REPORT_FID and FAN_RE‐
295 PORT_DIR_FID, there may be two information records attached to
296 the event: one with info_type field value of
297 FAN_EVENT_INFO_TYPE_DFID, identifying a parent directory object,
298 and one with info_type field value of FAN_EVENT_INFO_TYPE_FID,
299 identifying a non-directory object. The fan‐
300 otify_event_info_header contains a len field. The value of len
301 is the size of the additional information record including the
302 fanotify_event_info_header itself. The total size of all addi‐
303 tional information records is not expected to be bigger than (
304 event_len - metadata_len ).
305
306 fsid This is a unique identifier of the filesystem containing the ob‐
307 ject associated with the event. It is a structure of type
308 __kernel_fsid_t and contains the same value as f_fsid when call‐
309 ing statfs(2).
310
311 file_handle
312 This is a variable length structure of type struct file_handle.
313 It is an opaque handle that corresponds to a specified object on
314 a filesystem as returned by name_to_handle_at(2). It can be
315 used to uniquely identify a file on a filesystem and can be
316 passed as an argument to open_by_handle_at(2). Note that for
317 the directory entry modification events FAN_CREATE, FAN_DELETE,
318 and FAN_MOVE, the file_handle identifies the modified directory
319 and not the created/deleted/moved child object. If the value of
320 info_type field is FAN_EVENT_INFO_TYPE_DFID_NAME, the file han‐
321 dle is followed by a null terminated string that identifies the
322 created/deleted/moved directory entry name. For other events
323 such as FAN_OPEN, FAN_ATTRIB, FAN_DELETE_SELF, and
324 FAN_MOVE_SELF, if the value of info_type field is
325 FAN_EVENT_INFO_TYPE_FID, the file_handle identifies the object
326 correlated to the event. If the value of info_type field is
327 FAN_EVENT_INFO_TYPE_DFID, the file_handle identifies the direc‐
328 tory object correlated to the event or the parent directory of a
329 non-directory object correlated to the event. If the value of
330 info_type field is FAN_EVENT_INFO_TYPE_DFID_NAME, the file_han‐
331 dle identifies the same directory object that would be reported
332 with FAN_EVENT_INFO_TYPE_DFID and the file handle is followed by
333 a null terminated string that identifies the name of a directory
334 entry in that directory, or '.' to identify the directory object
335 itself.
336
337 The following macros are provided to iterate over a buffer containing
338 fanotify event metadata returned by a read(2) from an fanotify file de‐
339 scriptor:
340
341 FAN_EVENT_OK(meta, len)
342 This macro checks the remaining length len of the buffer meta
343 against the length of the metadata structure and the event_len
344 field of the first metadata structure in the buffer.
345
346 FAN_EVENT_NEXT(meta, len)
347 This macro uses the length indicated in the event_len field of
348 the metadata structure pointed to by meta to calculate the ad‐
349 dress of the next metadata structure that follows meta. len is
350 the number of bytes of metadata that currently remain in the
351 buffer. The macro returns a pointer to the next metadata struc‐
352 ture that follows meta, and reduces len by the number of bytes
353 in the metadata structure that has been skipped over (i.e., it
354 subtracts meta->event_len from len).
355
356 In addition, there is:
357
358 FAN_EVENT_METADATA_LEN
359 This macro returns the size (in bytes) of the structure fan‐
360 otify_event_metadata. This is the minimum size (and currently
361 the only size) of any event metadata.
362
363 Monitoring an fanotify file descriptor for events
364 When an fanotify event occurs, the fanotify file descriptor indicates
365 as readable when passed to epoll(7), poll(2), or select(2).
366
367 Dealing with permission events
368 For permission events, the application must write(2) a structure of the
369 following form to the fanotify file descriptor:
370
371 struct fanotify_response {
372 __s32 fd;
373 __u32 response;
374 };
375
376 The fields of this structure are as follows:
377
378 fd This is the file descriptor from the structure fan‐
379 otify_event_metadata.
380
381 response
382 This field indicates whether or not the permission is to be
383 granted. Its value must be either FAN_ALLOW to allow the file
384 operation or FAN_DENY to deny the file operation.
385
386 If access is denied, the requesting application call will receive an
387 EPERM error. Additionally, if the notification group has been created
388 with the FAN_ENABLE_AUDIT flag, then the FAN_AUDIT flag can be set in
389 the response field. In that case, the audit subsystem will log infor‐
390 mation about the access decision to the audit logs.
391
392 Closing the fanotify file descriptor
393 When all file descriptors referring to the fanotify notification group
394 are closed, the fanotify group is released and its resources are freed
395 for reuse by the kernel. Upon close(2), outstanding permission events
396 will be set to allowed.
397
398 /proc/[pid]/fdinfo
399 The file /proc/[pid]/fdinfo/[fd] contains information about fanotify
400 marks for file descriptor fd of process pid. See proc(5) for details.
401
403 In addition to the usual errors for read(2), the following errors can
404 occur when reading from the fanotify file descriptor:
405
406 EINVAL The buffer is too small to hold the event.
407
408 EMFILE The per-process limit on the number of open files has been
409 reached. See the description of RLIMIT_NOFILE in getrlimit(2).
410
411 ENFILE The system-wide limit on the total number of open files has been
412 reached. See /proc/sys/fs/file-max in proc(5).
413
414 ETXTBSY
415 This error is returned by read(2) if O_RDWR or O_WRONLY was
416 specified in the event_f_flags argument when calling fan‐
417 otify_init(2) and an event occurred for a monitored file that is
418 currently being executed.
419
420 In addition to the usual errors for write(2), the following errors can
421 occur when writing to the fanotify file descriptor:
422
423 EINVAL Fanotify access permissions are not enabled in the kernel con‐
424 figuration or the value of response in the response structure is
425 not valid.
426
427 ENOENT The file descriptor fd in the response structure is not valid.
428 This may occur when a response for the permission event has al‐
429 ready been written.
430
432 The fanotify API was introduced in version 2.6.36 of the Linux kernel
433 and enabled in version 2.6.37. Fdinfo support was added in version
434 3.8.
435
437 The fanotify API is Linux-specific.
438
440 The fanotify API is available only if the kernel was built with the
441 CONFIG_FANOTIFY configuration option enabled. In addition, fanotify
442 permission handling is available only if the CONFIG_FANOTIFY_AC‐
443 CESS_PERMISSIONS configuration option is enabled.
444
445 Limitations and caveats
446 Fanotify reports only events that a user-space program triggers through
447 the filesystem API. As a result, it does not catch remote events that
448 occur on network filesystems.
449
450 The fanotify API does not report file accesses and modifications that
451 may occur because of mmap(2), msync(2), and munmap(2).
452
453 Events for directories are created only if the directory itself is
454 opened, read, and closed. Adding, removing, or changing children of a
455 marked directory does not create events for the monitored directory it‐
456 self.
457
458 Fanotify monitoring of directories is not recursive: to monitor subdi‐
459 rectories under a directory, additional marks must be created. The
460 FAN_CREATE event can be used for detecting when a subdirectory has been
461 created under a marked directory. An additional mark must then be set
462 on the newly created subdirectory. This approach is racy, because it
463 can lose events that occurred inside the newly created subdirectory,
464 before a mark is added on that subdirectory. Monitoring mounts offers
465 the capability to monitor a whole directory tree in a race-free manner.
466 Monitoring filesystems offers the capability to monitor changes made
467 from any mount of a filesystem instance in a race-free manner.
468
469 The event queue can overflow. In this case, events are lost.
470
472 Before Linux 3.19, fallocate(2) did not generate fanotify events.
473 Since Linux 3.19, calls to fallocate(2) generate FAN_MODIFY events.
474
475 As of Linux 3.17, the following bugs exist:
476
477 * On Linux, a filesystem object may be accessible through multiple
478 paths, for example, a part of a filesystem may be remounted using
479 the --bind option of mount(8). A listener that marked a mount will
480 be notified only of events that were triggered for a filesystem ob‐
481 ject using the same mount. Any other event will pass unnoticed.
482
483 * When an event is generated, no check is made to see whether the user
484 ID of the receiving process has authorization to read or write the
485 file before passing a file descriptor for that file. This poses a
486 security risk, when the CAP_SYS_ADMIN capability is set for programs
487 executed by unprivileged users.
488
489 * If a call to read(2) processes multiple events from the fanotify
490 queue and an error occurs, the return value will be the total length
491 of the events successfully copied to the user-space buffer before
492 the error occurred. The return value will not be -1, and errno will
493 not be set. Thus, the reading application has no way to detect the
494 error.
495
497 The two example programs below demonstrate the usage of the fanotify
498 API.
499
500 Example program: fanotify_example.c
501 The first program is an example of fanotify being used with its event
502 object information passed in the form of a file descriptor. The pro‐
503 gram marks the mount passed as a command-line argument and waits for
504 events of type FAN_OPEN_PERM and FAN_CLOSE_WRITE. When a permission
505 event occurs, a FAN_ALLOW response is given.
506
507 The following shell session shows an example of running this program.
508 This session involved editing the file /home/user/temp/notes. Before
509 the file was opened, a FAN_OPEN_PERM event occurred. After the file
510 was closed, a FAN_CLOSE_WRITE event occurred. Execution of the program
511 ends when the user presses the ENTER key.
512
513 # ./fanotify_example /home
514 Press enter key to terminate.
515 Listening for events.
516 FAN_OPEN_PERM: File /home/user/temp/notes
517 FAN_CLOSE_WRITE: File /home/user/temp/notes
518
519 Listening for events stopped.
520
521 Program source: fanotify_example.c
522
523 #define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
524 #include <errno.h>
525 #include <fcntl.h>
526 #include <limits.h>
527 #include <poll.h>
528 #include <stdio.h>
529 #include <stdlib.h>
530 #include <sys/fanotify.h>
531 #include <unistd.h>
532
533 /* Read all available fanotify events from the file descriptor 'fd'. */
534
535 static void
536 handle_events(int fd)
537 {
538 const struct fanotify_event_metadata *metadata;
539 struct fanotify_event_metadata buf[200];
540 ssize_t len;
541 char path[PATH_MAX];
542 ssize_t path_len;
543 char procfd_path[PATH_MAX];
544 struct fanotify_response response;
545
546 /* Loop while events can be read from fanotify file descriptor. */
547
548 for (;;) {
549
550 /* Read some events. */
551
552 len = read(fd, buf, sizeof(buf));
553 if (len == -1 && errno != EAGAIN) {
554 perror("read");
555 exit(EXIT_FAILURE);
556 }
557
558 /* Check if end of available data reached. */
559
560 if (len <= 0)
561 break;
562
563 /* Point to the first event in the buffer. */
564
565 metadata = buf;
566
567 /* Loop over all events in the buffer. */
568
569 while (FAN_EVENT_OK(metadata, len)) {
570
571 /* Check that run-time and compile-time structures match. */
572
573 if (metadata->vers != FANOTIFY_METADATA_VERSION) {
574 fprintf(stderr,
575 "Mismatch of fanotify metadata version.\n");
576 exit(EXIT_FAILURE);
577 }
578
579 /* metadata->fd contains either FAN_NOFD, indicating a
580 queue overflow, or a file descriptor (a nonnegative
581 integer). Here, we simply ignore queue overflow. */
582
583 if (metadata->fd >= 0) {
584
585 /* Handle open permission event. */
586
587 if (metadata->mask & FAN_OPEN_PERM) {
588 printf("FAN_OPEN_PERM: ");
589
590 /* Allow file to be opened. */
591
592 response.fd = metadata->fd;
593 response.response = FAN_ALLOW;
594 write(fd, &response, sizeof(response));
595 }
596
597 /* Handle closing of writable file event. */
598
599 if (metadata->mask & FAN_CLOSE_WRITE)
600 printf("FAN_CLOSE_WRITE: ");
601
602 /* Retrieve and print pathname of the accessed file. */
603
604 snprintf(procfd_path, sizeof(procfd_path),
605 "/proc/self/fd/%d", metadata->fd);
606 path_len = readlink(procfd_path, path,
607 sizeof(path) - 1);
608 if (path_len == -1) {
609 perror("readlink");
610 exit(EXIT_FAILURE);
611 }
612
613 path[path_len] = '\0';
614 printf("File %s\n", path);
615
616 /* Close the file descriptor of the event. */
617
618 close(metadata->fd);
619 }
620
621 /* Advance to next event. */
622
623 metadata = FAN_EVENT_NEXT(metadata, len);
624 }
625 }
626 }
627
628 int
629 main(int argc, char *argv[])
630 {
631 char buf;
632 int fd, poll_num;
633 nfds_t nfds;
634 struct pollfd fds[2];
635
636 /* Check mount point is supplied. */
637
638 if (argc != 2) {
639 fprintf(stderr, "Usage: %s MOUNT\n", argv[0]);
640 exit(EXIT_FAILURE);
641 }
642
643 printf("Press enter key to terminate.\n");
644
645 /* Create the file descriptor for accessing the fanotify API. */
646
647 fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
648 O_RDONLY | O_LARGEFILE);
649 if (fd == -1) {
650 perror("fanotify_init");
651 exit(EXIT_FAILURE);
652 }
653
654 /* Mark the mount for:
655 - permission events before opening files
656 - notification events after closing a write-enabled
657 file descriptor. */
658
659 if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
660 FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
661 argv[1]) == -1) {
662 perror("fanotify_mark");
663 exit(EXIT_FAILURE);
664 }
665
666 /* Prepare for polling. */
667
668 nfds = 2;
669
670 fds[0].fd = STDIN_FILENO; /* Console input */
671 fds[0].events = POLLIN;
672
673 fds[1].fd = fd; /* Fanotify input */
674 fds[1].events = POLLIN;
675
676 /* This is the loop to wait for incoming events. */
677
678 printf("Listening for events.\n");
679
680 while (1) {
681 poll_num = poll(fds, nfds, -1);
682 if (poll_num == -1) {
683 if (errno == EINTR) /* Interrupted by a signal */
684 continue; /* Restart poll() */
685
686 perror("poll"); /* Unexpected error */
687 exit(EXIT_FAILURE);
688 }
689
690 if (poll_num > 0) {
691 if (fds[0].revents & POLLIN) {
692
693 /* Console input is available: empty stdin and quit. */
694
695 while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
696 continue;
697 break;
698 }
699
700 if (fds[1].revents & POLLIN) {
701
702 /* Fanotify events are available. */
703
704 handle_events(fd);
705 }
706 }
707 }
708
709 printf("Listening for events stopped.\n");
710 exit(EXIT_SUCCESS);
711 }
712
713 Example program: fanotify_fid.c
714 The second program is an example of fanotify being used with a group
715 that identifies objects by file handles. The program marks the
716 filesystem object that is passed as a command-line argument and waits
717 until an event of type FAN_CREATE has occurred. The event mask indi‐
718 cates which type of filesystem object—either a file or a directory—was
719 created. Once all events have been read from the buffer and processed
720 accordingly, the program simply terminates.
721
722 The following shell sessions show two different invocations of this
723 program, with different actions performed on a watched object.
724
725 The first session shows a mark being placed on /home/user. This is
726 followed by the creation of a regular file, /home/user/testfile.txt.
727 This results in a FAN_CREATE event being generated and reported against
728 the file's parent watched directory object and with the created file
729 name. Program execution ends once all events captured within the buf‐
730 fer have been processed.
731
732 # ./fanotify_fid /home/user
733 Listening for events.
734 FAN_CREATE (file created):
735 Directory /home/user has been modified.
736 Entry 'testfile.txt' is not a subdirectory.
737 All events processed successfully. Program exiting.
738
739 $ touch /home/user/testfile.txt # In another terminal
740
741 The second session shows a mark being placed on /home/user. This is
742 followed by the creation of a directory, /home/user/testdir. This spe‐
743 cific action results in a FAN_CREATE event being generated and is re‐
744 ported with the FAN_ONDIR flag set and with the created directory name.
745
746 # ./fanotify_fid /home/user
747 Listening for events.
748 FAN_CREATE | FAN_ONDIR (subdirectory created):
749 Directory /home/user has been modified.
750 Entry 'testdir' is a subdirectory.
751 All events processed successfully. Program exiting.
752
753 $ mkdir -p /home/user/testdir # In another terminal
754
755 Program source: fanotify_fid.c
756
757 #define _GNU_SOURCE
758 #include <errno.h>
759 #include <fcntl.h>
760 #include <limits.h>
761 #include <stdio.h>
762 #include <stdlib.h>
763 #include <sys/types.h>
764 #include <sys/stat.h>
765 #include <sys/fanotify.h>
766 #include <unistd.h>
767
768 #define BUF_SIZE 256
769
770 int
771 main(int argc, char *argv[])
772 {
773 int fd, ret, event_fd, mount_fd;
774 ssize_t len, path_len;
775 char path[PATH_MAX];
776 char procfd_path[PATH_MAX];
777 char events_buf[BUF_SIZE];
778 struct file_handle *file_handle;
779 struct fanotify_event_metadata *metadata;
780 struct fanotify_event_info_fid *fid;
781 const char *file_name;
782 struct stat sb;
783
784 if (argc != 2) {
785 fprintf(stderr, "Invalid number of command line arguments.\n");
786 exit(EXIT_FAILURE);
787 }
788
789 mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
790 if (mount_fd == -1) {
791 perror(argv[1]);
792 exit(EXIT_FAILURE);
793 }
794
795
796 /* Create an fanotify file descriptor with FAN_REPORT_DFID_NAME as
797 a flag so that program can receive fid events with directory
798 entry name. */
799
800 fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME, 0);
801 if (fd == -1) {
802 perror("fanotify_init");
803 exit(EXIT_FAILURE);
804 }
805
806 /* Place a mark on the filesystem object supplied in argv[1]. */
807
808 ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR,
809 FAN_CREATE | FAN_ONDIR,
810 AT_FDCWD, argv[1]);
811 if (ret == -1) {
812 perror("fanotify_mark");
813 exit(EXIT_FAILURE);
814 }
815
816 printf("Listening for events.\n");
817
818 /* Read events from the event queue into a buffer. */
819
820 len = read(fd, events_buf, sizeof(events_buf));
821 if (len == -1 && errno != EAGAIN) {
822 perror("read");
823 exit(EXIT_FAILURE);
824 }
825
826 /* Process all events within the buffer. */
827
828 for (metadata = (struct fanotify_event_metadata *) events_buf;
829 FAN_EVENT_OK(metadata, len);
830 metadata = FAN_EVENT_NEXT(metadata, len)) {
831 fid = (struct fanotify_event_info_fid *) (metadata + 1);
832 file_handle = (struct file_handle *) fid->handle;
833
834 /* Ensure that the event info is of the correct type. */
835
836 if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_FID ||
837 fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID) {
838 file_name = NULL;
839 } else if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) {
840 file_name = file_handle->f_handle +
841 file_handle->handle_bytes;
842 } else {
843 fprintf(stderr, "Received unexpected event info type.\n");
844 exit(EXIT_FAILURE);
845 }
846
847 if (metadata->mask == FAN_CREATE)
848 printf("FAN_CREATE (file created):\n");
849
850 if (metadata->mask == (FAN_CREATE | FAN_ONDIR))
851 printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\n");
852
853 /* metadata->fd is set to FAN_NOFD when the group identifies
854 objects by file handles. To obtain a file descriptor for
855 the file object corresponding to an event you can use the
856 struct file_handle that's provided within the
857 fanotify_event_info_fid in conjunction with the
858 open_by_handle_at(2) system call. A check for ESTALE is
859 done to accommodate for the situation where the file handle
860 for the object was deleted prior to this system call. */
861
862 event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
863 if (event_fd == -1) {
864 if (errno == ESTALE) {
865 printf("File handle is no longer valid. "
866 "File has been deleted\n");
867 continue;
868 } else {
869 perror("open_by_handle_at");
870 exit(EXIT_FAILURE);
871 }
872 }
873
874 snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
875 event_fd);
876
877 /* Retrieve and print the path of the modified dentry. */
878
879 path_len = readlink(procfd_path, path, sizeof(path) - 1);
880 if (path_len == -1) {
881 perror("readlink");
882 exit(EXIT_FAILURE);
883 }
884
885 path[path_len] = '\0';
886 printf("\tDirectory '%s' has been modified.\n", path);
887
888 if (file_name) {
889 ret = fstatat(event_fd, file_name, &sb, 0);
890 if (ret == -1) {
891 if (errno != ENOENT) {
892 perror("fstatat");
893 exit(EXIT_FAILURE);
894 }
895 printf("\tEntry '%s' does not exist.\n", file_name);
896 } else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
897 printf("\tEntry '%s' is a subdirectory.\n", file_name);
898 } else {
899 printf("\tEntry '%s' is not a subdirectory.\n",
900 file_name);
901 }
902 }
903
904 /* Close associated file descriptor for this event. */
905
906 close(event_fd);
907 }
908
909 printf("All events processed successfully. Program exiting.\n");
910 exit(EXIT_SUCCESS);
911 }
912
914 fanotify_init(2), fanotify_mark(2), inotify(7)
915
917 This page is part of release 5.13 of the Linux man-pages project. A
918 description of the project, information about reporting bugs, and the
919 latest version of this page, can be found at
920 https://www.kernel.org/doc/man-pages/.
921
922
923
924Linux 2021-08-27 FANOTIFY(7)