1/*	$OpenBSD: lockf.c,v 1.1 2018/11/06 18:11:11 anton Exp $	*/
2
3/*
4 * Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <err.h>
20#include <fcntl.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24
25#include "util.h"
26
27int verbose = 0;
28
29/*
30 * Test 1 - F_LOCK positive length
31 */
32static int
33test1(int fd)
34{
35	struct flock fl;
36	pid_t pid;
37	int res;
38
39	fl.l_start = 0;
40	fl.l_len = 16;
41	fl.l_type = F_WRLCK;
42	fl.l_whence = SEEK_CUR;
43	res = fcntl(fd, F_SETLK, &fl);
44	FAIL(res != 0);
45
46	pid = fork();
47	if (pid == -1)
48		err(1, "fork");
49	if (pid == 0) {
50		res = fcntl(fd, F_SETLK, &fl);
51		FAIL(res != -1);
52		FAIL(fl.l_type != F_WRLCK);
53		_exit(0);
54	}
55	res = safe_waitpid(pid);
56	FAIL(res != 0);
57
58	SUCCEED;
59}
60
61/*
62 * Test 2 - F_LOCK negative length
63 */
64static int
65test2(int fd)
66{
67	struct flock fl;
68	pid_t pid;
69	off_t len = 16;
70	int res;
71
72	if (lseek(fd, len, SEEK_SET) == -1)
73		err(1, "lseek");
74
75	fl.l_start = 0;
76	fl.l_len = -len;
77	fl.l_type = F_WRLCK;
78	fl.l_whence = SEEK_CUR;
79	res = fcntl(fd, F_SETLK, &fl);
80	FAIL(res != 0);
81
82	pid = fork();
83	if (pid == -1)
84		err(1, "fork");
85	if (pid == 0) {
86		if (lseek(fd, 0, SEEK_SET) == -1)
87			err(1, "lseek");
88
89		fl.l_start = 0;
90		fl.l_len = len;
91		fl.l_whence = SEEK_SET;
92		res = fcntl(fd, F_GETLK, &fl);
93		FAIL(res != 0);
94		FAIL(fl.l_type != F_WRLCK);
95		_exit(0);
96	}
97	res = safe_waitpid(pid);
98	FAIL(res != 0);
99
100	SUCCEED;
101}
102
103static struct test tests[] = {
104	{	test1,		0	},
105	{	test2,		0	},
106};
107
108static int test_count = sizeof(tests) / sizeof(tests[0]);
109
110int
111main(int argc, char *argv[])
112{
113	const char *errstr;
114	int c, error, fd, i;
115	int testnum = 0;
116
117	while ((c = getopt(argc, argv, "v")) != -1)
118		switch (c) {
119		case 'v':
120			verbose = 1;
121			break;
122		default:
123			usage();
124		}
125	argc -= optind;
126	argv += optind;
127	if (argc > 1)
128		usage();
129	if (argc == 1) {
130		testnum = strtonum(argv[0], 1, test_count, &errstr);
131		if (testnum == 0)
132			errx(1, "test number %s", errstr);
133	}
134
135	fd = make_file(1024);
136
137	error = 0;
138	for (i = 0; i < test_count; i++) {
139		if (testnum == 0 || i + 1 == testnum)
140			error |= tests[i].testfn(fd);
141	}
142
143	return (error ? 1 : 0);
144}
145