Merge branch 'exp-hash'
[eleutheria.git] / kqueue / kqdir.c
blob7dc7ba4c7bf4cf19441776e77e973cfd0fde55f9
1 /* compile with:
2 gcc kqdir.c -o kqdir -Wall -W -Wextra -ansi -pedantic
4 The following program will monitor up to MAX_ENTRIES files
5 (in a directory supplied by the user), and will report any
6 delete, write or attributes' change operation.
7 */
9 #include <dirent.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h> /* for strerror () */
14 #include <unistd.h>
15 #include <sys/event.h>
17 #define MAX_ENTRIES 256
19 /* function prototypes */
20 void diep(const char *s);
22 int main(int argc, char *argv[])
24 struct kevent evlist[MAX_ENTRIES]; /* events we want to monitor */
25 struct kevent chlist[MAX_ENTRIES]; /* events that were triggered */
26 struct dirent *pdent;
27 DIR *pdir;
28 char fullpath[256];
29 int fdlist[MAX_ENTRIES], cnt, i, kq, nev;
31 /* check argument count */
32 if (argc != 2) {
33 fprintf(stderr, "Usage: %s directory\n", argv[0]);
34 exit(EXIT_FAILURE);
37 /* create a new kernel event queue */
38 if ((kq = kqueue()) == -1)
39 diep("kqueue");
41 /* open directory named by argv[1], associate a directory stream
42 with it and return a pointer to it
44 if ((pdir = opendir(argv[1])) == NULL)
45 diep("opendir");
47 /* skip . and .. entries */
48 cnt = 0;
49 while((pdent = readdir(pdir)) != NULL && cnt++ < 2)
52 /* get all directory entries and for each one of them,
53 initialise a kevent structure
55 cnt = 0;
56 while((pdent = readdir(pdir)) != NULL) {
57 /* check whether we have exceeded the max number of
58 entries that we can monitor
60 if (cnt > MAX_ENTRIES - 1) {
61 fprintf(stderr, "Max number of entries exceeded\n");
62 goto CLEANUP_AND_EXIT;
65 /* check path length
66 don't forget +1 for the '\0'
68 if (strlen(argv[1] + strlen(pdent->d_name) + 2) > 256) {
69 fprintf(stderr,"Max path length exceeded\n");
70 goto CLEANUP_AND_EXIT;
72 strcpy(fullpath, argv[1]);
73 strcat(fullpath, "/");
74 strcat(fullpath, pdent->d_name);
76 /* open directory entry */
77 if ((fdlist[cnt] = open(fullpath, O_RDONLY)) == -1) {
78 perror("open");
79 goto CLEANUP_AND_EXIT;
82 /* initialise kevent structure */
83 EV_SET(&chlist[cnt], fdlist[cnt], EVFILT_VNODE,
84 EV_ADD | EV_ENABLE | EV_ONESHOT,
85 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB,
86 0, 0);
88 cnt++;
91 /* loop forever */
92 for (;;) {
93 nev = kevent(kq, chlist, cnt, evlist, cnt, NULL);
94 if (nev == -1)
95 perror("kevent");
97 else if (nev > 0) {
98 for (i = 0; i < nev; i++) {
99 if (evlist[i].flags & EV_ERROR) {
100 fprintf(stderr, "EV_ERROR: %s\n", strerror(evlist[i].data));
101 goto CLEANUP_AND_EXIT;
104 if (evlist[i].fflags & NOTE_DELETE)
105 printf("fd: %d Deleted\n", evlist[i].ident);
107 else if (evlist[i].fflags & NOTE_EXTEND
108 || evlist[i].fflags & NOTE_WRITE)
109 printf("fd: %d Modified\n", evlist[i].ident);
111 else if (evlist[i].fflags & NOTE_ATTRIB)
112 printf("fd: %d Attributes modified\n", evlist[i].ident);
117 /* close open file descriptors, directory stream and kqueue */
118 CLEANUP_AND_EXIT:;
119 for (i = 0; i < cnt; i++)
120 close(fdlist[i]);
121 closedir(pdir);
122 close(kq);
124 return EXIT_SUCCESS;
127 void diep(const char *s)
129 perror(s);
130 exit(EXIT_FAILURE);