1 #include <err.h> 2 #include <fcntl.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 6 #include <sys/event.h> 7 #include <sys/time.h> 8 9 /* 10 * External test set-up code is expected to do the equivalent of 11 * cd $TOPDIR 12 * mkdir realdir 13 * mkdir nulldir 14 * mount -t null $TOPDIR/realdir $TOPDIR/nulldir 15 * rm -f $TOPDIR/realdir/afile 16 * touch $TOPDIR/realdir/afile 17 * then execute this test program: 18 * ./h_nullmnt $TOPDIR/realdir/afile $TOPDIR/nulldir/afile 19 * 20 * The expected result is that the write() to the nullfile will 21 * queue up a preexisting kevent which will then be detected by 22 * the (second) call to kevent(); the failure mode is that the 23 * write()'s extension to the file is not seen, and the kevent 24 * call times out after 5 seconds. 25 * 26 * Clean-up code should undo the null mount and delete everything 27 * in the test directory. 28 */ 29 30 int main(int argc, char **argv) 31 { 32 int watch_file, write_file; 33 int kq, nev, rsize; 34 struct timespec timeout; 35 struct kevent eventlist; 36 const char outbuf[] = "new\n"; 37 char inbuf[20]; 38 39 if (argc <= 2) 40 errx(EXIT_FAILURE, "insufficient args %d", argc); 41 42 watch_file = open(argv[1], O_RDONLY); 43 if (watch_file == -1) 44 err(EXIT_FAILURE, "failed to open watch_file %s", 45 argv[1]); 46 47 write_file = open(argv[2], O_WRONLY, O_APPEND); 48 if (write_file == -1) 49 err(EXIT_FAILURE, "failed to open write_file %s", 50 argv[2]); 51 52 if ((kq = kqueue()) == -1) 53 err(EXIT_FAILURE, "Cannot create kqueue"); 54 55 timeout.tv_sec = 5; 56 timeout.tv_nsec = 0; 57 58 EV_SET(&eventlist, watch_file, 59 EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 60 NOTE_WRITE | NOTE_EXTEND, 0, 0); 61 if (kevent(kq, &eventlist, 1, NULL, 0, NULL) == -1) 62 err(EXIT_FAILURE, "Failed to set eventlist for fd %d", 63 watch_file); 64 65 rsize = read(watch_file, &inbuf, sizeof(inbuf)); 66 if (rsize) 67 errx(EXIT_FAILURE, "Ooops we got %d bytes of data!\n", rsize); 68 69 write(write_file, &outbuf, sizeof(outbuf) - 1); 70 71 nev = kevent(kq, NULL, 0, &eventlist, 1, &timeout); 72 if (nev == -1) 73 err(EXIT_FAILURE, "Failed to retrieve event"); 74 75 errx((nev == 0) ? EXIT_FAILURE : EXIT_SUCCESS, 76 "Retrieved %d events, first 0x%x", nev, eventlist.flags); 77 } 78