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.   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  following  bits  may appear in mask only in conjunction with other
265       event type bits:
266
267       FAN_ONDIR
268              The events described in the mask have occurred  on  a  directory
269              object.   Reporting  events on directories requires setting this
270              flag in the mark  mask.   See  fanotify_mark(2)  for  additional
271              details.   The  FAN_ONDIR flag is reported in an event mask only
272              if the  fanotify  group  has  been  initialized  with  the  flag
273              FAN_REPORT_FID.
274
275       The fields of the fanotify_event_info_fid structure are as follows:
276
277       hdr    This is a structure of type fanotify_event_info_header.  It is a
278              generic header that contains information used to describe  addi‐
279              tional  information attached to the event.  For example, when an
280              fanotify file descriptor is created  using  FAN_REPORT_FID,  the
281              info_type     field     of     this    header    is    set    to
282              FAN_EVENT_INFO_TYPE_FID.  Event listeners can use this field  to
283              check  that  the additional information received for an event is
284              of    the    correct    type.     Additionally,     the     fan‐
285              otify_event_info_header  also contains a len field.  In the cur‐
286              rent implementation, the value of len  is  always  (event_len  -
287              FAN_EVENT_METADATA_LEN).
288
289       fsid   This  is  a  unique  identifier of the filesystem containing the
290              object associated with the event.  It is  a  structure  of  type
291              __kernel_fsid_t and contains the same value as f_fsid when call‐
292              ing statfs(2).
293
294       file_handle
295              This is a variable length structure of type file_handle.  It  is
296              an  opaque  handle  that  corresponds to a specified object on a
297              filesystem as returned by name_to_handle_at(2).  It can be  used
298              to uniquely identify a file on a filesystem and can be passed as
299              an argument to open_by_handle_at(2).  Note  that  for  directory
300              entry  events, such as FAN_CREATE, FAN_DELETE, and FAN_MOVE, the
301              file_handle describes the modified directory and  not  the  cre‐
302              ated/deleted/moved   child   object.    The  events  FAN_ATTRIB,
303              FAN_DELETE_SELF, and FAN_MOVE_SELF will  carry  the  file_handle
304              information  for  the  child object if the child object is being
305              watched.
306
307       The following macros are provided to iterate over a  buffer  containing
308       fanotify  event  metadata  returned  by a read(2) from an fanotify file
309       descriptor:
310
311       FAN_EVENT_OK(meta, len)
312              This macro checks the remaining length len of  the  buffer  meta
313              against  the  length of the metadata structure and the event_len
314              field of the first metadata structure in the buffer.
315
316       FAN_EVENT_NEXT(meta, len)
317              This macro uses the length indicated in the event_len  field  of
318              the  metadata  structure  pointed  to  by  meta to calculate the
319              address of the next metadata structure that follows  meta.   len
320              is  the number of bytes of metadata that currently remain in the
321              buffer.  The macro returns a pointer to the next metadata struc‐
322              ture  that  follows meta, and reduces len by the number of bytes
323              in the metadata structure that has been skipped over  (i.e.,  it
324              subtracts meta->event_len from len).
325
326       In addition, there is:
327
328       FAN_EVENT_METADATA_LEN
329              This  macro  returns  the  size (in bytes) of the structure fan‐
330              otify_event_metadata.  This is the minimum size  (and  currently
331              the only size) of any event metadata.
332
333   Monitoring an fanotify file descriptor for events
334       When  an  fanotify event occurs, the fanotify file descriptor indicates
335       as readable when passed to epoll(7), poll(2), or select(2).
336
337   Dealing with permission events
338       For permission events, the application must write(2) a structure of the
339       following form to the fanotify file descriptor:
340
341           struct fanotify_response {
342               __s32 fd;
343               __u32 response;
344           };
345
346       The fields of this structure are as follows:
347
348       fd     This   is   the   file   descriptor   from  the  structure  fan‐
349              otify_event_metadata.
350
351       response
352              This field indicates whether or not  the  permission  is  to  be
353              granted.   Its  value must be either FAN_ALLOW to allow the file
354              operation or FAN_DENY to deny the file operation.
355
356       If access is denied, the requesting application call  will  receive  an
357       EPERM error.
358
359   Closing the fanotify file descriptor
360       When  all file descriptors referring to the fanotify notification group
361       are closed, the fanotify group is released and its resources are  freed
362       for  reuse by the kernel.  Upon close(2), outstanding permission events
363       will be set to allowed.
364
365   /proc/[pid]/fdinfo
366       The file /proc/[pid]/fdinfo/[fd] contains  information  about  fanotify
367       marks for file descriptor fd of process pid.  See proc(5) for details.
368

