Monitor directory recursively for file additions/modifications/deletions

3k views Asked by At

I need to watch a directory with several subdirectories, each of which has files which I need to monitor for file additions, modifications and deletions.

I found some example code, and had to modify it slightly to get it working, but it doesn't exactly do what I need. It can find a file rename, or delete within a directory (but not a subdirectory), but doesn't respond to file modifications.

The way that I can find using a Google search is to monitor each file individually; however, I have several hundreds of thousands of files to monitor, and holding a file descriptor to each is probably unwise.

Is there a way under FreeBSD to do what I need to do? Or will I have to find an alternative solution?

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h> 
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h> 

int main(void) {
   int f, kq, nev;
   struct kevent change;
   struct kevent event;

   kq = kqueue();
   if (kq == -1)
       perror("kqueue");

   f = open("/tmp/foo", O_RDONLY);
   if (f == -1)
       perror("open");

   EV_SET(&change, f, EVFILT_VNODE,
          EV_ADD | EV_ENABLE | EV_ONESHOT,
          NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB,
          0, 0);

   for (;;) {
       nev = kevent(kq, &change, 1, &event, 1, NULL);
       if (nev == -1)
           perror("kevent");
       else if (nev > 0) {
           if (event.fflags & NOTE_DELETE) {
               printf("File deleted\n");
               break;
           }
           if (event.fflags & NOTE_EXTEND ||
               event.fflags & NOTE_WRITE)
               printf("File modified\n");
           if (event.fflags & NOTE_ATTRIB)
               printf("File attributes modified\n");
       }
   }

   close(kq);
   close(f);
   return EXIT_SUCCESS;
}
1

There are 1 answers

6
vijucat On BEST ANSWER

As you rightly guessed, kqueue is not scalable because you have to hold a handle to the file / directory in question, even if in O_RDONLY mode. On Linux, one would use inotify for this purpose (http://linux.die.net/man/7/inotify), but I believe there is no FreeBSD port of this kernel feature!

If you have the time and resources, what you could do is look at the code for audit on BSD (http://www.freebsd.org/cgi/man.cgi?query=audit&sektion=4) and try to code up a version of inotify for BSD! O_O