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
96              read(2), the read buffer contains one or more of  the  following
97              structures:
98
99           struct fanotify_event_metadata {
100               __u32 event_len;
101               __u8 vers;
102               __u8 reserved;
103               __u16 metadata_len;
104               __aligned_u64 mask;
105               __s32 fd;
106               __s32 pid;
107           };
108
109       In case of an fanotify group that identifies filesystem objects by file
110       handles, you should also expect to receive one or more  additional  in‐
111       formation records of the structure detailed below following the generic
112       fanotify_event_metadata structure within the read buffer:
113
114           struct fanotify_event_info_header {
115               __u8 info_type;
116               __u8 pad;
117               __u16 len;
118           };
119
120           struct fanotify_event_info_fid {
121               struct fanotify_event_info_header hdr;
122               __kernel_fsid_t fsid;
123               unsigned char file_handle[0];
124           };
125
126       For performance reasons, it is recommended to use a large  buffer  size
127       (for  example, 4096 bytes), so that multiple events can be retrieved by
128       a single read(2).
129
130       The return value of read(2) is the number of bytes placed in  the  buf‐
131       fer, or -1 in case of an error (but see BUGS).
132
133       The fields of the fanotify_event_metadata structure are as follows:
134
135       event_len
136              This  is  the  length  of the data for the current event and the
137              offset to the next event in the buffer.  Unless the group  iden‐
138              tifies   filesystem  objects  by  file  handles,  the  value  of
139              event_len is always FAN_EVENT_METADATA_LEN.  For  a  group  that
140              identifies  filesystem  objects  by file handles, event_len also
141              includes the variable length file identifier records.
142
143       vers   This field holds a version number for the structure.  It must be
144              compared  to FANOTIFY_METADATA_VERSION to verify that the struc‐
145              tures returned at run time match the structures defined at  com‐
146              pile  time.  In case of a mismatch, the application should aban‐
147              don trying to use the fanotify file descriptor.
148
149       reserved
150              This field is not used.
151
152       metadata_len
153              This is the length of the structure.  The field  was  introduced
154              to  facilitate  the implementation of optional headers per event
155              type.  No such optional headers exist in the current implementa‐
156              tion.
157
158       mask   This is a bit mask describing the event (see below).
159
160       fd     This  is  an open file descriptor for the object being accessed,
161              or FAN_NOFD if a queue  overflow  occurred.   With  an  fanotify
162              group that identifies filesystem objects by file handles, appli‐
163              cations should expect this value to be set to FAN_NOFD for  each
164              event  that is received.  The file descriptor can be used to ac‐
165              cess the contents of the monitored file or directory.  The read‐
166              ing application is responsible for closing this file descriptor.
167
168              When  calling  fanotify_init(2), the caller may specify (via the
169              event_f_flags argument) various file status flags that are to be
170              set  on  the open file description that corresponds to this file
171              descriptor.  In addition, the  (kernel-internal)  FMODE_NONOTIFY
172              file status flag is set on the open file description.  This flag
173              suppresses fanotify event generation.  Hence, when the  receiver
174              of  the  fanotify  event accesses the notified file or directory
175              using this file descriptor, no additional events  will  be  cre‐
176              ated.
177
178       pid    If  flag FAN_REPORT_TID was set in fanotify_init(2), this is the
179              TID of the thread that caused the event.   Otherwise,  this  the
180              PID of the process that caused the event.
181
182       A  program listening to fanotify events can compare this PID to the PID
183       returned by getpid(2), to determine whether the event is caused by  the
184       listener itself, or is due to a file access by another process.
185
186       The  bit mask in mask indicates which events have occurred for a single
187       filesystem object.  Multiple bits may be set in this mask, if more than
188       one event occurred for the monitored filesystem object.  In particular,
189       consecutive events for the same filesystem object and originating  from
190       the  same process may be merged into a single event, with the exception
191       that two permission events are never merged into one queue entry.
192
193       The bits that may appear in mask are as follows:
194
195       FAN_ACCESS
196              A file or a directory (but see BUGS) was accessed (read).
197
198       FAN_OPEN
199              A file or a directory was opened.
200
201       FAN_OPEN_EXEC
202              A file was opened with the intent to be executed.  See NOTES  in
203              fanotify_mark(2) for additional details.
204
205       FAN_ATTRIB
206              A file or directory metadata was changed.
207
208       FAN_CREATE
209              A child file or directory was created in a watched parent.
210
211       FAN_DELETE
212              A child file or directory was deleted in a watched parent.
213
214       FAN_DELETE_SELF
215              A watched file or directory was deleted.
216
217       FAN_MOVED_FROM
218              A  file or directory has been moved from a watched parent direc‐
219              tory.
220
221       FAN_MOVED_TO
222              A file or directory has been moved to a  watched  parent  direc‐
223              tory.
224
225       FAN_MOVE_SELF
226              A watched file or directory was moved.
227
228       FAN_MODIFY
229              A file was modified.
230
231       FAN_CLOSE_WRITE
232              A  file  that  was  opened  for writing (O_WRONLY or O_RDWR) was
233              closed.
234
235       FAN_CLOSE_NOWRITE
236              A file or directory that was  opened  read-only  (O_RDONLY)  was
237              closed.
238
239       FAN_Q_OVERFLOW
240              The event queue exceeded the limit of 16384 entries.  This limit
241              can be overridden by  specifying  the  FAN_UNLIMITED_QUEUE  flag
242              when calling fanotify_init(2).
243
244       FAN_ACCESS_PERM
245              An  application  wants  to read a file or directory, for example
246              using read(2) or readdir(2).  The reader must write  a  response
247              (as  described  below) that determines whether the permission to
248              access the filesystem object shall be granted.
249
250       FAN_OPEN_PERM
251              An application wants to open a file or  directory.   The  reader
252              must  write a response that determines whether the permission to
253              open the filesystem object shall be granted.
254
255       FAN_OPEN_EXEC_PERM
256              An application wants to open a file for execution.   The  reader
257              must  write a response that determines whether the permission to
258              open the filesystem object for execution shall be granted.   See
259              NOTES in fanotify_mark(2) for additional details.
260
261       To check for any close event, the following bit mask may be used:
262
263       FAN_CLOSE
264              A file was closed.  This is a synonym for:
265
266                  FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE
267
268       To check for any move event, the following bit mask may be used:
269
270       FAN_MOVE
271              A file or directory was moved.  This is a synonym for:
272
273                  FAN_MOVED_FROM | FAN_MOVED_TO
274
275       The  following  bits  may appear in mask only in conjunction with other
276       event type bits:
277
278       FAN_ONDIR
279              The events described in the mask have occurred  on  a  directory
280              object.   Reporting  events on directories requires setting this
281              flag in the mark mask.  See fanotify_mark(2) for additional  de‐
282              tails.   The FAN_ONDIR flag is reported in an event mask only if
283              the fanotify group identifies filesystem objects  by  file  han‐
284              dles.
285
286       The fields of the fanotify_event_info_fid structure are as follows:
287
288       hdr    This is a structure of type fanotify_event_info_header.  It is a
289              generic header that contains information used to describe an ad‐
290              ditional information record attached to the event.  For example,
291              when an  fanotify  file  descriptor  is  created  using  FAN_RE‐
292              PORT_FID, a single information record is expected to be attached
293              to    the    event    with    info_type    field    value     of
294              FAN_EVENT_INFO_TYPE_FID.   When  an  fanotify file descriptor is
295              created using the  combination  of  FAN_REPORT_FID  and  FAN_RE‐
296              PORT_DIR_FID,  there  may be two information records attached to
297              the   event:    one    with    info_type    field    value    of
298              FAN_EVENT_INFO_TYPE_DFID, identifying a parent directory object,
299              and one with info_type field value  of  FAN_EVENT_INFO_TYPE_FID,
300              identifying     a     non-directory     object.      The    fan‐
301              otify_event_info_header contains a len field.  The value of  len
302              is  the  size of the additional information record including the
303              fanotify_event_info_header itself.  The total size of all  addi‐
304              tional  information  records is not expected to be bigger than (
305              event_len - metadata_len ).
306
307       fsid   This is a unique identifier of the filesystem containing the ob‐
308              ject  associated  with  the  event.   It  is a structure of type
309              __kernel_fsid_t and contains the same value as f_fsid when call‐
310              ing statfs(2).
311
312       file_handle
313              This  is a variable length structure of type struct file_handle.
314              It is an opaque handle that corresponds to a specified object on
315              a  filesystem  as  returned  by name_to_handle_at(2).  It can be
316              used to uniquely identify a file on  a  filesystem  and  can  be
317              passed  as  an  argument to open_by_handle_at(2).  Note that for
318              the directory entry modification events FAN_CREATE,  FAN_DELETE,
319              and  FAN_MOVE, the file_handle identifies the modified directory
320              and not the created/deleted/moved child object.  If the value of
321              info_type  field is FAN_EVENT_INFO_TYPE_DFID_NAME, the file han‐
322              dle is followed by a null terminated string that identifies  the
323              created/deleted/moved  directory  entry  name.  For other events
324              such   as    FAN_OPEN,    FAN_ATTRIB,    FAN_DELETE_SELF,    and
325              FAN_MOVE_SELF,    if   the   value   of   info_type   field   is
326              FAN_EVENT_INFO_TYPE_FID, the file_handle identifies  the  object
327              correlated  to  the  event.   If the value of info_type field is
328              FAN_EVENT_INFO_TYPE_DFID, the file_handle identifies the  direc‐
329              tory object correlated to the event or the parent directory of a
330              non-directory object correlated to the event.  If the  value  of
331              info_type  field is FAN_EVENT_INFO_TYPE_DFID_NAME, the file_han‐
332              dle identifies the same directory object that would be  reported
333              with FAN_EVENT_INFO_TYPE_DFID and the file handle is followed by
334              a null terminated string that identifies the name of a directory
335              entry in that directory, or '.' to identify the directory object
336              itself.
337
338       The following macros are provided to iterate over a  buffer  containing
339       fanotify event metadata returned by a read(2) from an fanotify file de‐
340       scriptor:
341
342       FAN_EVENT_OK(meta, len)
343              This macro checks the remaining length len of  the  buffer  meta
344              against  the  length of the metadata structure and the event_len
345              field of the first metadata structure in the buffer.
346
347       FAN_EVENT_NEXT(meta, len)
348              This macro uses the length indicated in the event_len  field  of
349              the  metadata  structure pointed to by meta to calculate the ad‐
350              dress of the next metadata structure that follows meta.  len  is
351              the  number  of  bytes  of metadata that currently remain in the
352              buffer.  The macro returns a pointer to the next metadata struc‐
353              ture  that  follows meta, and reduces len by the number of bytes
354              in the metadata structure that has been skipped over  (i.e.,  it
355              subtracts meta->event_len from len).
356
357       In addition, there is:
358
359       FAN_EVENT_METADATA_LEN
360              This  macro  returns  the  size (in bytes) of the structure fan‐
361              otify_event_metadata.  This is the minimum size  (and  currently
362              the only size) of any event metadata.
363
364   Monitoring an fanotify file descriptor for events
365       When  an  fanotify event occurs, the fanotify file descriptor indicates
366       as readable when passed to epoll(7), poll(2), or select(2).
367
368   Dealing with permission events
369       For permission events, the application must write(2) a structure of the
370       following form to the fanotify file descriptor:
371
372           struct fanotify_response {
373               __s32 fd;
374               __u32 response;
375           };
376
377       The fields of this structure are as follows:
378
379       fd     This   is   the   file   descriptor   from  the  structure  fan‐
380              otify_event_metadata.
381
382       response
383              This field indicates whether or not  the  permission  is  to  be
384              granted.   Its  value must be either FAN_ALLOW to allow the file
385              operation or FAN_DENY to deny the file operation.
386
387       If access is denied, the requesting application call  will  receive  an
388       EPERM error.
389
390   Closing the fanotify file descriptor
391       When  all file descriptors referring to the fanotify notification group
392       are closed, the fanotify group is released and its resources are  freed
393       for  reuse by the kernel.  Upon close(2), outstanding permission events
394       will be set to allowed.
395
396   /proc/[pid]/fdinfo
397       The file /proc/[pid]/fdinfo/[fd] contains  information  about  fanotify
398       marks for file descriptor fd of process pid.  See proc(5) for details.
399

