1 /* $OpenBSD: kqueue-flock.c,v 1.1 2012/07/08 12:31:03 guenther Exp $ */ 2 /* 3 * Written by Philip Guenther <guenther@openbsd.org> 2012 Public Domain 4 */ 5 6 #include <sys/types.h> 7 #include <sys/event.h> 8 #include <sys/time.h> 9 #include <sys/wait.h> 10 #include <err.h> 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 #define FILE "lock.test" 18 19 int do_flock(void); 20 21 static void 22 check_lock(int fd, const char *msg) 23 { 24 pid_t pid = fork(); 25 int status; 26 27 if (pid == -1) 28 err(1, "fork"); 29 if (pid == 0) { 30 struct flock fl; 31 32 memset(&fl, 0, sizeof fl); 33 fl.l_type = F_WRLCK; 34 if (fcntl(fd, F_SETLK, &fl) == 0) { 35 printf("lock succeeded %s\n", msg); 36 _exit(1); 37 } 38 if (errno != EAGAIN) 39 err(1, "fcntl(SETLK)"); 40 if (fcntl(fd, F_GETLK, &fl)) 41 err(1, "fcntl(GETLK)"); 42 if (fl.l_type != F_WRLCK) { 43 printf("lock not found %s\n"); 44 _exit(1); 45 } 46 _exit(0); 47 } 48 49 waitpid(pid, &status, 0); 50 if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) 51 exit(1); 52 } 53 54 int 55 do_flock(void) 56 { 57 int fd, kq; 58 struct kevent kev; 59 struct flock fl; 60 61 fd = open(FILE, O_CREAT|O_RDWR, 0666); 62 if (fd < 0) 63 err(1, "open"); 64 memset(&fl, 0, sizeof fl); 65 fl.l_type = F_WRLCK; 66 if (fcntl(fd, F_SETLK, &fl)) 67 err(1, "fcntl(SETLK)"); 68 69 check_lock(fd, "before"); 70 71 kq = kqueue(); 72 EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD, NOTE_LINK, 0, NULL); 73 if (kevent(kq, &kev, 1, NULL, 0, NULL)) 74 err(1, "kevent"); 75 76 check_lock(fd, "after add"); 77 78 EV_SET(&kev, fd, EVFILT_VNODE, EV_DELETE, NOTE_LINK, 0, NULL); 79 if (kevent(kq, &kev, 1, NULL, 0, NULL)) 80 err(1, "kevent"); 81 82 check_lock(fd, "after delete"); 83 84 close(kq); 85 86 check_lock(fd, "after kq close"); 87 88 close(fd); 89 unlink(FILE); 90 return (0); 91 } 92