ERRORS

370       In  addition  to the usual errors for read(2), the following errors can
371       occur when reading from the fanotify file descriptor:
372
373       EINVAL The buffer is too small to hold the event.
374
375       EMFILE The per-process limit on the  number  of  open  files  has  been
376              reached.  See the description of RLIMIT_NOFILE in getrlimit(2).
377
378       ENFILE The system-wide limit on the total number of open files has been
379              reached.  See /proc/sys/fs/file-max in proc(5).
380
381       ETXTBSY
382              This error is returned by read(2)  if  O_RDWR  or  O_WRONLY  was
383              specified  in  the  event_f_flags  argument  when  calling  fan‐
384              otify_init(2) and an event occurred for a monitored file that is
385              currently being executed.
386
387       In  addition to the usual errors for write(2), the following errors can
388       occur when writing to the fanotify file descriptor:
389
390       EINVAL Fanotify access permissions are not enabled in the  kernel  con‐
391              figuration or the value of response in the response structure is
392              not valid.
393
394       ENOENT The file descriptor fd in the response structure is  not  valid.
395              This  may  occur  when  a  response for the permission event has
396              already been written.
397

VERSIONS

399       The fanotify API was introduced in version 2.6.36 of the  Linux  kernel
400       and  enabled  in  version  2.6.37.  Fdinfo support was added in version
401       3.8.
402

CONFORMING TO

404       The fanotify API is Linux-specific.
405

NOTES

407       The fanotify API is available only if the kernel  was  built  with  the
408       CONFIG_FANOTIFY  configuration  option  enabled.  In addition, fanotify
409       permission   handling   is   available   only   if   the    CONFIG_FAN‐
410       OTIFY_ACCESS_PERMISSIONS configuration option is enabled.
411
412   Limitations and caveats
413       Fanotify reports only events that a user-space program triggers through
414       the filesystem API.  As a result, it does not catch remote events  that
415       occur on network filesystems.
416
417       The  fanotify  API does not report file accesses and modifications that
418       may occur because of mmap(2), msync(2), and munmap(2).
419
420       Events for directories are created only  if  the  directory  itself  is
421       opened,  read, and closed.  Adding, removing, or changing children of a
422       marked directory does not create events  for  the  monitored  directory
423       itself.
424
425       Fanotify  monitoring of directories is not recursive: to monitor subdi‐
426       rectories under a directory, additional marks must  be  created.   (But
427       note  that  the fanotify API provides no way of detecting when a subdi‐
428       rectory has been created under a marked directory, which  makes  recur‐
429       sive monitoring difficult.)  Monitoring mounts offers the capability to
430       monitor a whole directory  tree.   Monitoring  filesystems  offers  the
431       capability  to  monitor  changes  made  from  any mount of a filesystem
432       instance.
433
434       The event queue can overflow.  In this case, events are lost.
435

BUGS

437       Before Linux 3.19,  fallocate(2)  did  not  generate  fanotify  events.
438       Since Linux 3.19, calls to fallocate(2) generate FAN_MODIFY events.
439
440       As of Linux 3.17, the following bugs exist:
441
442       *  On  Linux,  a  filesystem  object may be accessible through multiple
443          paths, for example, a part of a filesystem may  be  remounted  using
444          the  --bind option of mount(8).  A listener that marked a mount will
445          be notified only of events that  were  triggered  for  a  filesystem
446          object using the same mount.  Any other event will pass unnoticed.
447
448       *  When an event is generated, no check is made to see whether the user
449          ID of the receiving process has authorization to read or  write  the
450          file  before  passing a file descriptor for that file.  This poses a
451          security risk, when the CAP_SYS_ADMIN capability is set for programs
452          executed by unprivileged users.
453
454       *  If  a  call  to  read(2) processes multiple events from the fanotify
455          queue and an error occurs, the return value will be the total length
456          of  the  events  successfully copied to the user-space buffer before
457          the error occurred.  The return value will not be -1, and errno will
458          not  be set.  Thus, the reading application has no way to detect the
459          error.
460

