xref: /openbsd-src/regress/sys/kern/kqueue/kqueue-flock.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
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