[ACCEPTED]-How do I program for Linux's new `fanotify` file system monitoring feature?-fanotify

Accepted answer
Score: 19

This LWN article is often quoted as a source of documentation 26 for fanotify. But the description there 25 appears to be out of date. fanotify no longer 24 works using a socket connection. Instead, there 23 are two new libc functions wrapping syscalls, declared 22 in sys/fanotify.h. One is called fanotify_init, the other is fanotify_mark. At the 21 time of this writing, these syscalls are 20 still included in the list of missing manual pages. There is, however, a 19 mail containing drafts for these manual pages. With a combination 18 of these man pages, a look at the headers 17 in question, and a bit of trial and error, you 16 should be able to get this going.

It seems 15 that some of the functionality originally 14 envisioned for fanotify is no longer suipported 13 in that fashion. For example, the LWN article 12 describes a FAN_GLOBAL_LISTENER flag which will implicitely 11 mark the whole filesystem tree unless parts 10 are explicitely unmarked. The current interface 9 has no such provision, but a similar result 8 can be achieved using the following mark:

              FAN_MARK_ADD | FAN_MARK_MOUNT,
              FAN_OPEN | FAN_EVENT_ON_CHILD,
              AT_FDCWD, "/")

Where 7 inotify events provide the path to the accessed 6 object as part of the event, fanotify opens 5 a file descriptor for it. In order to turn 4 this descriptor into a path name, the corresponding 3 entry from the proc file system can be used, as 2 described here.

Here is a simple example which 1 simply prints the name of every opened file:

#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/fanotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#define CHK(expr, errcode) if((expr)==errcode) perror(#expr), exit(EXIT_FAILURE)
int main(int argc, char** argv) {
  int fan;
  char buf[4096];
  char fdpath[32];
  char path[PATH_MAX + 1];
  ssize_t buflen, linklen;
  struct fanotify_event_metadata *metadata;
  CHK(fan = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY), -1);
  CHK(fanotify_mark(fan, FAN_MARK_ADD | FAN_MARK_MOUNT,
                    FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, "/"), -1);
  for (;;) {
    CHK(buflen = read(fan, buf, sizeof(buf)), -1);
    metadata = (struct fanotify_event_metadata*)&buf;
    while(FAN_EVENT_OK(metadata, buflen)) {
      if (metadata->mask & FAN_Q_OVERFLOW) {
        printf("Queue overflow!\n");
      sprintf(fdpath, "/proc/self/fd/%d", metadata->fd);
      CHK(linklen = readlink(fdpath, path, sizeof(path) - 1), -1);
      path[linklen] = '\0';
      printf("%s opened by process %d.\n", path, (int)metadata->pid);
      metadata = FAN_EVENT_NEXT(metadata, buflen);
Score: 13

The documentation for the fanotify API is 3 available in the Linux manpages:

Here are 2 some examples, fatrace being the most elaborate.

Bindings 1 exist for Go and Python.

Score: 6

I just learned about fanotify and it seems 20 very nice. Very nice interface!

It is not 19 in the Linus tree yet but I guess it will 18 get there for Linux 2.6.33 and before for 17 testing (I noticed some patches today in 16 LKML). In the original patch they announce 15 a GIT tree thus you might be able to build 14 a testing kernel from there. You might also 13 find testing git trees.

I couldn't find utilities 12 that use it but I guess they'll come soon.

There 11 is an example here, at the end of the email:


If 10 you are really interested in this new feature 9 you might want to monitor the Linux Kernel 8 Mailing List and interact there. You can 7 also wait until the utilities are released 6 or develop your own.

About the detail, it 5 seems fanotify provides less events than 4 inotify. I guess this might change in the 3 future but since this is a brand new feature 2 in development there is not much I can say 1 about it now.

More Related questions