//ripped from the netbsd man page for kqueue //and modified very slightly. //I'll add some more stuff as I find a use for it. #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { if(argc < 2) { printf("usage: filemon file [prog]"); return 1; } monitor(argv[1],argv[2]); } int monitor(char *file,char *handler) { int fd, kq, nev; struct kevent ev; struct stat sb; char buffer[ static const struct timespec tout = { 1, 0 }; if ((fd = open(file, O_RDONLY)) == -1) err(1, "Cannot open `%s'", argv[1]); fstat(fd,&sb); if(S_ISDIR(sb.st_mode)) { //read list of files from dir? //rerun self on all files in that dir. //system("filemon file/*"); //XD getdents(fd,,); } if ((kq = kqueue()) == -1) err(1, "Cannot create kqueue"); EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE, 0, 0); if (kevent(kq, &ev, 1, NULL, 0, &tout) == -1) err(1, "kevent"); for (;;) { nev = kevent(kq, NULL, 0, &ev, 1, &tout); if (nev == -1) err(1, "kevent"); if (nev == 0) continue; printf("nev:%x\n",nev);//probably fd that triggered event? printf("ev.ident:%x\n",ev.ident); printf("ev.filter:%x\n",ev.filter); printf("ev.flags:%x\n",ev.flags); printf("ev.fflags:%x\n",ev.fflags); printf("ev.data:%x\n",ev.data); printf("ev.udata:%x\n",ev.udata); if (ev.fflags & (NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE)) { printf("%s: ",file); if(argv[2]) system(handler); } if (ev.fflags & NOTE_DELETE) { printf("deleted "); ev.fflags &= ~NOTE_DELETE; } if (ev.fflags & NOTE_WRITE) { printf("written "); ev.fflags &= ~NOTE_WRITE; } if (ev.fflags & NOTE_EXTEND) { printf("extended "); ev.fflags &= ~NOTE_EXTEND; } if (ev.fflags & NOTE_ATTRIB) { printf("chmod/chown/utimes "); ev.fflags &= ~NOTE_ATTRIB; } if (ev.fflags & NOTE_LINK) { printf("hardlinked "); ev.fflags &= ~NOTE_LINK; } if (ev.fflags & NOTE_RENAME) { printf("renamed "); ev.fflags &= ~NOTE_RENAME; } if (ev.fflags & NOTE_REVOKE) { printf("revoked "); ev.fflags &= ~NOTE_REVOKE; } printf("\n"); if (ev.fflags) { warnx("unknown event 0x%x\n", ev.fflags); } } return 0; }