]> git.ipfire.org Git - thirdparty/man-pages.git/blame_incremental - man7/fanotify.7
fanotify.7: wfix
[thirdparty/man-pages.git] / man7 / fanotify.7
... / ...
CommitLineData
1.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@gmx.de>
2.\" and Copyright (C) 2014, Michael Kerrisk <mtk.manpages@gmail.com>
3.\"
4.\" %%%LICENSE_START(VERBATIM)
5.\" Permission is granted to make and distribute verbatim copies of this
6.\" manual provided the copyright notice and this permission notice are
7.\" preserved on all copies.
8.\"
9.\" Permission is granted to copy and distribute modified versions of
10.\" this manual under the conditions for verbatim copying, provided that
11.\" the entire resulting derived work is distributed under the terms of
12.\" a permission notice identical to this one.
13.\"
14.\" Since the Linux kernel and libraries are constantly changing, this
15.\" manual page may be incorrect or out-of-date. The author(s) assume.
16.\" no responsibility for errors or omissions, or for damages resulting.
17.\" from the use of the information contained herein. The author(s) may.
18.\" not have taken the same level of care in the production of this.
19.\" manual, which is licensed free of charge, as they might when working.
20.\" professionally.
21.\"
22.\" Formatted or processed versions of this manual, if unaccompanied by
23.\" the source, must acknowledge the copyright and authors of this work.
24.\" %%%LICENSE_END
25.TH FANOTIFY 7 2019-03-06 "Linux" "Linux Programmer's Manual"
26.SH NAME
27fanotify \- monitoring filesystem events
28.SH DESCRIPTION
29The fanotify API provides notification and interception of
30filesystem events.
31Use cases include virus scanning and hierarchical storage management.
32Currently, only a limited set of events is supported.
33In particular, there is no support for create, delete, and move events.
34(See
35.BR inotify (7)
36for details of an API that does notify those events.)
37.PP
38Additional capabilities compared to the
39.BR inotify (7)
40API include the ability to monitor all of the objects
41in a mounted filesystem,
42the ability to make access permission decisions, and the
43possibility to read or modify files before access by other applications.
44.PP
45The following system calls are used with this API:
46.BR fanotify_init (2),
47.BR fanotify_mark (2),
48.BR read (2),
49.BR write (2),
50and
51.BR close (2).
52.SS fanotify_init(), fanotify_mark(), and notification groups
53The
54.BR fanotify_init (2)
55system call creates and initializes an fanotify notification group
56and returns a file descriptor referring to it.
57.PP
58An fanotify notification group is a kernel-internal object that holds
59a list of files, directories, filesystems, and mount points for which
60events shall be created.
61.PP
62For each entry in an fanotify notification group, two bit masks exist: the
63.I mark
64mask and the
65.I ignore
66mask.
67The mark mask defines file activities for which an event shall be created.
68The ignore mask defines activities for which no event shall be generated.
69Having these two types of masks permits a filesystem, mount point, or
70directory to be marked for receiving events, while at the same time
71ignoring events for specific objects under a mount point or directory.
72.PP
73The
74.BR fanotify_mark (2)
75system call adds a file, directory, filesystem or mount point to a
76notification group and specifies which events
77shall be reported (or ignored), or removes or modifies such an entry.
78.PP
79A possible usage of the ignore mask is for a file cache.
80Events of interest for a file cache are modification of a file and closing
81of the same.
82Hence, the cached directory or mount point is to be marked to receive these
83events.
84After receiving the first event informing that a file has been modified,
85the corresponding cache entry will be invalidated.
86No further modification events for this file are of interest until the file
87is closed.
88Hence, the modify event can be added to the ignore mask.
89Upon receiving the close event, the modify event can be removed from the
90ignore mask and the file cache entry can be updated.
91.PP
92The entries in the fanotify notification groups refer to files and
93directories via their inode number and to mounts via their mount ID.
94If files or directories are renamed or moved within the same mount,
95the respective entries survive.
96If files or directories are deleted or moved to another mount or if
97filesystems or mounts are unmounted, the corresponding entries are deleted.
98.SS The event queue
99As events occur on the filesystem objects monitored by a notification group,
100the fanotify system generates events that are collected in a queue.
101These events can then be read (using
102.BR read (2)
103or similar)
104from the fanotify file descriptor
105returned by
106.BR fanotify_init (2).
107.PP
108Two types of events are generated:
109.I notification
110events and
111.I permission
112events.
113Notification events are merely informative
114and require no action to be taken by
115the receiving application with the exception being that the file
116descriptor provided within a generic event must be closed.
117The closing of file descriptors for each event applies only to
118applications that have initialized fanotify without using
119.BR FAN_REPORT_FID
120(see below).
121Permission events are requests to the receiving application to decide
122whether permission for a file access shall be granted.
123For these events, the recipient must write a response which decides whether
124access is granted or not.
125.PP
126An event is removed from the event queue of the fanotify group
127when it has been read.
128Permission events that have been read are kept in an internal list of the
129fanotify group until either a permission decision has been taken by
130writing to the fanotify file descriptor or the fanotify file descriptor
131is closed.
132.SS Reading fanotify events
133Calling
134.BR read (2)
135for the file descriptor returned by
136.BR fanotify_init (2)
137blocks (if the flag
138.B FAN_NONBLOCK
139is not specified in the call to
140.BR fanotify_init (2))
141until either a file event occurs or the call is interrupted by a signal
142(see
143.BR signal (7)).
144.PP
145The use of the
146.BR FAN_REPORT_FID
147flag in
148.BR fanotify_init (2)
149influences what data structures are returned to the event listener for each
150event.
151After a successful
152.BR read (2),
153the read buffer contains one or more of the following structures:
154.PP
155.in +4n
156.EX
157struct fanotify_event_metadata {
158 __u32 event_len;
159 __u8 vers;
160 __u8 reserved;
161 __u16 metadata_len;
162 __aligned_u64 mask;
163 __s32 fd;
164 __s32 pid;
165};
166.EE
167.in
168.PP
169In the case where
170.BR FAN_REPORT_FID
171is supplied as one of the flags to
172.BR fanotify_init (2),
173you should also expect to receive the structure detailed below following
174the generic
175.I fanotify_event_metadata
176structure within the read buffer:
177.PP
178.in +4n
179.EX
180struct fanotify_event_info_fid {
181 struct fanotify_event_info_header hdr;
182 __kernel_fsid_t fsid;
183 unsigned char file_handle[0];
184};
185.EE
186.in
187.PP
188For performance reasons, it is recommended to use a large
189buffer size (for example, 4096 bytes),
190so that multiple events can be retrieved by a single
191.BR read (2).
192.PP
193The return value of
194.BR read (2)
195is the number of bytes placed in the buffer,
196or \-1 in case of an error (but see BUGS).
197.PP
198The fields of the
199.I fanotify_event_metadata
200structure are as follows:
201.TP
202.I event_len
203This is the length of the data for the current event and the offset
204to the next event in the buffer.
205Without
206.BR FAN_REPORT_FID ,
207the value of
208.I event_len
209is always
210.BR FAN_EVENT_METADATA_LEN .
211With
212.BR FAN_REPORT_FID ,
213.I event_len
214also includes the variable length file identifier.
215.TP
216.I vers
217This field holds a version number for the structure.
218It must be compared to
219.B FANOTIFY_METADATA_VERSION
220to verify that the structures returned at run time match
221the structures defined at compile time.
222In case of a mismatch, the application should abandon trying to use the
223fanotify file descriptor.
224.TP
225.I reserved
226This field is not used.
227.TP
228.I metadata_len
229This is the length of the structure.
230The field was introduced to facilitate the implementation of
231optional headers per event type.
232No such optional headers exist in the current implementation.
233.TP
234.I mask
235This is a bit mask describing the event (see below).
236.TP
237.I fd
238This is an open file descriptor for the object being accessed, or
239.B FAN_NOFD
240if a queue overflow occurred.
241If the fanotify file descriptor has been initialized using
242.BR FAN_REPORT_FID ,
243applications should expect this value to be set to
244.B FAN_NOFD
245for each event that is received.
246The file descriptor can be used to access the contents
247of the monitored file or directory.
248The reading application is responsible for closing this file descriptor.
249.IP
250When calling
251.BR fanotify_init (2),
252the caller may specify (via the
253.I event_f_flags
254argument) various file status flags that are to be set
255on the open file description that corresponds to this file descriptor.
256In addition, the (kernel-internal)
257.B FMODE_NONOTIFY
258file status flag is set on the open file description.
259This flag suppresses fanotify event generation.
260Hence, when the receiver of the fanotify event accesses the notified file or
261directory using this file descriptor, no additional events will be created.
262.TP
263.I pid
264If flag
265.B FAN_REPORT_TID
266was set in
267.BR fanotify_init (2),
268this is the TID of the thread that caused the event.
269Otherwise, this the PID of the process that caused the event.
270.PP
271A program listening to fanotify events can compare this PID
272to the PID returned by
273.BR getpid (2),
274to determine whether the event is caused by the listener itself,
275or is due to a file access by another process.
276.PP
277The bit mask in
278.I mask
279indicates which events have occurred for a single filesystem object.
280Multiple bits may be set in this mask,
281if more than one event occurred for the monitored filesystem object.
282In particular,
283consecutive events for the same filesystem object and originating from the
284same process may be merged into a single event, with the exception that two
285permission events are never merged into one queue entry.
286.PP
287The bits that may appear in
288.I mask
289are as follows:
290.TP
291.B FAN_ACCESS
292A file or a directory (but see BUGS) was accessed (read).
293.TP
294.B FAN_OPEN
295A file or a directory was opened.
296.TP
297.B FAN_OPEN_EXEC
298A file was opened with the intent to be executed.
299See NOTES in
300.BR fanotify_mark (2)
301for additional details.
302.TP
303.B FAN_ATTRIB
304A file or directory metadata was changed.
305.TP
306.B FAN_CREATE
307A child file or directory was created in a watched parent.
308.TP
309.B FAN_DELETE
310A child file or directory was deleted in a watched parent.
311.TP
312.B FAN_DELETE_SELF
313A watched file or directory was deleted.
314.TP
315.B FAN_MOVED_FROM
316A file or directory has been moved from a watched parent directory.
317.TP
318.B FAN_MOVED_TO
319A file or directory has been moved to a watched parent directory.
320.TP
321.B FAN_MOVE_SELF
322A watched file or directory was moved.
323.TP
324.B FAN_MODIFY
325A file was modified.
326.TP
327.B FAN_CLOSE_WRITE
328A file that was opened for writing
329.RB ( O_WRONLY
330or
331.BR O_RDWR )
332was closed.
333.TP
334.B FAN_CLOSE_NOWRITE
335A file or directory that was opened read-only
336.RB ( O_RDONLY )
337was closed.
338.TP
339.B FAN_Q_OVERFLOW
340The event queue exceeded the limit of 16384 entries.
341This limit can be overridden by specifying the
342.BR FAN_UNLIMITED_QUEUE
343flag when calling
344.BR fanotify_init (2).
345.TP
346.B FAN_ACCESS_PERM
347An application wants to read a file or directory, for example using
348.BR read (2)
349or
350.BR readdir (2).
351The reader must write a response (as described below)
352that determines whether the permission to
353access the filesystem object shall be granted.
354.TP
355.B FAN_OPEN_PERM
356An application wants to open a file or directory.
357The reader must write a response that determines whether the permission to
358open the filesystem object shall be granted.
359.TP
360.B FAN_OPEN_EXEC_PERM
361An application wants to open a file for execution.
362The reader must write a response that determines whether the permission to
363open the filesystem object for execution shall be granted.
364See NOTES in
365.BR fanotify_mark (2)
366for additional details.
367.PP
368To check for any close event, the following bit mask may be used:
369.TP
370.B FAN_CLOSE
371A file was closed.
372This is a synonym for:
373.IP
374 FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE
375.PP
376To check for any move event, the following bit mask may be used:
377.TP
378.B FAN_MOVE
379A file or directory was moved.
380This is a synonym for:
381.IP
382 FAN_MOVED_FROM | FAN_MOVED_TO
383.PP
384The fields of the
385.I fanotify_event_info_fid
386structure are as follows:
387.TP
388.I hdr
389This is a structure of type
390.IR fanotify_event_info_header .
391It is a generic header that contains information used to describe
392additional information attached to the event.
393For example, when an fanotify file descriptor is created using
394.BR FAN_REPORT_FID ,
395the
396.I info_type
397field of this header is set to
398.BR FAN_EVENT_INFO_TYPE_FID .
399Event listeners can use this field to check that the additional
400information received for an event is of the correct type.
401Additionally, the
402.I fanotify_event_info_header
403also contains a
404.I len
405field.
406In the current implementation, the value of
407.I len
408is always (event_len \- FAN_EVENT_METADATA_LEN).
409.TP
410.I fsid
411This is a unique identifier of the filesystem containing the object
412associated with the event.
413It is a structure of type
414.I __kernel_fsid_t
415and contains the same value as
416.I f_fsid
417when calling
418.BR statfs (2).
419.TP
420.I file_handle
421This is a variable length structure of type
422.IR file_handle .
423It is an opaque handle that corresponds to a specified object on a
424filesystem as returned by
425.BR name_to_handle_at (2).
426It can be used to uniquely identify a file on a filesystem and can be
427passed as an argument to
428.BR open_by_handle_at (2).
429Note that for directory entry events, such as
430.BR FAN_CREATE ,
431.BR FAN_DELETE ,
432and
433.BR FAN_MOVE ,
434the
435.IR file_handle
436describes the modified directory and not the created/deleted/moved child
437object.
438The events
439.BR FAN_ATTRIB ,
440.BR FAN_DELETE_SELF ,
441and
442.BR FAN_MOVE_SELF
443will carry the
444.IR file_handle
445information for the child object if the child object is being watched.
446.PP
447The following macros are provided to iterate over a buffer containing
448fanotify event metadata returned by a
449.BR read (2)
450from an fanotify file descriptor:
451.TP
452.B FAN_EVENT_OK(meta, len)
453This macro checks the remaining length
454.I len
455of the buffer
456.I meta
457against the length of the metadata structure and the
458.I event_len
459field of the first metadata structure in the buffer.
460.TP
461.B FAN_EVENT_NEXT(meta, len)
462This macro uses the length indicated in the
463.I event_len
464field of the metadata structure pointed to by
465.IR meta
466to calculate the address of the next metadata structure that follows
467.IR meta .
468.I len
469is the number of bytes of metadata that currently remain in the buffer.
470The macro returns a pointer to the next metadata structure that follows
471.IR meta ,
472and reduces
473.I len
474by the number of bytes in the metadata structure that
475has been skipped over (i.e., it subtracts
476.IR meta\->event_len
477from
478.IR len ).
479.PP
480In addition, there is:
481.TP
482.B FAN_EVENT_METADATA_LEN
483This macro returns the size (in bytes) of the structure
484.IR fanotify_event_metadata .
485This is the minimum size (and currently the only size) of any event metadata.
486.\"
487.SS Monitoring an fanotify file descriptor for events
488When an fanotify event occurs, the fanotify file descriptor indicates as
489readable when passed to
490.BR epoll (7),
491.BR poll (2),
492or
493.BR select (2).
494.SS Dealing with permission events
495For permission events, the application must
496.BR write (2)
497a structure of the following form to the
498fanotify file descriptor:
499.PP
500.in +4n
501.EX
502struct fanotify_response {
503 __s32 fd;
504 __u32 response;
505};
506.EE
507.in
508.PP
509The fields of this structure are as follows:
510.TP
511.I fd
512This is the file descriptor from the structure
513.IR fanotify_event_metadata .
514.TP
515.I response
516This field indicates whether or not the permission is to be granted.
517Its value must be either
518.B FAN_ALLOW
519to allow the file operation or
520.B FAN_DENY
521to deny the file operation.
522.PP
523If access is denied, the requesting application call will receive an
524.BR EPERM
525error.
526.SS Closing the fanotify file descriptor
527.PP
528When all file descriptors referring to the fanotify notification group are
529closed, the fanotify group is released and its resources
530are freed for reuse by the kernel.
531Upon
532.BR close (2),
533outstanding permission events will be set to allowed.
534.SS /proc/[pid]/fdinfo
535The file
536.I /proc/[pid]/fdinfo/[fd]
537contains information about fanotify marks for file descriptor
538.I fd
539of process
540.IR pid .
541See
542.BR proc (5)
543for details.
544.SH ERRORS
545In addition to the usual errors for
546.BR read (2),
547the following errors can occur when reading from the
548fanotify file descriptor:
549.TP
550.B EINVAL
551The buffer is too small to hold the event.
552.TP
553.B EMFILE
554The per-process limit on the number of open files has been reached.
555See the description of
556.B RLIMIT_NOFILE
557in
558.BR getrlimit (2).
559.TP
560.B ENFILE
561The system-wide limit on the total number of open files has been reached.
562See
563.I /proc/sys/fs/file\-max
564in
565.BR proc (5).
566.TP
567.B ETXTBSY
568This error is returned by
569.BR read (2)
570if
571.B O_RDWR
572or
573.B O_WRONLY
574was specified in the
575.I event_f_flags
576argument when calling
577.BR fanotify_init (2)
578and an event occurred for a monitored file that is currently being executed.
579.PP
580In addition to the usual errors for
581.BR write (2),
582the following errors can occur when writing to the fanotify file descriptor:
583.TP
584.B EINVAL
585Fanotify access permissions are not enabled in the kernel configuration
586or the value of
587.I response
588in the response structure is not valid.
589.TP
590.B ENOENT
591The file descriptor
592.I fd
593in the response structure is not valid.
594This may occur when a response for the permission event has already been
595written.
596.SH VERSIONS
597The fanotify API was introduced in version 2.6.36 of the Linux kernel and
598enabled in version 2.6.37.
599Fdinfo support was added in version 3.8.
600.SH CONFORMING TO
601The fanotify API is Linux-specific.
602.SH NOTES
603The fanotify API is available only if the kernel was built with the
604.B CONFIG_FANOTIFY
605configuration option enabled.
606In addition, fanotify permission handling is available only if the
607.B CONFIG_FANOTIFY_ACCESS_PERMISSIONS
608configuration option is enabled.
609.SS Limitations and caveats
610Fanotify reports only events that a user-space program triggers through the
611filesystem API.
612As a result,
613it does not catch remote events that occur on network filesystems.
614.PP
615The fanotify API does not report file accesses and modifications that
616may occur because of
617.BR mmap (2),
618.BR msync (2),
619and
620.BR munmap (2).
621.PP
622Events for directories are created only if the directory itself is opened,
623read, and closed.
624Adding, removing, or changing children of a marked directory does not create
625events for the monitored directory itself.
626.PP
627Fanotify monitoring of directories is not recursive:
628to monitor subdirectories under a directory,
629additional marks must be created.
630(But note that the fanotify API provides no way of detecting when a
631subdirectory has been created under a marked directory,
632which makes recursive monitoring difficult.)
633Monitoring mounts offers the capability to monitor a whole directory tree.
634Monitoring filesystems offers the capability to monitor changes made from
635any mount of a filesystem instance.
636.PP
637The event queue can overflow.
638In this case, events are lost.
639.SH BUGS
640Before Linux 3.19,
641.BR fallocate (2)
642did not generate fanotify events.
643Since Linux 3.19,
644.\" commit 820c12d5d6c0890bc93dd63893924a13041fdc35
645calls to
646.BR fallocate (2)
647generate
648.B FAN_MODIFY
649events.
650.PP
651As of Linux 3.17,
652the following bugs exist:
653.IP * 3
654On Linux, a filesystem object may be accessible through multiple paths,
655for example, a part of a filesystem may be remounted using the
656.IR \-\-bind
657option of
658.BR mount (8).
659A listener that marked a mount will be notified only of events that were
660triggered for a filesystem object using the same mount.
661Any other event will pass unnoticed.
662.IP *
663.\" FIXME . A patch was proposed.
664When an event is generated,
665no check is made to see whether the user ID of the
666receiving process has authorization to read or write the file
667before passing a file descriptor for that file.
668This poses a security risk, when the
669.B CAP_SYS_ADMIN
670capability is set for programs executed by unprivileged users.
671.IP *
672If a call to
673.BR read (2)
674processes multiple events from the fanotify queue and an error occurs,
675the return value will be the total length of the events successfully
676copied to the user-space buffer before the error occurred.
677The return value will not be \-1, and
678.I errno
679will not be set.
680Thus, the reading application has no way to detect the error.
681.SH EXAMPLE
682The two example programs below demonstrate the usage of the fanotify API.
683.SS Example program: fanotify_example.c
684The first program is an example of fanotify being
685used with its event object information passed in the form of a file
686descriptor.
687The program marks the mount point passed as a command-line argument and
688waits for events of type
689.B FAN_OPEN_PERM
690and
691.BR FAN_CLOSE_WRITE .
692When a permission event occurs, a
693.B FAN_ALLOW
694response is given.
695.PP
696The following shell session shows an example of
697running this program.
698This session involved editing the file
699.IR /home/user/temp/notes .
700Before the file was opened, a
701.B FAN_OPEN_PERM
702event occurred.
703After the file was closed, a
704.B FAN_CLOSE_WRITE
705event occurred.
706Execution of the program ends when the user presses the ENTER key.
707.PP
708.in +4n
709.EX
710# \fB./fanotify_example /home\fP
711Press enter key to terminate.
712Listening for events.
713FAN_OPEN_PERM: File /home/user/temp/notes
714FAN_CLOSE_WRITE: File /home/user/temp/notes
715
716Listening for events stopped.
717.EE
718.in
719.EE
720.in
721.SS Program source: fanotify_example.c
722\&
723.EX
724#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
725#include <errno.h>
726#include <fcntl.h>
727#include <limits.h>
728#include <poll.h>
729#include <stdio.h>
730#include <stdlib.h>
731#include <sys/fanotify.h>
732#include <unistd.h>
733
734/* Read all available fanotify events from the file descriptor \(aqfd\(aq */
735
736static void
737handle_events(int fd)
738{
739 const struct fanotify_event_metadata *metadata;
740 struct fanotify_event_metadata buf[200];
741 ssize_t len;
742 char path[PATH_MAX];
743 ssize_t path_len;
744 char procfd_path[PATH_MAX];
745 struct fanotify_response response;
746
747 /* Loop while events can be read from fanotify file descriptor */
748
749 for (;;) {
750
751 /* Read some events */
752
753 len = read(fd, (void *) &buf, sizeof(buf));
754 if (len == \-1 && errno != EAGAIN) {
755 perror("read");
756 exit(EXIT_FAILURE);
757 }
758
759 /* Check if end of available data reached */
760
761 if (len <= 0)
762 break;
763
764 /* Point to the first event in the buffer */
765
766 metadata = buf;
767
768 /* Loop over all events in the buffer */
769
770 while (FAN_EVENT_OK(metadata, len)) {
771
772 /* Check that run\-time and compile\-time structures match */
773
774 if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
775 fprintf(stderr,
776 "Mismatch of fanotify metadata version.\en");
777 exit(EXIT_FAILURE);
778 }
779
780 /* metadata\->fd contains either FAN_NOFD, indicating a
781 queue overflow, or a file descriptor (a nonnegative
782 integer). Here, we simply ignore queue overflow. */
783
784 if (metadata\->fd >= 0) {
785
786 /* Handle open permission event */
787
788 if (metadata\->mask & FAN_OPEN_PERM) {
789 printf("FAN_OPEN_PERM: ");
790
791 /* Allow file to be opened */
792
793 response.fd = metadata\->fd;
794 response.response = FAN_ALLOW;
795 write(fd, &response,
796 sizeof(struct fanotify_response));
797 }
798
799 /* Handle closing of writable file event */
800
801 if (metadata\->mask & FAN_CLOSE_WRITE)
802 printf("FAN_CLOSE_WRITE: ");
803
804 /* Retrieve and print pathname of the accessed file */
805
806 snprintf(procfd_path, sizeof(procfd_path),
807 "/proc/self/fd/%d", metadata\->fd);
808 path_len = readlink(procfd_path, path,
809 sizeof(path) \- 1);
810 if (path_len == \-1) {
811 perror("readlink");
812 exit(EXIT_FAILURE);
813 }
814
815 path[path_len] = \(aq\e0\(aq;
816 printf("File %s\en", path);
817
818 /* Close the file descriptor of the event */
819
820 close(metadata\->fd);
821 }
822
823 /* Advance to next event */
824
825 metadata = FAN_EVENT_NEXT(metadata, len);
826 }
827 }
828}
829
830int
831main(int argc, char *argv[])
832{
833 char buf;
834 int fd, poll_num;
835 nfds_t nfds;
836 struct pollfd fds[2];
837
838 /* Check mount point is supplied */
839
840 if (argc != 2) {
841 fprintf(stderr, "Usage: %s MOUNT\en", argv[0]);
842 exit(EXIT_FAILURE);
843 }
844
845 printf("Press enter key to terminate.\en");
846
847 /* Create the file descriptor for accessing the fanotify API */
848
849 fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
850 O_RDONLY | O_LARGEFILE);
851 if (fd == \-1) {
852 perror("fanotify_init");
853 exit(EXIT_FAILURE);
854 }
855
856 /* Mark the mount for:
857 \- permission events before opening files
858 \- notification events after closing a write\-enabled
859 file descriptor */
860
861 if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
862 FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
863 argv[1]) == \-1) {
864 perror("fanotify_mark");
865 exit(EXIT_FAILURE);
866 }
867
868 /* Prepare for polling */
869
870 nfds = 2;
871
872 /* Console input */
873
874 fds[0].fd = STDIN_FILENO;
875 fds[0].events = POLLIN;
876
877 /* Fanotify input */
878
879 fds[1].fd = fd;
880 fds[1].events = POLLIN;
881
882 /* This is the loop to wait for incoming events */
883
884 printf("Listening for events.\en");
885
886 while (1) {
887 poll_num = poll(fds, nfds, \-1);
888 if (poll_num == \-1) {
889 if (errno == EINTR) /* Interrupted by a signal */
890 continue; /* Restart poll() */
891
892 perror("poll"); /* Unexpected error */
893 exit(EXIT_FAILURE);
894 }
895
896 if (poll_num > 0) {
897 if (fds[0].revents & POLLIN) {
898
899 /* Console input is available: empty stdin and quit */
900
901 while (read(STDIN_FILENO, &buf, 1) > 0 && buf != \(aq\en\(aq)
902 continue;
903 break;
904 }
905
906 if (fds[1].revents & POLLIN) {
907
908 /* Fanotify events are available */
909
910 handle_events(fd);
911 }
912 }
913 }
914
915 printf("Listening for events stopped.\en");
916 exit(EXIT_SUCCESS);
917}
918.EE
919.\"
920.SS Example program: fanotify_fid.c
921The second program is an example of fanotify being used with
922.B FAN_REPORT_FID
923enabled.
924The program marks the filesystem object that is passed as
925a command-line argument
926and waits until an event of type
927.B FAN_CREATE
928has occurred.
929The event mask indicates which type of filesystem object\(emeither
930a file or a directory\(emwas created".
931Once all events have been read from the buffer and processed accordingly,
932the program simply terminates.
933.PP
934The following shell sessions show two different invocations of
935this program, with different actions performed on a watched object.
936.PP
937The first session shows a mark being placed on
938.IR /home/user .
939This is followed by the creation of a regular file,
940.IR /home/user/testfile.txt .
941This results in a
942.B FAN_CREATE
943event being created and reported against the file's parent watched
944directory object.
945Program execution ends once all events captured within the buffer have
946been processed.
947Program execution ends once all events captured within the buffer are
948processed.
949.PP
950.in +4n
951.EX
952# \fB./fanotify_fid /home/user\fP
953Listening for events.
954FAN_CREATE (file created): Directory /home/user has been modified.
955All events processed successfully. Program exiting.
956
957$ \fBtouch /home/user/testing\fP # In another terminal
958.EE
959.in
960.PP
961The second session shows a mark being placed on
962.IR /home/user .
963This is followed by the creation of a directory,
964.IR /home/user/testdir .
965This specific action results in the program producing a
966.B FAN_CREATE
967and
968.B FAN_ONDIR
969event.
970.PP
971.in +4n
972.EX
973# \fB./fanotify_fid /home/user\fP
974Listening for events.
975FAN_CREATE | FAN_ONDIR (subdirectory created):
976 Directory /home/user has been modified.
977All events processed successfully. Program exiting.
978
979$ \fBmkdir \-p /home/user/testing\fP # In another terminal
980.EE
981.in
982.SS Program source: fanotify_fid.c
983\&
984.EX
985#define _GNU_SOURCE
986#include <errno.h>
987#include <fcntl.h>
988#include <limits.h>
989#include <stdio.h>
990#include <stdlib.h>
991#include <sys/types.h>
992#include <sys/stat.h>
993#include <sys/fanotify.h>
994#include <unistd.h>
995
996#define BUF_SIZE 256
997
998int
999main(int argc, char **argv)
1000{
1001 int fd, ret, event_fd;
1002 ssize_t len, path_len;
1003 char path[PATH_MAX];
1004 char procfd_path[PATH_MAX];
1005 char events_buf[BUF_SIZE];
1006 struct file_handle *file_handle;
1007 struct fanotify_event_metadata *metadata;
1008 struct fanotify_event_info_fid *fid;
1009
1010 if (argc != 2) {
1011 fprintf(stderr, "Invalid number of command line arguments.\e\n");
1012 exit(EXIT_FAILURE);
1013 }
1014
1015 /* Create an fanotify file descriptor with FAN_REPORT_FID as a flag
1016 so that program can receive fid events. */
1017
1018 fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, 0);
1019 if (fd == \-1) {
1020 perror("fanotify_init");
1021 exit(EXIT_FAILURE);
1022 }
1023
1024 /* Place a mark on the filesystem object supplied in argv[1]. */
1025
1026 ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR,
1027 FAN_CREATE | FAN_ONDIR,
1028 AT_FDCWD, argv[1]);
1029 if (ret == \-1) {
1030 perror("fanotify_mark");
1031 exit(EXIT_FAILURE);
1032 }
1033
1034 printf("Listening for events.\e\n");
1035
1036 /* Read events from the event queue into a buffer */
1037
1038 len = read(fd, (void *) &events_buf, sizeof(events_buf));
1039 if (len == \-1 && errno != EAGAIN) {
1040 perror("read");
1041 exit(EXIT_FAILURE);
1042 }
1043
1044 /* Process all events within the buffer */
1045
1046 for (metadata = (struct fanotify_event_metadata *) events_buf;
1047 FAN_EVENT_OK(metadata, len);
1048 metadata = FAN_EVENT_NEXT(metadata, len)) {
1049 fid = (struct fanotify_event_info_fid *) (metadata + 1);
1050 file_handle = (struct file_handle *) fid->handle;
1051
1052 /* Ensure that the event info is of the correct type */
1053
1054 if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
1055 fprintf(stderr, "Received unexpected event info type.\e\n");
1056 exit(EXIT_FAILURE);
1057 }
1058
1059 if (metadata->mask == FAN_CREATE)
1060 printf("FAN_CREATE (file created):");
1061
1062 if (metadata->mask == FAN_CREATE | FAN_ONDIR)
1063 printf("FAN_CREATE | FAN_ONDIR (subdirectory created):");
1064
1065 /* metadata->fd is set to FAN_NOFD when FAN_REPORT_FID is enabled.
1066 To obtain a file descriptor for the file object corresponding to
1067 an event you can use the struct file_handle that\(aqs provided
1068 within the fanotify_event_info_fid in conjunction with the
1069 open_by_handle_at(2) system call. A check for ESTALE is done
1070 to accommodate for the situation where the file handle for the
1071 object was deleted prior to this system call. */
1072
1073 event_fd = open_by_handle_at(AT_FDCWD, file_handle, O_RDONLY);
1074 if (ret == \-1) {
1075 if (errno == ESTALE) {
1076 printf("File handle is no longer valid. "
1077 "File has been deleted\e\n");
1078 continue;
1079 } else {
1080 perror("open_by_handle_at");
1081 exit(EXIT_FAILURE);
1082 }
1083 }
1084
1085 snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
1086 event_fd);
1087
1088 /* Retrieve and print the path of the modified dentry */
1089
1090 path_len = readlink(procfd_path, path, sizeof(path) \- 1);
1091 if (path_len == \-1) {
1092 perror("readlink");
1093 exit(EXIT_FAILURE);
1094 }
1095
1096 path[path_len] = \(aq\e\0\(aq;
1097 printf("\etDirectory \(aq%s\(aq has been modified.\e\n", path);
1098
1099 /* Close associated file descriptor for this event */
1100
1101 close(event_fd);
1102 }
1103
1104 printf("All events processed successfully. Program exiting.\e\n");
1105 exit(EXIT_SUCCESS);
1106}
1107.EE
1108.SH SEE ALSO
1109.ad l
1110.BR fanotify_init (2),
1111.BR fanotify_mark (2),
1112.BR inotify (7)