ERRORS

401       In  addition  to the usual errors for read(2), the following errors can
402       occur when reading from the fanotify file descriptor:
403
404       EINVAL The buffer is too small to hold the event.
405
406       EMFILE The per-process limit on the  number  of  open  files  has  been
407              reached.  See the description of RLIMIT_NOFILE in getrlimit(2).
408
409       ENFILE The system-wide limit on the total number of open files has been
410              reached.  See /proc/sys/fs/file-max in proc(5).
411
412       ETXTBSY
413              This error is returned by read(2)  if  O_RDWR  or  O_WRONLY  was
414              specified  in  the  event_f_flags  argument  when  calling  fan‐
415              otify_init(2) and an event occurred for a monitored file that is
416              currently being executed.
417
418       In  addition to the usual errors for write(2), the following errors can
419       occur when writing to the fanotify file descriptor:
420
421       EINVAL Fanotify access permissions are not enabled in the  kernel  con‐
422              figuration or the value of response in the response structure is
423              not valid.
424
425       ENOENT The file descriptor fd in the response structure is  not  valid.
426              This  may occur when a response for the permission event has al‐
427              ready been written.
428

VERSIONS

430       The fanotify API was introduced in version 2.6.36 of the  Linux  kernel
431       and  enabled  in  version  2.6.37.  Fdinfo support was added in version
432       3.8.
433

