Monitoring Directory/File events in Linux

Monitoring Directory/File events  is an essential  functionality for many types of programs. Applications can be implemented  to dynamically carry out various operations in response to Directory/ File events.

Linux kernel provides two separate interfaces for  monitoring Directory/ File events

Dnotify

D_NOTIFY is a facility to monitor a directory for changes. It will send the monitoring application a signal when files in the directory are added, removed, or modified. notification will trigger when a new subdirectory is added, but does not trigger when files in that subdirectory are modified. D_NOTIFY sends a signal as notification. By default it will send SIGIO, though this can be changed.

Program to monitor directory events for current working directory

#include <stdio.h>
#define __USE_GNU
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

volatile sig_atomic_t modified = 0;

static void handler(int signum, siginfo_t* si, void* data) {
  modified = 1;
}

#define MYSIG (SIGRTMIN+3)

int main(int argc, char** argv) {
  struct sigaction act;
  int fd;

  act.sa_sigaction = handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = SA_SIGINFO;
  sigaction(MYSIG, &act, NULL);

  fd = open(".", O_RDONLY);
  /* The default signal is SIGIO, but we use MYSIG instead */
  fcntl(fd, F_SETSIG, MYSIG);
  fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT);

  while (1) {
    pause();

    if (modified) {
      printf("Directory modified!n");
      modified = 0;
    }
  }
}

Inotify

Where dnotify sends signals, inotify uses a file descriptor suitable for adding to select() or poll(). inotify can be used for monitoring file events , read, write, move, delete. inotify was introduced as replacement to dnotify . It is recommended to use inotify over dnotify while writing new applications. inotify, was introduced with kernel 2.6.13, and is flexible and easy to use.

Program to monitor directory events for current working directory using Inotify

#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>

int main(int argc, char** argv) {
  int fd, watchdir, rlen;
  /* there is a variable length filename in the inotify_event, need to leave room for it. */
  char buf[sizeof(struct inotify_event) + 256];

  if ((fd = inotify_init()) < 0) {
    perror("inotify_init failed");
    exit(1);
  }

  if ((watchdir = inotify_add_watch (fd, ".",
                   IN_MODIFY | IN_CREATE | IN_DELETE)) < 0) {
    perror("inotify_add_watch failed");
    exit(2);
  }

  while ((rlen = read(fd, buf, sizeof(buf))) > 0) {
    struct inotify_event* event = (struct inotify_event*) buf;
    /* can examine event-> mask to determine what happened */
    printf("Directory modified!n");
  }
}

References

1. kernel Inotify doc

2. more Inotify examples

Tags: , ,

Leave a Reply