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;
}
As you rightly guessed,
kqueue
is not scalable because you have to hold a handle to the file / directory in question, even if inO_RDONLY
mode. On Linux, one would useinotify
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