EXAMPLES

462       The two example programs below demonstrate the usage  of  the  fanotify
463       API.
464
465   Example program: fanotify_example.c
466       The  first  program is an example of fanotify being used with its event
467       object information passed in the form of a file descriptor.   The  pro‐
468       gram  marks the mount point passed as a command-line argument and waits
469       for events of type FAN_OPEN_PERM and FAN_CLOSE_WRITE.  When  a  permis‐
470       sion event occurs, a FAN_ALLOW response is given.
471
472       The  following  shell session shows an example of running this program.
473       This session involved editing the file  /home/user/temp/notes.   Before
474       the  file  was  opened, a FAN_OPEN_PERM event occurred.  After the file
475       was closed, a FAN_CLOSE_WRITE event occurred.  Execution of the program
476       ends when the user presses the ENTER key.
477
478           # ./fanotify_example /home
479           Press enter key to terminate.
480           Listening for events.
481           FAN_OPEN_PERM: File /home/user/temp/notes
482           FAN_CLOSE_WRITE: File /home/user/temp/notes
483
484           Listening for events stopped.
485
486   Program source: fanotify_example.c
487
488       #define _GNU_SOURCE     /* Needed to get O_LARGEFILE definition */
489       #include <errno.h>
490       #include <fcntl.h>
491       #include <limits.h>
492       #include <poll.h>
493       #include <stdio.h>
494       #include <stdlib.h>
495       #include <sys/fanotify.h>
496       #include <unistd.h>
497
498       /* Read all available fanotify events from the file descriptor 'fd' */
499
500       static void
501       handle_events(int fd)
502       {
503           const struct fanotify_event_metadata *metadata;
504           struct fanotify_event_metadata buf[200];
505           ssize_t len;
506           char path[PATH_MAX];
507           ssize_t path_len;
508           char procfd_path[PATH_MAX];
509           struct fanotify_response response;
510
511           /* Loop while events can be read from fanotify file descriptor */
512
513           for (;;) {
514
515               /* Read some events */
516
517               len = read(fd, (void *) &buf, sizeof(buf));
518               if (len == -1 && errno != EAGAIN) {
519                   perror("read");
520                   exit(EXIT_FAILURE);
521               }
522
523               /* Check if end of available data reached */
524
525               if (len <= 0)
526                   break;
527
528               /* Point to the first event in the buffer */
529
530               metadata = buf;
531
532               /* Loop over all events in the buffer */
533
534               while (FAN_EVENT_OK(metadata, len)) {
535
536                   /* Check that run-time and compile-time structures match */
537
538                   if (metadata->vers != FANOTIFY_METADATA_VERSION) {
539                       fprintf(stderr,
540                               "Mismatch of fanotify metadata version.\n");
541                       exit(EXIT_FAILURE);
542                   }
543
544                   /* metadata->fd contains either FAN_NOFD, indicating a
545                      queue overflow, or a file descriptor (a nonnegative
546                      integer). Here, we simply ignore queue overflow. */
547
548                   if (metadata->fd >= 0) {
549
550                       /* Handle open permission event */
551
552                       if (metadata->mask & FAN_OPEN_PERM) {
553                           printf("FAN_OPEN_PERM: ");
554
555                           /* Allow file to be opened */
556
557                           response.fd = metadata->fd;
558                           response.response = FAN_ALLOW;
559                           write(fd, &response,
560                                 sizeof(struct fanotify_response));
561                       }
562
563                       /* Handle closing of writable file event */
564
565                       if (metadata->mask & FAN_CLOSE_WRITE)
566                           printf("FAN_CLOSE_WRITE: ");
567
568                       /* Retrieve and print pathname of the accessed file */
569
570                       snprintf(procfd_path, sizeof(procfd_path),
571                                "/proc/self/fd/%d", metadata->fd);
572                       path_len = readlink(procfd_path, path,
573                                           sizeof(path) - 1);
574                       if (path_len == -1) {
575                           perror("readlink");
576                           exit(EXIT_FAILURE);
577                       }
578
579                       path[path_len] = '\0';
580                       printf("File %s\n", path);
581
582                       /* Close the file descriptor of the event */
583
584                       close(metadata->fd);
585                   }
586
587                   /* Advance to next event */
588
589                   metadata = FAN_EVENT_NEXT(metadata, len);
590               }
591           }
592       }
593
594       int
595       main(int argc, char *argv[])
596       {
597           char buf;
598           int fd, poll_num;
599           nfds_t nfds;
600           struct pollfd fds[2];
601
602           /* Check mount point is supplied */
603
604           if (argc != 2) {
605               fprintf(stderr, "Usage: %s MOUNT\n", argv[0]);
606               exit(EXIT_FAILURE);
607           }
608
609           printf("Press enter key to terminate.\n");
610
611           /* Create the file descriptor for accessing the fanotify API */
612
613           fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
614                              O_RDONLY | O_LARGEFILE);
615           if (fd == -1) {
616               perror("fanotify_init");
617               exit(EXIT_FAILURE);
618           }
619
620           /* Mark the mount for:
621              - permission events before opening files
622              - notification events after closing a write-enabled
623                file descriptor */
624
625           if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
626                             FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
627                             argv[1]) == -1) {
628               perror("fanotify_mark");
629               exit(EXIT_FAILURE);
630           }
631
632           /* Prepare for polling */
633
634           nfds = 2;
635
636           /* Console input */
637
638           fds[0].fd = STDIN_FILENO;
639           fds[0].events = POLLIN;
640
641           /* Fanotify input */
642
643           fds[1].fd = fd;
644           fds[1].events = POLLIN;
645
646           /* This is the loop to wait for incoming events */
647
648           printf("Listening for events.\n");
649
650           while (1) {
651               poll_num = poll(fds, nfds, -1);
652               if (poll_num == -1) {
653                   if (errno == EINTR)     /* Interrupted by a signal */
654                       continue;           /* Restart poll() */
655
656                   perror("poll");         /* Unexpected error */
657                   exit(EXIT_FAILURE);
658               }
659
660               if (poll_num > 0) {
661                   if (fds[0].revents & POLLIN) {
662
663                       /* Console input is available: empty stdin and quit */
664
665                       while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
666                           continue;
667                       break;
668                   }
669
670                   if (fds[1].revents & POLLIN) {
671
672                       /* Fanotify events are available */
673
674                       handle_events(fd);
675                   }
676               }
677           }
678
679           printf("Listening for events stopped.\n");
680           exit(EXIT_SUCCESS);
681       }
682
683   Example program: fanotify_fid.c
684       The   second  program  is  an  example  of  fanotify  being  used  with
685       FAN_REPORT_FID enabled.  The program marks the filesystem  object  that
686       is  passed  as a command-line argument and waits until an event of type
687       FAN_CREATE has occurred.   The  event  mask  indicates  which  type  of
688       filesystem  object—either  a file or a directory—was created.  Once all
689       events have been read from the buffer and  processed  accordingly,  the
690       program simply terminates.
691
692       The  following  shell  sessions  show two different invocations of this
693       program, with different actions performed on a watched object.
694
695       The first session shows a mark being placed  on  /home/user.   This  is
696       followed  by  the  creation of a regular file, /home/user/testfile.txt.
697       This results in a FAN_CREATE event being generated and reported against
698       the  file's  parent  watched  directory object.  Program execution ends
699       once all events captured within the buffer have been processed.
700
701           # ./fanotify_fid /home/user
702           Listening for events.
703           FAN_CREATE (file created):
704                   Directory /home/user has been modified.
705           All events processed successfully. Program exiting.
706
707           $ touch /home/user/testfile.txt              # In another terminal
708
709       The second session shows a mark being placed on  /home/user.   This  is
710       followed by the creation of a directory, /home/user/testdir.  This spe‐
711       cific action results in a  FAN_CREATE  event  being  generated  and  is
712       reported with the FAN_ONDIR flag set.
713
714           # ./fanotify_fid /home/user
715           Listening for events.
716           FAN_CREATE | FAN_ONDIR (subdirectory created):
717                   Directory /home/user has been modified.
718           All events processed successfully. Program exiting.
719
720           $ mkdir -p /home/user/testdir          # In another terminal
721
722   Program source: fanotify_fid.c
723
724       #define _GNU_SOURCE
725       #include <errno.h>
726       #include <fcntl.h>
727       #include <limits.h>
728       #include <stdio.h>
729       #include <stdlib.h>
730       #include <sys/types.h>
731       #include <sys/stat.h>
732       #include <sys/fanotify.h>
733       #include <unistd.h>
734
735       #define BUF_SIZE 256
736
737       int
738       main(int argc, char **argv)
739       {
740           int fd, ret, event_fd, mount_fd;
741           ssize_t len, path_len;
742           char path[PATH_MAX];
743           char procfd_path[PATH_MAX];
744           char events_buf[BUF_SIZE];
745           struct file_handle *file_handle;
746           struct fanotify_event_metadata *metadata;
747           struct fanotify_event_info_fid *fid;
748
749           if (argc != 2) {
750               fprintf(stderr, "Invalid number of command line arguments.\n");
751               exit(EXIT_FAILURE);
752           }
753
754           mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
755           if (mount_fd == -1) {
756               perror(argv[1]);
757               exit(EXIT_FAILURE);
758           }
759
760
761           /* Create an fanotify file descriptor with FAN_REPORT_FID as a flag
762              so that program can receive fid events. */
763
764           fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, 0);
765           if (fd == -1) {
766               perror("fanotify_init");
767               exit(EXIT_FAILURE);
768           }
769
770           /* Place a mark on the filesystem object supplied in argv[1]. */
771
772           ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR,
773                               FAN_CREATE | FAN_ONDIR,
774                               AT_FDCWD, argv[1]);
775           if (ret == -1) {
776               perror("fanotify_mark");
777               exit(EXIT_FAILURE);
778           }
779
780           printf("Listening for events.\n");
781
782           /* Read events from the event queue into a buffer */
783
784           len = read(fd, (void *) &events_buf, sizeof(events_buf));
785           if (len == -1 && errno != EAGAIN) {
786               perror("read");
787               exit(EXIT_FAILURE);
788           }
789
790           /* Process all events within the buffer */
791
792           for (metadata = (struct fanotify_event_metadata *) events_buf;
793                   FAN_EVENT_OK(metadata, len);
794                   metadata = FAN_EVENT_NEXT(metadata, len)) {
795               fid = (struct fanotify_event_info_fid *) (metadata + 1);
796               file_handle = (struct file_handle *) fid->handle;
797
798               /* Ensure that the event info is of the correct type */
799
800               if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
801                   fprintf(stderr, "Received unexpected event info type.\n");
802                   exit(EXIT_FAILURE);
803               }
804
805               if (metadata->mask == FAN_CREATE)
806                   printf("FAN_CREATE (file created):\n");
807
808               if (metadata->mask == (FAN_CREATE | FAN_ONDIR))
809                   printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\n");
810
811               /* metadata->fd is set to FAN_NOFD when FAN_REPORT_FID is
812                  enabled.  To obtain a file descriptor for the file object
813                  corresponding to an event you can use the struct file_handle
814                  that's provided within the fanotify_event_info_fid in
815                  conjunction with the open_by_handle_at(2) system call.
816                  A check for ESTALE is done to accommodate for the situation
817                  where the file handle for the object was deleted prior to
818                  this system call. */
819
820               event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
821               if (event_fd == -1) {
822                   if (errno == ESTALE) {
823                       printf("File handle is no longer valid. "
824                               "File has been deleted\n");
825                       continue;
826                   } else {
827                       perror("open_by_handle_at");
828                       exit(EXIT_FAILURE);
829                   }
830               }
831
832               snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
833                       event_fd);
834
835               /* Retrieve and print the path of the modified dentry */
836
837               path_len = readlink(procfd_path, path, sizeof(path) - 1);
838               if (path_len == -1) {
839                   perror("readlink");
840                   exit(EXIT_FAILURE);
841               }
842
843               path[path_len] = '\0';
844               printf("\tDirectory '%s' has been modified.\n", path);
845
846               /* Close associated file descriptor for this event */
847
848               close(event_fd);
849           }
850
851           printf("All events processed successfully. Program exiting.\n");
852           exit(EXIT_SUCCESS);
853       }
854

SEE ALSO

856       fanotify_init(2), fanotify_mark(2), inotify(7)
857

COLOPHON

859       This page is part of release 5.07 of the Linux man-pages project.  A
860       description of the project, information about reporting bugs, and the
861       latest version of this page, can be found at
862       https://www.kernel.org/doc/man-pages/.
863
864
865
866Linux                             2020-06-09                       FANOTIFY(7)
Impressum