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