Dummy commit to test new ssh key
[eleutheria.git] / kqueue / kqdir.c
blobb522a53c219b6be4a9d27059f7ed0d2dee82871d
1 /*
2 * Compile with:
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.
8 */
10 #include <dirent.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h> /* for strerror () */
15 #include <unistd.h>
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 */
27 struct dirent *pdent;
28 DIR *pdir;
29 char fullpath[256];
30 int fdlist[MAX_ENTRIES], cnt, i, error, kq, nev;
32 /* Check argument count */
33 if (argc != 2) {
34 fprintf(stderr, "Usage: %s directory\n", argv[0]);
35 exit(EXIT_FAILURE);
38 /* Create a new kernel event queue */
39 if ((kq = kqueue()) == -1)
40 diep("kqueue()");
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)
47 diep("opendir()");
49 /* Skip . and .. entries */
50 cnt = 0;
51 while((pdent = readdir(pdir)) != NULL && cnt++ < 2)
52 ; /* VOID */
55 * Get all directory entries and for each one of them,
56 * initialise a kevent structure.
58 cnt = 0;
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;
70 * Check path length
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) {
83 perror("open()");
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,
91 0, 0);
93 cnt++;
96 /* Loop forever */
97 for (;;) {
98 nev = kevent(kq, chlist, cnt, evlist, cnt, NULL);
99 if (nev == -1)
100 perror("kevent()");
102 else if (nev > 0) {
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 */
123 CLEANUP_AND_EXIT:;
124 error = EXIT_SUCCESS;
125 for (i = 0; i < cnt; i++)
126 if (close(fdlist[i]) == -1) {
127 error = EXIT_FAILURE;
128 perror("close");
131 if ((closedir(pdir) == -1) || (close(kq) == -1)) {
132 error = EXIT_FAILURE;
133 perror("close");
136 return error;
139 void diep(const char *s)
141 perror(s);
142 exit(EXIT_FAILURE);