CONFORMING TO

435       The fanotify API is Linux-specific.
436

NOTES

438       The fanotify API is available only if the kernel  was  built  with  the
439       CONFIG_FANOTIFY  configuration  option  enabled.  In addition, fanotify
440       permission  handling  is  available  only  if  the  CONFIG_FANOTIFY_AC‐
441       CESS_PERMISSIONS configuration option is enabled.
442
443   Limitations and caveats
444       Fanotify reports only events that a user-space program triggers through
445       the filesystem API.  As a result, it does not catch remote events  that
446       occur on network filesystems.
447
448       The  fanotify  API does not report file accesses and modifications that
449       may occur because of mmap(2), msync(2), and munmap(2).
450
451       Events for directories are created only  if  the  directory  itself  is
452       opened,  read, and closed.  Adding, removing, or changing children of a
453       marked directory does not create events for the monitored directory it‐
454       self.
455
456       Fanotify  monitoring of directories is not recursive: to monitor subdi‐
457       rectories under a directory, additional marks  must  be  created.   The
458       FAN_CREATE event can be used for detecting when a subdirectory has been
459       created under a marked directory.  An additional mark must then be  set
460       on  the  newly created subdirectory.  This approach is racy, because it
461       can lose events that occurred inside the  newly  created  subdirectory,
462       before  a mark is added on that subdirectory.  Monitoring mounts offers
463       the capability to monitor a whole directory tree in a race-free manner.
464       Monitoring  filesystems  offers  the capability to monitor changes made
465       from any mount of a filesystem instance in a race-free manner.
466
467       The event queue can overflow.  In this case, events are lost.
468

