1 /* $OpenBSD: kqueue-flock.c,v 1.3 2015/08/13 10:13:55 uebayasi 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 close(fd); 48 _exit(0); 49 } 50 51 waitpid(pid, &status, 0); 52 if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) 53 exit(1); 54 } 55 56 int 57 do_flock(void) 58 { 59 int fd, kq; 60 struct kevent kev; 61 struct flock fl; 62 63 fd = open(FILE, O_CREAT|O_RDWR, 0666); 64 if (fd < 0) 65 err(1, "open"); 66 memset(&fl, 0, sizeof fl); 67 fl.l_type = F_WRLCK; 68 if (fcntl(fd, F_SETLK, &fl)) 69 err(1, "fcntl(SETLK)"); 70 71 check_lock(fd, "before"); 72 73 kq = kqueue(); 74 EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD, NOTE_LINK, 0, NULL); 75 if (kevent(kq, &kev, 1, NULL, 0, NULL)) 76 err(1, "kevent"); 77 78 check_lock(fd, "after add"); 79 80 EV_SET(&kev, fd, EVFILT_VNODE, EV_DELETE, NOTE_LINK, 0, NULL); 81 if (kevent(kq, &kev, 1, NULL, 0, NULL)) 82 err(1, "kevent"); 83 84 check_lock(fd, "after delete"); 85 86 close(kq); 87 88 check_lock(fd, "after kq close"); 89 90 close(fd); 91 unlink(FILE); 92 return (0); 93 } 94