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