BUGS

470       Before Linux 3.19,  fallocate(2)  did  not  generate  fanotify  events.
471       Since Linux 3.19, calls to fallocate(2) generate FAN_MODIFY events.
472
473       As of Linux 3.17, the following bugs exist:
474
475       *  On  Linux,  a  filesystem  object may be accessible through multiple
476          paths, for example, a part of a filesystem may  be  remounted  using
477          the  --bind option of mount(8).  A listener that marked a mount will
478          be notified only of events that were triggered for a filesystem  ob‐
479          ject using the same mount.  Any other event will pass unnoticed.
480
481       *  When an event is generated, no check is made to see whether the user
482          ID of the receiving process has authorization to read or  write  the
483          file  before  passing a file descriptor for that file.  This poses a
484          security risk, when the CAP_SYS_ADMIN capability is set for programs
485          executed by unprivileged users.
486
487       *  If  a  call  to  read(2) processes multiple events from the fanotify
488          queue and an error occurs, the return value will be the total length
489          of  the  events  successfully copied to the user-space buffer before
490          the error occurred.  The return value will not be -1, and errno will
491          not  be set.  Thus, the reading application has no way to detect the
492          error.
493

EXAMPLES

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

SEE ALSO

916       fanotify_init(2), fanotify_mark(2), inotify(7)
917

COLOPHON

919       This page is part of release 5.10 of the Linux man-pages project.  A
920       description of the project, information about reporting bugs, and the
921       latest version of this page, can be found at
922       https://www.kernel.org/doc/man-pages/.
923
924
925
926Linux                             2020-11-01                       FANOTIFY(7)
Impressum