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