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