1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
//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 <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <err.h>
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'", file);
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,,); //I have code to do this in the MUD
printf("warning: this doesn't show changes of file in the dir.");
printf("warning: it just shows changes of the dir itself.");
}
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(handler) 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;
}
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("usage: filemon file [prog]");
return 1;
}
return monitor(argv[1],argv[2]);
}
|