libkqueue.c
1 /* kqueue interface, C mini-library 2 * 3 * Copyright 2012 Joey Hess <id@joeyh.name> 4 * 5 * License: BSD-2-clause 6 */ 7 8 #include <stdio.h> 9 #include <dirent.h> 10 #include <fcntl.h> 11 #include <stdlib.h> 12 #include <unistd.h> 13 #include <sys/types.h> 14 #include <sys/event.h> 15 #include <sys/time.h> 16 #include <errno.h> 17 18 /* The specified fds are added to the set of fds being watched for changes. 19 * Fds passed to prior calls still take effect, so it's most efficient to 20 * not pass the same fds repeatedly. 21 * 22 * Returns the fd that changed, or -1 on error. 23 */ 24 signed int helper(const int kq, const int fdcnt, const int *fdlist, int nodelay) { 25 int i, nev; 26 struct kevent evlist[1]; 27 struct kevent chlist[fdcnt]; 28 struct timespec avoiddelay = {0, 0}; 29 struct timespec *timeout = nodelay ? &avoiddelay : NULL; 30 31 for (i = 0; i < fdcnt; i++) { 32 EV_SET(&chlist[i], fdlist[i], EVFILT_VNODE, 33 EV_ADD | EV_ENABLE | EV_CLEAR, 34 NOTE_WRITE, 35 0, 0); 36 } 37 38 nev = kevent(kq, chlist, fdcnt, evlist, 1, timeout); 39 if (nev == 1) 40 return evlist[0].ident; 41 else 42 return -1; 43 } 44 45 /* Initializes a new, empty kqueue. */ 46 int init_kqueue() { 47 int kq; 48 if ((kq = kqueue()) == -1) { 49 perror("kqueue"); 50 exit(1); 51 } 52 return kq; 53 } 54 55 /* Adds fds to the set that should be watched. */ 56 void addfds_kqueue(const int kq, const int fdcnt, const int *fdlist) { 57 helper(kq, fdcnt, fdlist, 1); 58 } 59 60 /* Waits for a change event on a kqueue. */ 61 signed int waitchange_kqueue(const int kq) { 62 return helper(kq, 0, NULL, 0); 63 } 64 65 /* 66 main () { 67 int list[1]; 68 int kq; 69 list[0]=open(".", O_RDONLY); 70 kq = init_kqueue(); 71 addfds_kqueue(kq, 1, list) 72 printf("change: %i\n", waitchange_kqueue(kq)); 73 } 74 */