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

ERRORS

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

VERSIONS

388       The fanotify API was introduced in version 2.6.36 of the  Linux  kernel
389       and  enabled  in  version  2.6.37.  Fdinfo support was added in version
390       3.8.
391

CONFORMING TO

393       The fanotify API is Linux-specific.
394

NOTES

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

BUGS

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

EXAMPLE

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

SEE ALSO

838       fanotify_init(2), fanotify_mark(2), inotify(7)
839

COLOPHON

841       This page is part of release 5.04 of the Linux man-pages project.  A
842       description of the project, information about reporting bugs, and the
843       latest version of this page, can be found at
844       https://www.kernel.org/doc/man-pages/.
845
846
847
848Linux                             2019-08-02                       FANOTIFY(7)
Impressum