3 * gcc kqdir.c -o kqdir -Wall -W -Wextra -ansi -pedantic
5 * The following program will monitor up to MAX_ENTRIES files
6 * (in a directory supplied by the user), and will report any
7 * delete, write or attributes' change operation.
14 #include <string.h> /* for strerror () */
16 #include <sys/event.h>
18 #define MAX_ENTRIES 256
20 /* Function prototypes */
21 void diep(const char *s
);
23 int main(int argc
, char *argv
[])
25 struct kevent evlist
[MAX_ENTRIES
]; /* events we want to monitor */
26 struct kevent chlist
[MAX_ENTRIES
]; /* events that were triggered */
30 int fdlist
[MAX_ENTRIES
], cnt
, i
, error
, kq
, nev
;
32 /* Check argument count */
34 fprintf(stderr
, "Usage: %s directory\n", argv
[0]);
38 /* Create a new kernel event queue */
39 if ((kq
= kqueue()) == -1)
43 * Open directory named by argv[1], associate a directory stream
44 * with it and return a pointer to it.
46 if ((pdir
= opendir(argv
[1])) == NULL
)
49 /* Skip . and .. entries */
51 while((pdent
= readdir(pdir
)) != NULL
&& cnt
++ < 2)
55 * Get all directory entries and for each one of them,
56 * initialise a kevent structure.
59 while((pdent
= readdir(pdir
)) != NULL
) {
61 * Check whether we have exceeded the max number of
62 * entries that we can monitor.
64 if (cnt
> MAX_ENTRIES
- 1) {
65 fprintf(stderr
, "Max number of entries exceeded\n");
66 goto CLEANUP_AND_EXIT
;
71 * don't forget +1 for the '\0'
73 if (strlen(argv
[1] + strlen(pdent
->d_name
) + 2) > 256) {
74 fprintf(stderr
,"Max path length exceeded\n");
75 goto CLEANUP_AND_EXIT
;
77 strcpy(fullpath
, argv
[1]);
78 strcat(fullpath
, "/");
79 strcat(fullpath
, pdent
->d_name
);
81 /* Open directory entry */
82 if ((fdlist
[cnt
] = open(fullpath
, O_RDONLY
)) == -1) {
84 goto CLEANUP_AND_EXIT
;
87 /* Initialise kevent structure */
88 EV_SET(&chlist
[cnt
], fdlist
[cnt
], EVFILT_VNODE
,
89 EV_ADD
| EV_ENABLE
| EV_ONESHOT
,
90 NOTE_DELETE
| NOTE_EXTEND
| NOTE_WRITE
| NOTE_ATTRIB
,
98 nev
= kevent(kq
, chlist
, cnt
, evlist
, cnt
, NULL
);
103 for (i
= 0; i
< nev
; i
++) {
104 if (evlist
[i
].flags
& EV_ERROR
) {
105 fprintf(stderr
, "EV_ERROR: %s\n", strerror(evlist
[i
].data
));
106 goto CLEANUP_AND_EXIT
;
109 if (evlist
[i
].fflags
& NOTE_DELETE
)
110 printf("fd: %d Deleted\n", evlist
[i
].ident
);
112 else if (evlist
[i
].fflags
& NOTE_EXTEND
113 || evlist
[i
].fflags
& NOTE_WRITE
)
114 printf("fd: %d Modified\n", evlist
[i
].ident
);
116 else if (evlist
[i
].fflags
& NOTE_ATTRIB
)
117 printf("fd: %d Attributes modified\n", evlist
[i
].ident
);
122 /* Clean up file descriptors, directory stream, kqueue */
124 error
= EXIT_SUCCESS
;
125 for (i
= 0; i
< cnt
; i
++)
126 if (close(fdlist
[i
]) == -1) {
127 error
= EXIT_FAILURE
;
131 if ((closedir(pdir
) == -1) || (close(kq
) == -1)) {
132 error
= EXIT_FAILURE
;
139 void diep(const char *s
)