1FANOTIFY(7)                Linux Programmer's Manual               FANOTIFY(7)
2
3
4

NAME

6       fanotify - monitoring filesystem events
7

DESCRIPTION

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 mount points for which
31       events 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 point, or directory to  be  marked
38       for  receiving  events, while at the same time ignoring events for spe‐
39       cific objects under a mount point or directory.
40
41       The fanotify_mark(2) system call adds a file, directory, filesystem, or
42       mount point to a notification group and specifies which events shall be
43       reported (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 point is to  be  marked  to
48       receive these events.  After receiving the first event informing that a
49       file has been modified, the corresponding cache entry will  be  invali‐
50       dated.   No  further  modification events for this file are of interest
51       until the file is closed.  Hence, the modify event can be added to  the
52       ignore  mask.   Upon receiving the close event, the modify event can be
53       removed 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

ERRORS

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

VERSIONS

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

CONFORMING TO

437       The fanotify API is Linux-specific.
438

NOTES

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

BUGS

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

EXAMPLES

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 point passed as a command-line argument and  waits
504       for  events  of type FAN_OPEN_PERM and FAN_CLOSE_WRITE.  When a permis‐
505       sion 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

SEE ALSO

914       fanotify_init(2), fanotify_mark(2), inotify(7)
915

COLOPHON

917       This page is part of release 5.12 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-03-22                       FANOTIFY(7)
Impressum