xref: /openbsd-src/regress/sys/kern/flock/flock.c (revision c36021105abe733ede2e2136f463fbccbff33cff)
197a3f8ceSart /*-
297a3f8ceSart  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
397a3f8ceSart  * Authors: Doug Rabson <dfr@rabson.org>
497a3f8ceSart  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
597a3f8ceSart  *
697a3f8ceSart  * Redistribution and use in source and binary forms, with or without
797a3f8ceSart  * modification, are permitted provided that the following conditions
897a3f8ceSart  * are met:
997a3f8ceSart  * 1. Redistributions of source code must retain the above copyright
1097a3f8ceSart  *    notice, this list of conditions and the following disclaimer.
1197a3f8ceSart  * 2. Redistributions in binary form must reproduce the above copyright
1297a3f8ceSart  *    notice, this list of conditions and the following disclaimer in the
1397a3f8ceSart  *    documentation and/or other materials provided with the distribution.
1497a3f8ceSart  *
1597a3f8ceSart  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1697a3f8ceSart  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1797a3f8ceSart  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1897a3f8ceSart  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1997a3f8ceSart  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2097a3f8ceSart  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2197a3f8ceSart  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2297a3f8ceSart  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2397a3f8ceSart  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2497a3f8ceSart  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2597a3f8ceSart  * SUCH DAMAGE.
2697a3f8ceSart  *
2797a3f8ceSart  * $FreeBSD: src/tools/regression/file/flock/flock.c,v 1.3 2008/06/26 10:21:54 dfr Exp $
2897a3f8ceSart  */
2997a3f8ceSart 
3097a3f8ceSart #include <sys/time.h>
3197a3f8ceSart #include <sys/stat.h>
3297a3f8ceSart 
3397a3f8ceSart #include <err.h>
3497a3f8ceSart #include <errno.h>
3597a3f8ceSart #include <fcntl.h>
360d5ae59dSanton #include <limits.h>
3797a3f8ceSart #include <signal.h>
3897a3f8ceSart #include <stdio.h>
3997a3f8ceSart #include <stdlib.h>
4097a3f8ceSart #include <string.h>
41afb1c1edSanton #include <termios.h>
4297a3f8ceSart #include <unistd.h>
43afb1c1edSanton #include <util.h>
4497a3f8ceSart 
45cdea53deSanton #include "util.h"
4697a3f8ceSart 
47cdea53deSanton int verbose = 0;
4897a3f8ceSart 
4997a3f8ceSart static void
ignore_alarm(int __unused sig)5097a3f8ceSart ignore_alarm(int __unused sig)
5197a3f8ceSart {
5297a3f8ceSart }
5397a3f8ceSart 
5497a3f8ceSart static int
safe_kill(pid_t pid,int sig)5597a3f8ceSart safe_kill(pid_t pid, int sig)
5697a3f8ceSart {
5797a3f8ceSart 	int save_errno;
5897a3f8ceSart 	int status;
5997a3f8ceSart 
6097a3f8ceSart 	save_errno = errno;
6197a3f8ceSart 	errno = 0;
6297a3f8ceSart 	status = kill(pid, sig);
6397a3f8ceSart 	errno = save_errno;
6497a3f8ceSart 
6597a3f8ceSart 	return (status);
6697a3f8ceSart }
6797a3f8ceSart 
6897a3f8ceSart /*
6997a3f8ceSart  * Test 1 - F_GETLK on unlocked region
7097a3f8ceSart  *
7197a3f8ceSart  * If no lock is found that would prevent this lock from being
7297a3f8ceSart  * created, the structure is left unchanged by this function call
7397a3f8ceSart  * except for the lock type which is set to F_UNLCK.
7497a3f8ceSart  */
7597a3f8ceSart static int
test1(int fd)7627fff5e2Santon test1(int fd)
7797a3f8ceSart {
7897a3f8ceSart 	struct flock fl1, fl2;
7997a3f8ceSart 
8097a3f8ceSart 	memset(&fl1, 1, sizeof(fl1));
8197a3f8ceSart 	fl1.l_type = F_WRLCK;
8297a3f8ceSart 	fl1.l_whence = SEEK_SET;
8397a3f8ceSart 	fl2 = fl1;
8497a3f8ceSart 
8597a3f8ceSart 	if (fcntl(fd, F_GETLK, &fl1) < 0)
8697a3f8ceSart 		err(1, "F_GETLK");
8797a3f8ceSart 
8897a3f8ceSart 	if (verbose) printf("1 - F_GETLK on unlocked region: ");
8997a3f8ceSart 	FAIL(fl1.l_start != fl2.l_start);
9097a3f8ceSart 	FAIL(fl1.l_len != fl2.l_len);
9197a3f8ceSart 	FAIL(fl1.l_pid != fl2.l_pid);
9297a3f8ceSart 	FAIL(fl1.l_type != F_UNLCK);
9397a3f8ceSart 	FAIL(fl1.l_whence != fl2.l_whence);
9497a3f8ceSart 
9597a3f8ceSart 	SUCCEED;
9697a3f8ceSart }
9797a3f8ceSart 
9897a3f8ceSart /*
9997a3f8ceSart  * Test 2 - F_SETLK on locked region
10097a3f8ceSart  *
10197a3f8ceSart  * If a shared or exclusive lock cannot be set, fcntl returns
10297a3f8ceSart  * immediately with EACCES or EAGAIN.
10397a3f8ceSart  */
10497a3f8ceSart static int
test2(int fd)10527fff5e2Santon test2(int fd)
10697a3f8ceSart {
10797a3f8ceSart 	/*
10897a3f8ceSart 	 * We create a child process to hold the lock which we will
10997a3f8ceSart 	 * test. We use a pipe to communicate with the child.
11097a3f8ceSart 	 */
11197a3f8ceSart 	int pid;
11297a3f8ceSart 	int pfd[2];
11397a3f8ceSart 	struct flock fl;
11497a3f8ceSart 	char ch;
11597a3f8ceSart 	int res;
11697a3f8ceSart 
11797a3f8ceSart 	if (pipe(pfd) < 0)
11897a3f8ceSart 		err(1, "pipe");
11997a3f8ceSart 
12097a3f8ceSart 	fl.l_start = 0;
12197a3f8ceSart 	fl.l_len = 0;
12297a3f8ceSart 	fl.l_type = F_WRLCK;
12397a3f8ceSart 	fl.l_whence = SEEK_SET;
12497a3f8ceSart 
12597a3f8ceSart 	pid = fork();
12697a3f8ceSart 	if (pid < 0)
12797a3f8ceSart 		err(1, "fork");
12897a3f8ceSart 
12997a3f8ceSart 	if (pid == 0) {
13097a3f8ceSart 		/*
13197a3f8ceSart 		 * We are the child. We set a write lock and then
13297a3f8ceSart 		 * write one byte back to the parent to tell it. The
13397a3f8ceSart 		 * parent will kill us when its done.
13497a3f8ceSart 		 */
13597a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
13697a3f8ceSart 			err(1, "F_SETLK (child)");
13797a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
13897a3f8ceSart 			err(1, "writing to pipe (child)");
13997a3f8ceSart 		pause();
14097a3f8ceSart 		exit(0);
14197a3f8ceSart 	}
14297a3f8ceSart 
14397a3f8ceSart 	/*
14497a3f8ceSart 	 * Wait until the child has set its lock and then perform the
14597a3f8ceSart 	 * test.
14697a3f8ceSart 	 */
14797a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
14897a3f8ceSart 		err(1, "reading from pipe (child)");
14997a3f8ceSart 
15097a3f8ceSart 	/*
15197a3f8ceSart 	 * fcntl should return -1 with errno set to either EACCES or
15297a3f8ceSart 	 * EAGAIN.
15397a3f8ceSart 	 */
15497a3f8ceSart 	if (verbose) printf("2 - F_SETLK on locked region: ");
15597a3f8ceSart 	res = fcntl(fd, F_SETLK, &fl);
15697a3f8ceSart 	safe_kill(pid, SIGTERM);
15797a3f8ceSart 	safe_waitpid(pid);
15897a3f8ceSart 	close(pfd[0]);
15997a3f8ceSart 	close(pfd[1]);
16097a3f8ceSart 	FAIL(res == 0);
16197a3f8ceSart 	FAIL(errno != EACCES && errno != EAGAIN);
16297a3f8ceSart 
16397a3f8ceSart 	SUCCEED;
16497a3f8ceSart }
16597a3f8ceSart 
16697a3f8ceSart /*
16797a3f8ceSart  * Test 3 - F_SETLKW on locked region
16897a3f8ceSart  *
16997a3f8ceSart  * If a shared or exclusive lock is blocked by other locks, the
17097a3f8ceSart  * process waits until the request can be satisfied.
17197a3f8ceSart  *
17297a3f8ceSart  * XXX this test hangs on FreeBSD NFS filesystems due to limitations
17397a3f8ceSart  * in FreeBSD's client (and server) lockd implementation.
17497a3f8ceSart  */
17597a3f8ceSart static int
test3(int fd)17627fff5e2Santon test3(int fd)
17797a3f8ceSart {
17897a3f8ceSart 	/*
17997a3f8ceSart 	 * We create a child process to hold the lock which we will
18097a3f8ceSart 	 * test. We use a pipe to communicate with the child.
18197a3f8ceSart 	 */
18297a3f8ceSart 	int pid;
18397a3f8ceSart 	int pfd[2];
18497a3f8ceSart 	struct flock fl;
18597a3f8ceSart 	char ch;
18697a3f8ceSart 	int res;
18797a3f8ceSart 
18897a3f8ceSart 	if (pipe(pfd) < 0)
18997a3f8ceSart 		err(1, "pipe");
19097a3f8ceSart 
19197a3f8ceSart 	fl.l_start = 0;
19297a3f8ceSart 	fl.l_len = 0;
19397a3f8ceSart 	fl.l_type = F_WRLCK;
19497a3f8ceSart 	fl.l_whence = SEEK_SET;
19597a3f8ceSart 
19697a3f8ceSart 	pid = fork();
19797a3f8ceSart 	if (pid < 0)
19897a3f8ceSart 		err(1, "fork");
19997a3f8ceSart 
20097a3f8ceSart 	if (pid == 0) {
20197a3f8ceSart 		/*
20297a3f8ceSart 		 * We are the child. We set a write lock and then
20397a3f8ceSart 		 * write one byte back to the parent to tell it. The
20497a3f8ceSart 		 * parent will kill us when its done.
20597a3f8ceSart 		 */
20697a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
20797a3f8ceSart 			err(1, "F_SETLK (child)");
20897a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
20997a3f8ceSart 			err(1, "writing to pipe (child)");
21097a3f8ceSart 		pause();
21197a3f8ceSart 		exit(0);
21297a3f8ceSart 	}
21397a3f8ceSart 
21497a3f8ceSart 	/*
21597a3f8ceSart 	 * Wait until the child has set its lock and then perform the
21697a3f8ceSart 	 * test.
21797a3f8ceSart 	 */
21897a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
21997a3f8ceSart 		err(1, "reading from pipe (child)");
22097a3f8ceSart 
22197a3f8ceSart 	/*
22297a3f8ceSart 	 * fcntl should wait until the alarm and then return -1 with
22397a3f8ceSart 	 * errno set to EINTR.
22497a3f8ceSart 	 */
22597a3f8ceSart 	if (verbose) printf("3 - F_SETLKW on locked region: ");
22697a3f8ceSart 
22797a3f8ceSart 	alarm(1);
22897a3f8ceSart 
22997a3f8ceSart 	res = fcntl(fd, F_SETLKW, &fl);
23097a3f8ceSart 	safe_kill(pid, SIGTERM);
23197a3f8ceSart 	safe_waitpid(pid);
23297a3f8ceSart 	close(pfd[0]);
23397a3f8ceSart 	close(pfd[1]);
23497a3f8ceSart 	FAIL(res == 0);
23597a3f8ceSart 	FAIL(errno != EINTR);
23697a3f8ceSart 
23797a3f8ceSart 	SUCCEED;
23897a3f8ceSart }
23997a3f8ceSart 
24097a3f8ceSart /*
24197a3f8ceSart  * Test 4 - F_GETLK on locked region
24297a3f8ceSart  *
24397a3f8ceSart  * Get the first lock that blocks the lock.
24497a3f8ceSart  */
24597a3f8ceSart static int
test4(int fd)24627fff5e2Santon test4(int fd)
24797a3f8ceSart {
24897a3f8ceSart 	/*
24997a3f8ceSart 	 * We create a child process to hold the lock which we will
25097a3f8ceSart 	 * test. We use a pipe to communicate with the child.
25197a3f8ceSart 	 */
25297a3f8ceSart 	int pid;
25397a3f8ceSart 	int pfd[2];
25497a3f8ceSart 	struct flock fl;
25597a3f8ceSart 	char ch;
25697a3f8ceSart 
25797a3f8ceSart 	if (pipe(pfd) < 0)
25897a3f8ceSart 		err(1, "pipe");
25997a3f8ceSart 
26097a3f8ceSart 	fl.l_start = 0;
26197a3f8ceSart 	fl.l_len = 99;
26297a3f8ceSart 	fl.l_type = F_WRLCK;
26397a3f8ceSart 	fl.l_whence = SEEK_SET;
26497a3f8ceSart 
26597a3f8ceSart 	pid = fork();
26697a3f8ceSart 	if (pid < 0)
26797a3f8ceSart 		err(1, "fork");
26897a3f8ceSart 
26997a3f8ceSart 	if (pid == 0) {
27097a3f8ceSart 		/*
27197a3f8ceSart 		 * We are the child. We set a write lock and then
27297a3f8ceSart 		 * write one byte back to the parent to tell it. The
27397a3f8ceSart 		 * parent will kill us when its done.
27497a3f8ceSart 		 */
27597a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
27697a3f8ceSart 			err(1, "F_SETLK (child)");
27797a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
27897a3f8ceSart 			err(1, "writing to pipe (child)");
27997a3f8ceSart 		pause();
28097a3f8ceSart 		exit(0);
28197a3f8ceSart 	}
28297a3f8ceSart 
28397a3f8ceSart 	/*
28497a3f8ceSart 	 * Wait until the child has set its lock and then perform the
28597a3f8ceSart 	 * test.
28697a3f8ceSart 	 */
28797a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
28897a3f8ceSart 		err(1, "reading from pipe (child)");
28997a3f8ceSart 
29097a3f8ceSart 	/*
29197a3f8ceSart 	 * fcntl should return a lock structure reflecting the lock we
29297a3f8ceSart 	 * made in the child process.
29397a3f8ceSart 	 */
29497a3f8ceSart 	if (fcntl(fd, F_GETLK, &fl) < 0)
29597a3f8ceSart 		err(1, "F_GETLK");
29697a3f8ceSart 
29797a3f8ceSart 	if (verbose) printf("4 - F_GETLK on locked region: ");
29897a3f8ceSart 	FAIL(fl.l_start != 0);
29997a3f8ceSart 	FAIL(fl.l_len != 99);
30097a3f8ceSart 	FAIL(fl.l_type != F_WRLCK);
30197a3f8ceSart 	FAIL(fl.l_pid != pid);
30297a3f8ceSart 
30397a3f8ceSart 	safe_kill(pid, SIGTERM);
30497a3f8ceSart 	safe_waitpid(pid);
30597a3f8ceSart 	close(pfd[0]);
30697a3f8ceSart 	close(pfd[1]);
30797a3f8ceSart 
30897a3f8ceSart 	SUCCEED;
30997a3f8ceSart }
31097a3f8ceSart 
31197a3f8ceSart /*
31297a3f8ceSart  * Test 5 - F_SETLKW simple deadlock
31397a3f8ceSart  *
31497a3f8ceSart  * If a blocking shared lock request would cause a deadlock (i.e. the
31597a3f8ceSart  * lock request is blocked by a process which is itself blocked on a
31697a3f8ceSart  * lock currently owned by the process making the new request),
31797a3f8ceSart  * EDEADLK is returned.
31897a3f8ceSart  */
31997a3f8ceSart static int
test5(int fd)32027fff5e2Santon test5(int fd)
32197a3f8ceSart {
32297a3f8ceSart 	/*
32397a3f8ceSart 	 * We create a child process to hold the lock which we will
32497a3f8ceSart 	 * test. Because our test relies on the child process being
32597a3f8ceSart 	 * blocked on the parent's lock, we can't easily use a pipe to
32697a3f8ceSart 	 * synchronize so we just sleep in the parent to given the
32797a3f8ceSart 	 * child a chance to setup.
32897a3f8ceSart 	 *
32997a3f8ceSart 	 * To create the deadlock condition, we arrange for the parent
33097a3f8ceSart 	 * to lock the first byte of the file and the child to lock
33197a3f8ceSart 	 * the second byte.  After locking the second byte, the child
33297a3f8ceSart 	 * will attempt to lock the first byte of the file, and
33397a3f8ceSart 	 * block. The parent will then attempt to lock the second byte
33497a3f8ceSart 	 * (owned by the child) which should cause deadlock.
33597a3f8ceSart 	 */
33697a3f8ceSart 	int pid;
33797a3f8ceSart 	struct flock fl;
33897a3f8ceSart 	int res;
33997a3f8ceSart 
34097a3f8ceSart 	/*
34197a3f8ceSart 	 * Lock the first byte in the parent.
34297a3f8ceSart 	 */
34397a3f8ceSart 	fl.l_start = 0;
34497a3f8ceSart 	fl.l_len = 1;
34597a3f8ceSart 	fl.l_type = F_WRLCK;
34697a3f8ceSart 	fl.l_whence = SEEK_SET;
34797a3f8ceSart 	if (fcntl(fd, F_SETLK, &fl) < 0)
34897a3f8ceSart 		err(1, "F_SETLK 1 (parent)");
34997a3f8ceSart 
35097a3f8ceSart 	pid = fork();
35197a3f8ceSart 	if (pid < 0)
35297a3f8ceSart 		err(1, "fork");
35397a3f8ceSart 
35497a3f8ceSart 	if (pid == 0) {
35597a3f8ceSart 		/*
35697a3f8ceSart 		 * Lock the second byte in the child and then block on
35797a3f8ceSart 		 * the parent's lock.
35897a3f8ceSart 		 */
35997a3f8ceSart 		fl.l_start = 1;
36097a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
36197a3f8ceSart 			err(1, "F_SETLK (child)");
36297a3f8ceSart 		fl.l_start = 0;
36397a3f8ceSart 		if (fcntl(fd, F_SETLKW, &fl) < 0)
36497a3f8ceSart 			err(1, "F_SETLKW (child)");
36597a3f8ceSart 		exit(0);
36697a3f8ceSart 	}
36797a3f8ceSart 
36897a3f8ceSart 	/*
36997a3f8ceSart 	 * Wait until the child has set its lock and then perform the
37097a3f8ceSart 	 * test.
37197a3f8ceSart 	 */
37297a3f8ceSart 	sleep(1);
37397a3f8ceSart 
37497a3f8ceSart 	/*
37597a3f8ceSart 	 * fcntl should immediately return -1 with errno set to
37697a3f8ceSart 	 * EDEADLK. If the alarm fires, we failed to detect the
37797a3f8ceSart 	 * deadlock.
37897a3f8ceSart 	 */
37997a3f8ceSart 	alarm(1);
38097a3f8ceSart 	if (verbose) printf("5 - F_SETLKW simple deadlock: ");
38197a3f8ceSart 
38297a3f8ceSart 	fl.l_start = 1;
38397a3f8ceSart 	res = fcntl(fd, F_SETLKW, &fl);
38497a3f8ceSart 	safe_kill(pid, SIGTERM);
38597a3f8ceSart 	safe_waitpid(pid);
38697a3f8ceSart 
38797a3f8ceSart 	FAIL(res == 0);
38897a3f8ceSart 	FAIL(errno != EDEADLK);
38997a3f8ceSart 
39097a3f8ceSart 	fl.l_start = 0;
39197a3f8ceSart 	fl.l_len = 0;
39297a3f8ceSart 	fl.l_type = F_UNLCK;
39397a3f8ceSart 	if (fcntl(fd, F_SETLK, &fl) < 0)
39497a3f8ceSart 		err(1, "F_UNLCK");
39597a3f8ceSart 
39697a3f8ceSart 	/*
39797a3f8ceSart 	 * Cancel the alarm to avoid confusing later tests.
39897a3f8ceSart 	 */
39997a3f8ceSart 	alarm(0);
40097a3f8ceSart 
40197a3f8ceSart 	SUCCEED;
40297a3f8ceSart }
40397a3f8ceSart 
40497a3f8ceSart /*
40597a3f8ceSart  * Test 6 - F_SETLKW complex deadlock.
40697a3f8ceSart  *
40797a3f8ceSart  * This test involves three process, P, C1 and C2. We set things up so
40897a3f8ceSart  * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We
40997a3f8ceSart  * also block C2 by attempting to lock byte zero. Lastly, P attempts
41097a3f8ceSart  * to lock a range including byte 1 and 2. This represents a deadlock
41197a3f8ceSart  * (due to C2's blocking attempt to lock byte zero).
41297a3f8ceSart  */
41397a3f8ceSart static int
test6(int fd)41427fff5e2Santon test6(int fd)
41597a3f8ceSart {
41697a3f8ceSart 	/*
41797a3f8ceSart 	 * Because our test relies on the child process being blocked
41897a3f8ceSart 	 * on the parent's lock, we can't easily use a pipe to
41997a3f8ceSart 	 * synchronize so we just sleep in the parent to given the
42097a3f8ceSart 	 * children a chance to setup.
42197a3f8ceSart 	 */
42297a3f8ceSart 	int pid1, pid2;
42397a3f8ceSart 	struct flock fl;
42497a3f8ceSart 	int res;
42597a3f8ceSart 
42697a3f8ceSart 	/*
42797a3f8ceSart 	 * Lock the first byte in the parent.
42897a3f8ceSart 	 */
42997a3f8ceSart 	fl.l_start = 0;
43097a3f8ceSart 	fl.l_len = 1;
43197a3f8ceSart 	fl.l_type = F_WRLCK;
43297a3f8ceSart 	fl.l_whence = SEEK_SET;
43397a3f8ceSart 	if (fcntl(fd, F_SETLK, &fl) < 0)
43497a3f8ceSart 		err(1, "F_SETLK 1 (parent)");
43597a3f8ceSart 
43697a3f8ceSart 	pid1 = fork();
43797a3f8ceSart 	if (pid1 < 0)
43897a3f8ceSart 		err(1, "fork");
43997a3f8ceSart 
44097a3f8ceSart 	if (pid1 == 0) {
44197a3f8ceSart 		/*
44297a3f8ceSart 		 * C1
44397a3f8ceSart 		 * Lock the second byte in the child and then sleep
44497a3f8ceSart 		 */
44597a3f8ceSart 		fl.l_start = 1;
44697a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
44797a3f8ceSart 			err(1, "F_SETLK (child1)");
44897a3f8ceSart 		pause();
44997a3f8ceSart 		exit(0);
45097a3f8ceSart 	}
45197a3f8ceSart 
45297a3f8ceSart 	pid2 = fork();
45397a3f8ceSart 	if (pid2 < 0)
45497a3f8ceSart 		err(1, "fork");
45597a3f8ceSart 
45697a3f8ceSart 	if (pid2 == 0) {
45797a3f8ceSart 		/*
45897a3f8ceSart 		 * C2
45997a3f8ceSart 		 * Lock the third byte in the child and then block on
46097a3f8ceSart 		 * the parent's lock.
46197a3f8ceSart 		 */
46297a3f8ceSart 		fl.l_start = 2;
46397a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
46497a3f8ceSart 			err(1, "F_SETLK (child2)");
46597a3f8ceSart 		fl.l_start = 0;
46697a3f8ceSart 		if (fcntl(fd, F_SETLKW, &fl) < 0)
46797a3f8ceSart 			err(1, "F_SETLKW (child2)");
46897a3f8ceSart 		exit(0);
46997a3f8ceSart 	}
47097a3f8ceSart 
47197a3f8ceSart 	/*
47297a3f8ceSart 	 * Wait until the children have set their locks and then
47397a3f8ceSart 	 * perform the test.
47497a3f8ceSart 	 */
47597a3f8ceSart 	sleep(1);
47697a3f8ceSart 
47797a3f8ceSart 	/*
47897a3f8ceSart 	 * fcntl should immediately return -1 with errno set to
47997a3f8ceSart 	 * EDEADLK. If the alarm fires, we failed to detect the
48097a3f8ceSart 	 * deadlock.
48197a3f8ceSart 	 */
48297a3f8ceSart 	alarm(1);
48397a3f8ceSart 	if (verbose) printf("6 - F_SETLKW complex deadlock: ");
48497a3f8ceSart 
48597a3f8ceSart 	fl.l_start = 1;
48697a3f8ceSart 	fl.l_len = 2;
48797a3f8ceSart 	res = fcntl(fd, F_SETLKW, &fl);
48897a3f8ceSart 	safe_kill(pid1, SIGTERM);
48997a3f8ceSart 	safe_waitpid(pid1);
49097a3f8ceSart 	safe_kill(pid2, SIGTERM);
49197a3f8ceSart 	safe_waitpid(pid2);
49297a3f8ceSart 
49397a3f8ceSart 	fl.l_start = 0;
49497a3f8ceSart 	fl.l_len = 0;
49597a3f8ceSart 	fl.l_type = F_UNLCK;
49697a3f8ceSart 	if (fcntl(fd, F_SETLK, &fl) < 0)
49797a3f8ceSart 		err(1, "F_UNLCK");
49897a3f8ceSart 
49997a3f8ceSart 	FAIL(res == 0);
50097a3f8ceSart 	FAIL(errno != EDEADLK);
50197a3f8ceSart 
50297a3f8ceSart 	/*
50397a3f8ceSart 	 * Cancel the alarm to avoid confusing later tests.
50497a3f8ceSart 	 */
50597a3f8ceSart 	alarm(0);
50697a3f8ceSart 
50797a3f8ceSart 	SUCCEED;
50897a3f8ceSart }
50997a3f8ceSart 
51097a3f8ceSart /*
51197a3f8ceSart  * Test 7 - F_SETLK shared lock on exclusive locked region
51297a3f8ceSart  *
51397a3f8ceSart  * If a shared or exclusive lock cannot be set, fcntl returns
51497a3f8ceSart  * immediately with EACCES or EAGAIN.
51597a3f8ceSart  */
51697a3f8ceSart static int
test7(int fd)51727fff5e2Santon test7(int fd)
51897a3f8ceSart {
51997a3f8ceSart 	/*
52097a3f8ceSart 	 * We create a child process to hold the lock which we will
52197a3f8ceSart 	 * test. We use a pipe to communicate with the child.
52297a3f8ceSart 	 */
52397a3f8ceSart 	int pid;
52497a3f8ceSart 	int pfd[2];
52597a3f8ceSart 	struct flock fl;
52697a3f8ceSart 	char ch;
52797a3f8ceSart 	int res;
52897a3f8ceSart 
52997a3f8ceSart 	if (pipe(pfd) < 0)
53097a3f8ceSart 		err(1, "pipe");
53197a3f8ceSart 
53297a3f8ceSart 	fl.l_start = 0;
53397a3f8ceSart 	fl.l_len = 0;
53497a3f8ceSart 	fl.l_type = F_WRLCK;
53597a3f8ceSart 	fl.l_whence = SEEK_SET;
53697a3f8ceSart 
53797a3f8ceSart 	pid = fork();
53897a3f8ceSart 	if (pid < 0)
53997a3f8ceSart 		err(1, "fork");
54097a3f8ceSart 
54197a3f8ceSart 	if (pid == 0) {
54297a3f8ceSart 		/*
54397a3f8ceSart 		 * We are the child. We set a write lock and then
54497a3f8ceSart 		 * write one byte back to the parent to tell it. The
54597a3f8ceSart 		 * parent will kill us when its done.
54697a3f8ceSart 		 */
54797a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
54897a3f8ceSart 			err(1, "F_SETLK (child)");
54997a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
55097a3f8ceSart 			err(1, "writing to pipe (child)");
55197a3f8ceSart 		pause();
55297a3f8ceSart 		exit(0);
55397a3f8ceSart 	}
55497a3f8ceSart 
55597a3f8ceSart 	/*
55697a3f8ceSart 	 * Wait until the child has set its lock and then perform the
55797a3f8ceSart 	 * test.
55897a3f8ceSart 	 */
55997a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
56097a3f8ceSart 		err(1, "reading from pipe (child)");
56197a3f8ceSart 
56297a3f8ceSart 	/*
56397a3f8ceSart 	 * fcntl should wait until the alarm and then return -1 with
56497a3f8ceSart 	 * errno set to EINTR.
56597a3f8ceSart 	 */
56697a3f8ceSart 	if (verbose) printf("7 - F_SETLK shared lock on exclusive locked region: ");
56797a3f8ceSart 
56897a3f8ceSart 	fl.l_type = F_RDLCK;
56997a3f8ceSart 	res = fcntl(fd, F_SETLK, &fl);
57097a3f8ceSart 	safe_kill(pid, SIGTERM);
57197a3f8ceSart 	safe_waitpid(pid);
57297a3f8ceSart 	close(pfd[0]);
57397a3f8ceSart 	close(pfd[1]);
57497a3f8ceSart 
57597a3f8ceSart 	FAIL(res == 0);
57697a3f8ceSart 	FAIL(errno != EACCES && errno != EAGAIN);
57797a3f8ceSart 
57897a3f8ceSart 	SUCCEED;
57997a3f8ceSart }
58097a3f8ceSart 
58197a3f8ceSart /*
58297a3f8ceSart  * Test 8 - F_SETLK shared lock on share locked region
58397a3f8ceSart  *
58497a3f8ceSart  * When a shared lock is set on a segment of a file, other processes
58597a3f8ceSart  * shall be able to set shared locks on that segment or a portion of
58697a3f8ceSart  * it.
58797a3f8ceSart  */
58897a3f8ceSart static int
test8(int fd)58927fff5e2Santon test8(int fd)
59097a3f8ceSart {
59197a3f8ceSart 	/*
59297a3f8ceSart 	 * We create a child process to hold the lock which we will
59397a3f8ceSart 	 * test. We use a pipe to communicate with the child.
59497a3f8ceSart 	 */
59597a3f8ceSart 	int pid;
59697a3f8ceSart 	int pfd[2];
59797a3f8ceSart 	struct flock fl;
59897a3f8ceSart 	char ch;
59997a3f8ceSart 	int res;
60097a3f8ceSart 
60197a3f8ceSart 	if (pipe(pfd) < 0)
60297a3f8ceSart 		err(1, "pipe");
60397a3f8ceSart 
60497a3f8ceSart 	fl.l_start = 0;
60597a3f8ceSart 	fl.l_len = 0;
60697a3f8ceSart 	fl.l_type = F_RDLCK;
60797a3f8ceSart 	fl.l_whence = SEEK_SET;
60897a3f8ceSart 
60997a3f8ceSart 	pid = fork();
61097a3f8ceSart 	if (pid < 0)
61197a3f8ceSart 		err(1, "fork");
61297a3f8ceSart 
61397a3f8ceSart 	if (pid == 0) {
61497a3f8ceSart 		/*
61597a3f8ceSart 		 * We are the child. We set a write lock and then
61697a3f8ceSart 		 * write one byte back to the parent to tell it. The
61797a3f8ceSart 		 * parent will kill us when its done.
61897a3f8ceSart 		 */
61997a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
62097a3f8ceSart 			err(1, "F_SETLK (child)");
62197a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
62297a3f8ceSart 			err(1, "writing to pipe (child)");
62397a3f8ceSart 		pause();
62497a3f8ceSart 		exit(0);
62597a3f8ceSart 	}
62697a3f8ceSart 
62797a3f8ceSart 	/*
62897a3f8ceSart 	 * Wait until the child has set its lock and then perform the
62997a3f8ceSart 	 * test.
63097a3f8ceSart 	 */
63197a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
63297a3f8ceSart 		err(1, "reading from pipe (child)");
63397a3f8ceSart 
63497a3f8ceSart 	/*
63597a3f8ceSart 	 * fcntl should wait until the alarm and then return -1 with
63697a3f8ceSart 	 * errno set to EINTR.
63797a3f8ceSart 	 */
63897a3f8ceSart 	if (verbose) printf("8 - F_SETLK shared lock on share locked region: ");
63997a3f8ceSart 
64097a3f8ceSart 	fl.l_type = F_RDLCK;
64197a3f8ceSart 	res = fcntl(fd, F_SETLK, &fl);
64297a3f8ceSart 
64397a3f8ceSart 	safe_kill(pid, SIGTERM);
64497a3f8ceSart 	safe_waitpid(pid);
64597a3f8ceSart 	close(pfd[0]);
64697a3f8ceSart 	close(pfd[1]);
64797a3f8ceSart 
64897a3f8ceSart 	fl.l_start = 0;
64997a3f8ceSart 	fl.l_len = 0;
65097a3f8ceSart 	fl.l_type = F_UNLCK;
65197a3f8ceSart 	if (fcntl(fd, F_SETLK, &fl) < 0)
65297a3f8ceSart 		err(1, "F_UNLCK");
65397a3f8ceSart 
65497a3f8ceSart 	FAIL(res != 0);
65597a3f8ceSart 
65697a3f8ceSart 	SUCCEED;
65797a3f8ceSart }
65897a3f8ceSart 
65997a3f8ceSart /*
66097a3f8ceSart  * Test 9 - F_SETLK exclusive lock on share locked region
66197a3f8ceSart  *
66297a3f8ceSart  * If a shared or exclusive lock cannot be set, fcntl returns
66397a3f8ceSart  * immediately with EACCES or EAGAIN.
66497a3f8ceSart  */
66597a3f8ceSart static int
test9(int fd)66627fff5e2Santon test9(int fd)
66797a3f8ceSart {
66897a3f8ceSart 	/*
66997a3f8ceSart 	 * We create a child process to hold the lock which we will
67097a3f8ceSart 	 * test. We use a pipe to communicate with the child.
67197a3f8ceSart 	 */
67297a3f8ceSart 	int pid;
67397a3f8ceSart 	int pfd[2];
67497a3f8ceSart 	struct flock fl;
67597a3f8ceSart 	char ch;
67697a3f8ceSart 	int res;
67797a3f8ceSart 
67897a3f8ceSart 	if (pipe(pfd) < 0)
67997a3f8ceSart 		err(1, "pipe");
68097a3f8ceSart 
68197a3f8ceSart 	fl.l_start = 0;
68297a3f8ceSart 	fl.l_len = 0;
68397a3f8ceSart 	fl.l_type = F_RDLCK;
68497a3f8ceSart 	fl.l_whence = SEEK_SET;
68597a3f8ceSart 
68697a3f8ceSart 	pid = fork();
68797a3f8ceSart 	if (pid < 0)
68897a3f8ceSart 		err(1, "fork");
68997a3f8ceSart 
69097a3f8ceSart 	if (pid == 0) {
69197a3f8ceSart 		/*
69297a3f8ceSart 		 * We are the child. We set a write lock and then
69397a3f8ceSart 		 * write one byte back to the parent to tell it. The
69497a3f8ceSart 		 * parent will kill us when its done.
69597a3f8ceSart 		 */
69697a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
69797a3f8ceSart 			err(1, "F_SETLK (child)");
69897a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
69997a3f8ceSart 			err(1, "writing to pipe (child)");
70097a3f8ceSart 		pause();
70197a3f8ceSart 		exit(0);
70297a3f8ceSart 	}
70397a3f8ceSart 
70497a3f8ceSart 	/*
70597a3f8ceSart 	 * Wait until the child has set its lock and then perform the
70697a3f8ceSart 	 * test.
70797a3f8ceSart 	 */
70897a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
70997a3f8ceSart 		err(1, "reading from pipe (child)");
71097a3f8ceSart 
71197a3f8ceSart 	/*
71297a3f8ceSart 	 * fcntl should wait until the alarm and then return -1 with
71397a3f8ceSart 	 * errno set to EINTR.
71497a3f8ceSart 	 */
71597a3f8ceSart 	if (verbose) printf("9 - F_SETLK exclusive lock on share locked region: ");
71697a3f8ceSart 
71797a3f8ceSart 	fl.l_type = F_WRLCK;
71897a3f8ceSart 	res = fcntl(fd, F_SETLK, &fl);
71997a3f8ceSart 	safe_kill(pid, SIGTERM);
72097a3f8ceSart 	safe_waitpid(pid);
72197a3f8ceSart 	close(pfd[0]);
72297a3f8ceSart 	close(pfd[1]);
72397a3f8ceSart 
72497a3f8ceSart 	FAIL(res == 0);
72597a3f8ceSart 	FAIL(errno != EACCES && errno != EAGAIN);
72697a3f8ceSart 
72797a3f8ceSart 	SUCCEED;
72897a3f8ceSart }
72997a3f8ceSart 
73097a3f8ceSart /*
73197a3f8ceSart  * Test 10 - trying to set bogus pid or sysid values
73297a3f8ceSart  *
73397a3f8ceSart  * The l_pid and l_sysid fields are only used with F_GETLK to return
73497a3f8ceSart  * the process ID of the process holding a blocking lock and the
73597a3f8ceSart  * system ID of the system that owns that process
73697a3f8ceSart  */
73797a3f8ceSart static int
test10(int fd)73827fff5e2Santon test10(int fd)
73997a3f8ceSart {
74097a3f8ceSart 	/*
74197a3f8ceSart 	 * We create a child process to hold the lock which we will
74297a3f8ceSart 	 * test. We use a pipe to communicate with the child.
74397a3f8ceSart 	 */
74497a3f8ceSart 	int pid;
74597a3f8ceSart 	int pfd[2];
74697a3f8ceSart 	struct flock fl;
74797a3f8ceSart 	char ch;
74897a3f8ceSart 
74997a3f8ceSart 	if (pipe(pfd) < 0)
75097a3f8ceSart 		err(1, "pipe");
75197a3f8ceSart 
75297a3f8ceSart 	fl.l_start = 0;
75397a3f8ceSart 	fl.l_len = 0;
75497a3f8ceSart 	fl.l_type = F_WRLCK;
75597a3f8ceSart 	fl.l_whence = SEEK_SET;
75697a3f8ceSart 	fl.l_pid = 9999;
75797a3f8ceSart 
75897a3f8ceSart 	pid = fork();
75997a3f8ceSart 	if (pid < 0)
76097a3f8ceSart 		err(1, "fork");
76197a3f8ceSart 
76297a3f8ceSart 	if (pid == 0) {
76397a3f8ceSart 		/*
76497a3f8ceSart 		 * We are the child. We set a write lock and then
76597a3f8ceSart 		 * write one byte back to the parent to tell it. The
76697a3f8ceSart 		 * parent will kill us when its done.
76797a3f8ceSart 		 */
76897a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
76997a3f8ceSart 			err(1, "F_SETLK (child)");
77097a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
77197a3f8ceSart 			err(1, "writing to pipe (child)");
77297a3f8ceSart 		pause();
77397a3f8ceSart 		exit(0);
77497a3f8ceSart 	}
77597a3f8ceSart 
77697a3f8ceSart 	/*
77797a3f8ceSart 	 * Wait until the child has set its lock and then perform the
77897a3f8ceSart 	 * test.
77997a3f8ceSart 	 */
78097a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
78197a3f8ceSart 		err(1, "reading from pipe (child)");
78297a3f8ceSart 
78397a3f8ceSart 	if (verbose) printf("10 - trying to set bogus pid or sysid values: ");
78497a3f8ceSart 
78597a3f8ceSart 	if (fcntl(fd, F_GETLK, &fl) < 0)
78697a3f8ceSart 		err(1, "F_GETLK");
78797a3f8ceSart 
78897a3f8ceSart 	safe_kill(pid, SIGTERM);
78997a3f8ceSart 	safe_waitpid(pid);
79097a3f8ceSart 	close(pfd[0]);
79197a3f8ceSart 	close(pfd[1]);
79297a3f8ceSart 
79397a3f8ceSart 	FAIL(fl.l_pid != pid);
79497a3f8ceSart 
79597a3f8ceSart 	SUCCEED;
79697a3f8ceSart }
79797a3f8ceSart 
79897a3f8ceSart /*
79997a3f8ceSart  * Test 11 - remote locks
80097a3f8ceSart  *
80197a3f8ceSart  * XXX temporary interface which will be removed when the kernel lockd
80297a3f8ceSart  * is added.
80397a3f8ceSart  */
80497a3f8ceSart static int
test11(int fd)80527fff5e2Santon test11(int fd)
80697a3f8ceSart {
80797a3f8ceSart #ifdef F_SETLK_REMOTE
80897a3f8ceSart 	struct flock fl;
80997a3f8ceSart 	int res;
81097a3f8ceSart 
81197a3f8ceSart 	if (geteuid() != 0)
81297a3f8ceSart 		return 0;
81397a3f8ceSart 
81497a3f8ceSart 	fl.l_start = 0;
81597a3f8ceSart 	fl.l_len = 0;
81697a3f8ceSart 	fl.l_type = F_WRLCK;
81797a3f8ceSart 	fl.l_whence = SEEK_SET;
81897a3f8ceSart 	fl.l_pid = 9999;
81997a3f8ceSart 	fl.l_sysid = 1001;
82097a3f8ceSart 
82197a3f8ceSart 	if (verbose) printf("11 - remote locks: ");
82297a3f8ceSart 
82397a3f8ceSart 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
82497a3f8ceSart 	FAIL(res != 0);
82597a3f8ceSart 
82697a3f8ceSart 	fl.l_sysid = 1002;
82797a3f8ceSart 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
82897a3f8ceSart 	FAIL(res == 0);
82997a3f8ceSart 	FAIL(errno != EACCES && errno != EAGAIN);
83097a3f8ceSart 
83197a3f8ceSart 	res = fcntl(fd, F_GETLK, &fl);
83297a3f8ceSart 	FAIL(res != 0);
83397a3f8ceSart 	FAIL(fl.l_pid != 9999);
83497a3f8ceSart 	FAIL(fl.l_sysid != 1001);
83597a3f8ceSart 
83697a3f8ceSart 	fl.l_type = F_UNLCK;
83797a3f8ceSart 	fl.l_sysid = 1001;
83897a3f8ceSart 	fl.l_start = 0;
83997a3f8ceSart 	fl.l_len = 0;
84097a3f8ceSart 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
84197a3f8ceSart 	FAIL(res != 0);
84297a3f8ceSart 
84397a3f8ceSart 	fl.l_pid = 1234;
84497a3f8ceSart 	fl.l_sysid = 1001;
84597a3f8ceSart 	fl.l_start = 0;
84697a3f8ceSart 	fl.l_len = 1;
84797a3f8ceSart 	fl.l_whence = SEEK_SET;
84897a3f8ceSart 	fl.l_type = F_RDLCK;
84997a3f8ceSart 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
85097a3f8ceSart 	FAIL(res != 0);
85197a3f8ceSart 
85297a3f8ceSart 	fl.l_sysid = 1002;
85397a3f8ceSart 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
85497a3f8ceSart 	FAIL(res != 0);
85597a3f8ceSart 
85697a3f8ceSart 	fl.l_type = F_UNLCKSYS;
85797a3f8ceSart 	fl.l_sysid = 1001;
85897a3f8ceSart 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
85997a3f8ceSart 	FAIL(res != 0);
86097a3f8ceSart 
86197a3f8ceSart 	fl.l_type = F_WRLCK;
86297a3f8ceSart 	res = fcntl(fd, F_GETLK, &fl);
86397a3f8ceSart 	FAIL(res != 0);
86497a3f8ceSart 	FAIL(fl.l_pid != 1234);
86597a3f8ceSart 	FAIL(fl.l_sysid != 1002);
86697a3f8ceSart 
86797a3f8ceSart 	fl.l_type = F_UNLCKSYS;
86897a3f8ceSart 	fl.l_sysid = 1002;
86997a3f8ceSart 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
87097a3f8ceSart 	FAIL(res != 0);
87197a3f8ceSart 
87297a3f8ceSart 	SUCCEED;
87397a3f8ceSart #else
87497a3f8ceSart 	return 0;
87597a3f8ceSart #endif
87697a3f8ceSart }
87797a3f8ceSart 
87897a3f8ceSart /*
87997a3f8ceSart  * Test 12 - F_SETLKW on locked region which is then unlocked
88097a3f8ceSart  *
88197a3f8ceSart  * If a shared or exclusive lock is blocked by other locks, the
88297a3f8ceSart  * process waits until the request can be satisfied.
88397a3f8ceSart  */
88497a3f8ceSart static int
test12(int fd)88527fff5e2Santon test12(int fd)
88697a3f8ceSart {
88797a3f8ceSart 	/*
88897a3f8ceSart 	 * We create a child process to hold the lock which we will
88997a3f8ceSart 	 * test. We use a pipe to communicate with the child.
89097a3f8ceSart 	 */
89197a3f8ceSart 	int pid;
89297a3f8ceSart 	int pfd[2];
89397a3f8ceSart 	struct flock fl;
89497a3f8ceSart 	char ch;
89597a3f8ceSart 	int res;
89697a3f8ceSart 
89797a3f8ceSart 	if (pipe(pfd) < 0)
89897a3f8ceSart 		err(1, "pipe");
89997a3f8ceSart 
90097a3f8ceSart 	fl.l_start = 0;
90197a3f8ceSart 	fl.l_len = 0;
90297a3f8ceSart 	fl.l_type = F_WRLCK;
90397a3f8ceSart 	fl.l_whence = SEEK_SET;
90497a3f8ceSart 
90597a3f8ceSart 	pid = fork();
90697a3f8ceSart 	if (pid < 0)
90797a3f8ceSart 		err(1, "fork");
90897a3f8ceSart 
90997a3f8ceSart 	if (pid == 0) {
91097a3f8ceSart 		/*
91197a3f8ceSart 		 * We are the child. We set a write lock and then
91297a3f8ceSart 		 * write one byte back to the parent to tell it. The
91397a3f8ceSart 		 * parent will kill us when its done.
91497a3f8ceSart 		 */
91597a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
91697a3f8ceSart 			err(1, "F_SETLK (child)");
91797a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
91897a3f8ceSart 			err(1, "writing to pipe (child)");
91997a3f8ceSart 
92097a3f8ceSart 		sleep(1);
92197a3f8ceSart 		exit(0);
92297a3f8ceSart 	}
92397a3f8ceSart 
92497a3f8ceSart 	/*
92597a3f8ceSart 	 * Wait until the child has set its lock and then perform the
92697a3f8ceSart 	 * test.
92797a3f8ceSart 	 */
92897a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
92997a3f8ceSart 		err(1, "reading from pipe (child)");
93097a3f8ceSart 
93197a3f8ceSart 	/*
93297a3f8ceSart 	 * fcntl should wait until the alarm and then return -1 with
93397a3f8ceSart 	 * errno set to EINTR.
93497a3f8ceSart 	 */
93597a3f8ceSart 	if (verbose) printf("12 - F_SETLKW on locked region which is then unlocked: ");
93697a3f8ceSart 
93797a3f8ceSart 	//alarm(1);
93897a3f8ceSart 
93997a3f8ceSart 	res = fcntl(fd, F_SETLKW, &fl);
94097a3f8ceSart 	safe_kill(pid, SIGTERM);
94197a3f8ceSart 	safe_waitpid(pid);
94297a3f8ceSart 	close(pfd[0]);
94397a3f8ceSart 	close(pfd[1]);
94497a3f8ceSart 	FAIL(res != 0);
94597a3f8ceSart 
94697a3f8ceSart 	fl.l_start = 0;
94797a3f8ceSart 	fl.l_len = 0;
94897a3f8ceSart 	fl.l_type = F_UNLCK;
94997a3f8ceSart 	if (fcntl(fd, F_SETLK, &fl) < 0)
95097a3f8ceSart 		err(1, "F_UNLCK");
95197a3f8ceSart 
95297a3f8ceSart 	SUCCEED;
95397a3f8ceSart }
95497a3f8ceSart 
95597a3f8ceSart /*
95697a3f8ceSart  * Test 13 - F_SETLKW on locked region, race with owner
95797a3f8ceSart  *
95897a3f8ceSart  * If a shared or exclusive lock is blocked by other locks, the
95997a3f8ceSart  * process waits until the request can be satisfied.
96097a3f8ceSart  */
96197a3f8ceSart static int
test13(int fd)96227fff5e2Santon test13(int fd)
96397a3f8ceSart {
96497a3f8ceSart 	/*
96597a3f8ceSart 	 * We create a child process to hold the lock which we will
96697a3f8ceSart 	 * test. We use a pipe to communicate with the child.
96797a3f8ceSart 	 */
96897a3f8ceSart 	int i;
96997a3f8ceSart 	int pid;
97097a3f8ceSart 	int pfd[2];
97197a3f8ceSart 	struct flock fl;
97297a3f8ceSart 	char ch;
97397a3f8ceSart 	int res;
97497a3f8ceSart 	struct itimerval itv;
97597a3f8ceSart 
97697a3f8ceSart 	if (verbose) printf("13 - F_SETLKW on locked region, race with owner: ");
97797a3f8ceSart 	fflush(stdout);
97897a3f8ceSart 
97997a3f8ceSart 	for (i = 0; i < 100; i++) {
98097a3f8ceSart 		if (pipe(pfd) < 0)
98197a3f8ceSart 			err(1, "pipe");
98297a3f8ceSart 
98397a3f8ceSart 		fl.l_start = 0;
98497a3f8ceSart 		fl.l_len = 0;
98597a3f8ceSart 		fl.l_type = F_WRLCK;
98697a3f8ceSart 		fl.l_whence = SEEK_SET;
98797a3f8ceSart 
98897a3f8ceSart 		pid = fork();
98997a3f8ceSart 		if (pid < 0)
99097a3f8ceSart 			err(1, "fork");
99197a3f8ceSart 
99297a3f8ceSart 		if (pid == 0) {
99397a3f8ceSart 			/*
99497a3f8ceSart 			 * We are the child. We set a write lock and then
99597a3f8ceSart 			 * write one byte back to the parent to tell it. The
99697a3f8ceSart 			 * parent will kill us when its done.
99797a3f8ceSart 			 */
99897a3f8ceSart 			if (fcntl(fd, F_SETLK, &fl) < 0)
99997a3f8ceSart 				err(1, "F_SETLK (child)");
100097a3f8ceSart 			if (write(pfd[1], "a", 1) < 0)
100197a3f8ceSart 				err(1, "writing to pipe (child)");
100297a3f8ceSart 
100397a3f8ceSart 			sleep(1);
100497a3f8ceSart 			exit(0);
100597a3f8ceSart 		}
100697a3f8ceSart 
100797a3f8ceSart 		/*
100897a3f8ceSart 		 * Wait until the child has set its lock and then perform the
100997a3f8ceSart 		 * test.
101097a3f8ceSart 		 */
101197a3f8ceSart 		while (read(pfd[0], &ch, 1) != 1) {
101297a3f8ceSart 			if (errno == EINTR)
101397a3f8ceSart 				continue;
101497a3f8ceSart 			err(1, "reading from pipe (child)");
101597a3f8ceSart 		}
101697a3f8ceSart 
101797a3f8ceSart 		/*
101897a3f8ceSart 		 * fcntl should wait until the alarm and then return -1 with
101997a3f8ceSart 		 * errno set to EINTR.
102097a3f8ceSart 		 */
102197a3f8ceSart 		itv.it_interval.tv_sec = 0;
102297a3f8ceSart 		itv.it_interval.tv_usec = 0;
102397a3f8ceSart 		itv.it_value.tv_sec = 0;
102497a3f8ceSart 		itv.it_value.tv_usec = 2;
102597a3f8ceSart 		setitimer(ITIMER_REAL, &itv, NULL);
102697a3f8ceSart 
102797a3f8ceSart 		res = fcntl(fd, F_SETLKW, &fl);
102897a3f8ceSart 		safe_kill(pid, SIGTERM);
102997a3f8ceSart 		safe_waitpid(pid);
103097a3f8ceSart 		close(pfd[0]);
103197a3f8ceSart 		close(pfd[1]);
103297a3f8ceSart 		FAIL(!(res == 0 || (res == -1 && errno == EINTR)));
103397a3f8ceSart 
103497a3f8ceSart 		fl.l_start = 0;
103597a3f8ceSart 		fl.l_len = 0;
103697a3f8ceSart 		fl.l_type = F_UNLCK;
103797a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
103897a3f8ceSart 			err(1, "F_UNLCK");
103997a3f8ceSart 	}
104097a3f8ceSart 	SUCCEED;
104197a3f8ceSart }
104297a3f8ceSart 
104397a3f8ceSart /*
104497a3f8ceSart  * Test 14 - soak test
104597a3f8ceSart  */
104697a3f8ceSart static int
test14(int fd)104727fff5e2Santon test14(int fd)
104897a3f8ceSart {
104997a3f8ceSart #define CHILD_COUNT 20
105097a3f8ceSart 	/*
105197a3f8ceSart 	 * We create a set of child processes and let each one run
105297a3f8ceSart 	 * through a random sequence of locks and unlocks.
105397a3f8ceSart 	 */
105427fff5e2Santon 	int i, j, id;
105597a3f8ceSart 	int pids[CHILD_COUNT], pid;
105697a3f8ceSart 	char buf[128];
105797a3f8ceSart 	char tbuf[128];
105897a3f8ceSart 	int map[128];
105997a3f8ceSart 	char outbuf[512];
106097a3f8ceSart 	struct flock fl;
106197a3f8ceSart 	struct itimerval itv;
106297a3f8ceSart 	int status;
106327fff5e2Santon 	int id_base = 0;
106497a3f8ceSart 
106597a3f8ceSart 	if (verbose) printf("14 - soak test: ");
106697a3f8ceSart 	fflush(stdout);
106797a3f8ceSart 
106897a3f8ceSart 	for (i = 0; i < 128; i++)
106997a3f8ceSart 		map[i] = F_UNLCK;
107097a3f8ceSart 
107197a3f8ceSart 	for (i = 0; i < CHILD_COUNT; i++) {
107297a3f8ceSart 
107397a3f8ceSart 		pid = fork();
107497a3f8ceSart 		if (pid < 0)
107597a3f8ceSart 			err(1, "fork");
107697a3f8ceSart 		if (pid) {
107797a3f8ceSart 			/*
107897a3f8ceSart 			 * Parent - record the pid and continue.
107997a3f8ceSart 			 */
108097a3f8ceSart 			pids[i] = pid;
108197a3f8ceSart 			continue;
108297a3f8ceSart 		}
108397a3f8ceSart 
108497a3f8ceSart 		/*
108597a3f8ceSart 		 * Child - do some work and exit.
108697a3f8ceSart 		 */
108797a3f8ceSart 		id = id_base + i;
108897a3f8ceSart 		for (j = 0; j < 50; j++) {
108997a3f8ceSart 			int start, end, len;
109097a3f8ceSart 			int set, wrlock;
109197a3f8ceSart 
109297a3f8ceSart 			do {
1093dc4e3d0aSjsing 				start = arc4random_uniform(128);
1094dc4e3d0aSjsing 				end = arc4random_uniform(128);
109597a3f8ceSart 			} while (end <= start);
109697a3f8ceSart 
1097dc4e3d0aSjsing 			set = arc4random_uniform(2);
1098dc4e3d0aSjsing 			wrlock = arc4random_uniform(2);
109997a3f8ceSart 
110097a3f8ceSart 			len = end - start;
110197a3f8ceSart 			fl.l_start = start;
110297a3f8ceSart 			fl.l_len = len;
110397a3f8ceSart 			fl.l_whence = SEEK_SET;
110497a3f8ceSart 			if (set)
110597a3f8ceSart 				fl.l_type = wrlock ? F_WRLCK : F_RDLCK;
110697a3f8ceSart 			else
110797a3f8ceSart 				fl.l_type = F_UNLCK;
110897a3f8ceSart 
110997a3f8ceSart 			itv.it_interval.tv_sec = 0;
111097a3f8ceSart 			itv.it_interval.tv_usec = 0;
111197a3f8ceSart 			itv.it_value.tv_sec = 0;
111297a3f8ceSart 			itv.it_value.tv_usec = 3000;
111397a3f8ceSart 			setitimer(ITIMER_REAL, &itv, NULL);
111497a3f8ceSart 
111597a3f8ceSart 			if (fcntl(fd, F_SETLKW, &fl) < 0) {
111697a3f8ceSart 				if (errno == EDEADLK || errno == EINTR) {
111797a3f8ceSart 					if (verbose) {
111897a3f8ceSart 						snprintf(outbuf, sizeof(outbuf),
111997a3f8ceSart 						    "%d[%d]: %s [%d .. %d] %s\n",
112097a3f8ceSart 						    id, j,
112197a3f8ceSart 						    set ? (wrlock ? "write lock"
112297a3f8ceSart 							: "read lock")
112397a3f8ceSart 						    : "unlock", start, end,
112497a3f8ceSart 						    errno == EDEADLK
112597a3f8ceSart 						    ? "deadlock"
112697a3f8ceSart 						    : "interrupted");
112797a3f8ceSart 						write(1, outbuf,
112897a3f8ceSart 						    strlen(outbuf));
112997a3f8ceSart 					}
113097a3f8ceSart 					continue;
113197a3f8ceSart 				} else {
113297a3f8ceSart 					perror("fcntl");
113397a3f8ceSart 				}
113497a3f8ceSart 			}
113597a3f8ceSart 
113697a3f8ceSart 			itv.it_interval.tv_sec = 0;
113797a3f8ceSart 			itv.it_interval.tv_usec = 0;
113897a3f8ceSart 			itv.it_value.tv_sec = 0;
113997a3f8ceSart 			itv.it_value.tv_usec = 0;
114097a3f8ceSart 			setitimer(ITIMER_REAL, &itv, NULL);
114197a3f8ceSart 
114297a3f8ceSart 			if (verbose) {
114397a3f8ceSart 				snprintf(outbuf, sizeof(outbuf),
114497a3f8ceSart 				    "%d[%d]: %s [%d .. %d] succeeded\n",
114597a3f8ceSart 				    id, j,
114697a3f8ceSart 				    set ? (wrlock ? "write lock" : "read lock")
114797a3f8ceSart 				    : "unlock", start, end);
114897a3f8ceSart 				write(1, outbuf, strlen(outbuf));
114997a3f8ceSart 			}
115097a3f8ceSart 
115197a3f8ceSart 			if (set) {
115297a3f8ceSart 				if (wrlock) {
115397a3f8ceSart 					/*
115497a3f8ceSart 					 * We got a write lock - write
115597a3f8ceSart 					 * our ID to each byte that we
115697a3f8ceSart 					 * managed to claim.
115797a3f8ceSart 					 */
115897a3f8ceSart 					for (i = start; i < end; i++)
115997a3f8ceSart 						map[i] = F_WRLCK;
116097a3f8ceSart 					memset(&buf[start], id, len);
116197a3f8ceSart 					if (pwrite(fd, &buf[start], len,
116297a3f8ceSart 						start) != len) {
116397a3f8ceSart 						printf("%d: short write\n", id);
116497a3f8ceSart 						exit(1);
116597a3f8ceSart 					}
116697a3f8ceSart 				} else {
116797a3f8ceSart 					/*
116897a3f8ceSart 					 * We got a read lock - read
116997a3f8ceSart 					 * the bytes which we claimed
117097a3f8ceSart 					 * so that we can check that
117197a3f8ceSart 					 * they don't change
117297a3f8ceSart 					 * unexpectedly.
117397a3f8ceSart 					 */
117497a3f8ceSart 					for (i = start; i < end; i++)
117597a3f8ceSart 						map[i] = F_RDLCK;
117697a3f8ceSart 					if (pread(fd, &buf[start], len,
117797a3f8ceSart 						start) != len) {
117897a3f8ceSart 						printf("%d: short read\n", id);
117997a3f8ceSart 						exit(1);
118097a3f8ceSart 					}
118197a3f8ceSart 				}
118297a3f8ceSart 			} else {
118397a3f8ceSart 				for (i = start; i < end; i++)
118497a3f8ceSart 					map[i] = F_UNLCK;
118597a3f8ceSart 			}
118697a3f8ceSart 
118797a3f8ceSart 			usleep(1000);
118897a3f8ceSart 
118997a3f8ceSart 			/*
119097a3f8ceSart 			 * Read back the whole region so that we can
119197a3f8ceSart 			 * check that all the bytes we have some kind
119297a3f8ceSart 			 * of claim to have the correct value.
119397a3f8ceSart 			 */
119497a3f8ceSart 			if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) {
119597a3f8ceSart 				printf("%d: short read\n", id);
119697a3f8ceSart 				exit(1);
119797a3f8ceSart 			}
119897a3f8ceSart 
119997a3f8ceSart 			for (i = 0; i < 128; i++) {
120097a3f8ceSart 				if (map[i] != F_UNLCK && buf[i] != tbuf[i]) {
120197a3f8ceSart 					snprintf(outbuf, sizeof(outbuf),
120297a3f8ceSart 					    "%d: byte %d expected %d, "
120397a3f8ceSart 					    "got %d\n", id, i, buf[i], tbuf[i]);
120497a3f8ceSart 					write(1, outbuf, strlen(outbuf));
120597a3f8ceSart 					exit(1);
120697a3f8ceSart 				}
120797a3f8ceSart 			}
120897a3f8ceSart 		}
120997a3f8ceSart 		if (verbose)
121097a3f8ceSart 			printf("%d[%d]: done\n", id, j);
121197a3f8ceSart 
121297a3f8ceSart 		exit(0);
121397a3f8ceSart 	}
121497a3f8ceSart 
121597a3f8ceSart 	status = 0;
121697a3f8ceSart 	for (i = 0; i < CHILD_COUNT; i++) {
121797a3f8ceSart 		status += safe_waitpid(pids[i]);
121897a3f8ceSart 	}
121997a3f8ceSart 	if (status)
122097a3f8ceSart 		FAIL(status != 0);
122197a3f8ceSart 
122297a3f8ceSart 	SUCCEED;
122397a3f8ceSart }
122497a3f8ceSart 
122597a3f8ceSart /*
122697a3f8ceSart  * Test 15 - flock(2) semantcs
122797a3f8ceSart  *
122897a3f8ceSart  * When a lock holder has a shared lock and attempts to upgrade that
122997a3f8ceSart  * shared lock to exclusive, it must drop the shared lock before
123097a3f8ceSart  * blocking on the exclusive lock.
123197a3f8ceSart  *
123297a3f8ceSart  * To test this, we first arrange for two shared locks on the file,
123397a3f8ceSart  * and then attempt to upgrade one of them to exclusive. This should
123497a3f8ceSart  * drop one of the shared locks and block. We interrupt the blocking
123597a3f8ceSart  * lock request and examine the lock state of the file after dropping
123697a3f8ceSart  * the other shared lock - there should be no active locks at this
123797a3f8ceSart  * point.
123897a3f8ceSart  */
123997a3f8ceSart static int
test15(int fd)124027fff5e2Santon test15(int fd)
124197a3f8ceSart {
124297a3f8ceSart #ifdef LOCK_EX
124397a3f8ceSart 	/*
124497a3f8ceSart 	 * We create a child process to hold the lock which we will
124597a3f8ceSart 	 * test. We use a pipe to communicate with the child.
124697a3f8ceSart 	 *
124797a3f8ceSart 	 * Since we only have one file descriptors and lock ownership
124897a3f8ceSart 	 * for flock(2) goes with the file descriptor, we use fcntl to
124997a3f8ceSart 	 * set the child's shared lock.
125097a3f8ceSart 	 */
125197a3f8ceSart 	int pid;
125297a3f8ceSart 	int pfd[2];
125397a3f8ceSart 	int fd2;
125497a3f8ceSart 	struct flock fl;
125597a3f8ceSart 	char ch;
125697a3f8ceSart 	int res;
125797a3f8ceSart 
125897a3f8ceSart 	if (pipe(pfd) < 0)
125997a3f8ceSart 		err(1, "pipe");
126097a3f8ceSart 
126197a3f8ceSart 	pid = fork();
126297a3f8ceSart 	if (pid < 0)
126397a3f8ceSart 		err(1, "fork");
126497a3f8ceSart 
126597a3f8ceSart 	if (pid == 0) {
126697a3f8ceSart 		/*
126797a3f8ceSart 		 * We are the child. We set a shared lock and then
126897a3f8ceSart 		 * write one byte back to the parent to tell it. The
126997a3f8ceSart 		 * parent will kill us when its done.
127097a3f8ceSart 		 */
127197a3f8ceSart 		fl.l_start = 0;
127297a3f8ceSart 		fl.l_len = 0;
127397a3f8ceSart 		fl.l_type = F_RDLCK;
127497a3f8ceSart 		fl.l_whence = SEEK_SET;
127597a3f8ceSart 		if (fcntl(fd, F_SETLK, &fl) < 0)
127697a3f8ceSart 			err(1, "fcntl(F_SETLK) (child)");
127797a3f8ceSart 		if (write(pfd[1], "a", 1) < 0)
127897a3f8ceSart 			err(1, "writing to pipe (child)");
127997a3f8ceSart 		pause();
128097a3f8ceSart 		exit(0);
128197a3f8ceSart 	}
128297a3f8ceSart 
128397a3f8ceSart 	/*
128497a3f8ceSart 	 * Wait until the child has set its lock and then perform the
128597a3f8ceSart 	 * test.
128697a3f8ceSart 	 */
128797a3f8ceSart 	if (read(pfd[0], &ch, 1) != 1)
128897a3f8ceSart 		err(1, "reading from pipe (child)");
128997a3f8ceSart 
129097a3f8ceSart 	fd2 = dup(fd);
1291c8db1e5aSanton 	FAIL(fd2 == -1);
129297a3f8ceSart 	if (flock(fd, LOCK_SH) < 0)
129397a3f8ceSart 		err(1, "flock shared");
129497a3f8ceSart 
129597a3f8ceSart 	/*
129697a3f8ceSart 	 * flock should wait until the alarm and then return -1 with
129797a3f8ceSart 	 * errno set to EINTR.
129897a3f8ceSart 	 */
129997a3f8ceSart 	if (verbose) printf("15 - flock(2) semantics: ");
130097a3f8ceSart 
130197a3f8ceSart 	alarm(1);
130297a3f8ceSart 	flock(fd, LOCK_EX);
130397a3f8ceSart 
130497a3f8ceSart 	/*
130597a3f8ceSart 	 * Kill the child to force it to drop its locks.
130697a3f8ceSart 	 */
130797a3f8ceSart 	safe_kill(pid, SIGTERM);
130897a3f8ceSart 	safe_waitpid(pid);
130997a3f8ceSart 
131097a3f8ceSart 	fl.l_start = 0;
131197a3f8ceSart 	fl.l_len = 0;
131297a3f8ceSart 	fl.l_type = F_WRLCK;
131397a3f8ceSart 	fl.l_whence = SEEK_SET;
131497a3f8ceSart 	res = fcntl(fd, F_GETLK, &fl);
131597a3f8ceSart 
131697a3f8ceSart 	close(pfd[0]);
131797a3f8ceSart 	close(pfd[1]);
131897a3f8ceSart 	FAIL(res != 0);
131997a3f8ceSart 	FAIL(fl.l_type != F_UNLCK);
132097a3f8ceSart 
132197a3f8ceSart 	SUCCEED;
132297a3f8ceSart #else
132397a3f8ceSart 	return 0;
132497a3f8ceSart #endif
132597a3f8ceSart }
132697a3f8ceSart 
1327bb03833fSanton /*
1328bb03833fSanton  * Test 16 - double free regression
13290d5ae59dSanton  *
13300d5ae59dSanton  * Not applicable anymore due to stricter bounds validation.
1331bb03833fSanton  */
1332bb03833fSanton static int
test16(int fd)133327fff5e2Santon test16(int fd)
1334bb03833fSanton {
13350d5ae59dSanton #if 0
1336bb03833fSanton 	struct flock fl;
1337bb03833fSanton 	int res;
1338bb03833fSanton 
1339bb03833fSanton 	fl.l_pid = 0;
1340bb03833fSanton 	fl.l_type = 1;
1341bb03833fSanton 	fl.l_whence = 0;
1342bb03833fSanton 
1343bb03833fSanton 	fl.l_start = 0;
1344bb03833fSanton 	fl.l_len = 0x8000000000000000;
1345bb03833fSanton 	res = fcntl(fd, F_SETLK, &fl);
1346bb03833fSanton 	FAIL(res != 0);
1347bb03833fSanton 
1348bb03833fSanton 	fl.l_start = 0x10000;
1349bb03833fSanton 	fl.l_len = 0;
1350bb03833fSanton 	res = fcntl(fd, F_SETLK, &fl);
1351bb03833fSanton 	FAIL(res != 0);
1352bb03833fSanton 
1353bb03833fSanton 	fl.l_start = 0;
1354bb03833fSanton 	fl.l_len = 0x8000000000000000;
1355bb03833fSanton 	res = fcntl(fd, F_SETLK, &fl);
1356bb03833fSanton 	FAIL(res != 0);
1357bb03833fSanton 
1358bb03833fSanton 	fl.l_start = 0x10000;
1359bb03833fSanton 	fl.l_len = 0;
1360bb03833fSanton 	res = fcntl(fd, F_SETLK, &fl);
1361bb03833fSanton 	FAIL(res != 0);
13620d5ae59dSanton #endif
1363bb03833fSanton 
1364bb03833fSanton 	SUCCEED;
1365bb03833fSanton }
1366bb03833fSanton 
13679f8d2875Santon /*
13689f8d2875Santon  * Test 17 - lf_findoverlap() case 0
13699f8d2875Santon  *
13709f8d2875Santon  * No overlap.
13719f8d2875Santon  */
13729f8d2875Santon static int
test17(int fd)137327fff5e2Santon test17(int fd)
13749f8d2875Santon {
13759f8d2875Santon 	struct flock fl;
13769f8d2875Santon 	int nfd, res;
13779f8d2875Santon 
13789f8d2875Santon 	/* First lock. */
13799f8d2875Santon 	{
13809f8d2875Santon 		nfd = dup(fd);
13819f8d2875Santon 		FAIL(nfd == -1);
13829f8d2875Santon 
13839f8d2875Santon 		fl.l_start = 0;
13849f8d2875Santon 		fl.l_len = 100;
13859f8d2875Santon 		fl.l_pid = 0;
13869f8d2875Santon 		fl.l_type = F_RDLCK;
13879f8d2875Santon 		fl.l_whence = 0;
13889f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
13899f8d2875Santon 		FAIL(res != 0);
13909f8d2875Santon 
13919f8d2875Santon 		close(nfd);
13929f8d2875Santon 	}
13939f8d2875Santon 
13949f8d2875Santon 	/* Insert at end. */
13959f8d2875Santon 	{
13969f8d2875Santon 		nfd = dup(fd);
13979f8d2875Santon 		FAIL(nfd == -1);
13989f8d2875Santon 
13999f8d2875Santon 		fl.l_start = 100;
14009f8d2875Santon 		fl.l_len = 100;
14019f8d2875Santon 		fl.l_pid = 0;
14029f8d2875Santon 		fl.l_type = F_RDLCK;
14039f8d2875Santon 		fl.l_whence = 0;
14049f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
14059f8d2875Santon 		FAIL(res != 0);
14069f8d2875Santon 
14079f8d2875Santon 		fl.l_start = 200;
14089f8d2875Santon 		fl.l_len = 100;
14099f8d2875Santon 		fl.l_pid = 0;
14109f8d2875Santon 		fl.l_type = F_RDLCK;
14119f8d2875Santon 		fl.l_whence = 0;
14129f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
14139f8d2875Santon 		FAIL(res != 0);
14149f8d2875Santon 
14159f8d2875Santon 		close(nfd);
14169f8d2875Santon 	}
14179f8d2875Santon 
14189f8d2875Santon 	/* Insert before overlap. */
14199f8d2875Santon 	{
14209f8d2875Santon 		nfd = dup(fd);
14219f8d2875Santon 		FAIL(nfd == -1);
14229f8d2875Santon 
14239f8d2875Santon 		fl.l_start = 300;
14249f8d2875Santon 		fl.l_len = 100;
14259f8d2875Santon 		fl.l_pid = 0;
14269f8d2875Santon 		fl.l_type = F_RDLCK;
14279f8d2875Santon 		fl.l_whence = 0;
14289f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
14299f8d2875Santon 		FAIL(res != 0);
14309f8d2875Santon 
14319f8d2875Santon 		fl.l_start = 500;
14329f8d2875Santon 		fl.l_len = 100;
14339f8d2875Santon 		fl.l_pid = 0;
14349f8d2875Santon 		fl.l_type = F_RDLCK;
14359f8d2875Santon 		fl.l_whence = 0;
14369f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
14379f8d2875Santon 		FAIL(res != 0);
14389f8d2875Santon 
14399f8d2875Santon 		fl.l_start = 400;
14409f8d2875Santon 		fl.l_len = 100;
14419f8d2875Santon 		fl.l_pid = 0;
14429f8d2875Santon 		fl.l_type = F_RDLCK;
14439f8d2875Santon 		fl.l_whence = 0;
14449f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
14459f8d2875Santon 		FAIL(res != 0);
14469f8d2875Santon 
14479f8d2875Santon 		close(nfd);
14489f8d2875Santon 	}
14499f8d2875Santon 
14509f8d2875Santon 	SUCCEED;
14519f8d2875Santon }
14529f8d2875Santon 
14539f8d2875Santon /*
14549f8d2875Santon  * Test 18 - lf_findoverlap() case 1
14559f8d2875Santon  *
14569f8d2875Santon  * Overlap and lock are equal.
14579f8d2875Santon  */
14589f8d2875Santon static int
test18(int fd)145927fff5e2Santon test18(int fd)
14609f8d2875Santon {
14619f8d2875Santon 	struct flock fl;
14629f8d2875Santon 	int res;
14639f8d2875Santon 
14649f8d2875Santon 	fl.l_start = 0;
14659f8d2875Santon 	fl.l_len = 100;
14669f8d2875Santon 	fl.l_pid = 0;
14679f8d2875Santon 	fl.l_type = F_RDLCK;
14689f8d2875Santon 	fl.l_whence = 0;
14699f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
14709f8d2875Santon 	FAIL(res != 0);
14719f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
14729f8d2875Santon 	FAIL(res != 0);
14739f8d2875Santon 
14749f8d2875Santon 	SUCCEED;
14759f8d2875Santon }
14769f8d2875Santon 
14779f8d2875Santon /*
14789f8d2875Santon  * Test 19 - lf_findoverlap() case 2
14799f8d2875Santon  *
14809f8d2875Santon  * Overlap contains lock.
14819f8d2875Santon  */
14829f8d2875Santon static int
test19(int fd)148327fff5e2Santon test19(int fd)
14849f8d2875Santon {
14859f8d2875Santon 	struct flock fl;
14869f8d2875Santon 	int nfd, res;
14879f8d2875Santon 
14889f8d2875Santon 	/* Same type. */
14899f8d2875Santon 	{
14909f8d2875Santon 		nfd = dup(fd);
14919f8d2875Santon 		FAIL(nfd == -1);
14929f8d2875Santon 
14939f8d2875Santon 		fl.l_start = 0;
14949f8d2875Santon 		fl.l_len = 100;
14959f8d2875Santon 		fl.l_pid = 0;
14969f8d2875Santon 		fl.l_type = F_RDLCK;
14979f8d2875Santon 		fl.l_whence = 0;
14989f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
14999f8d2875Santon 		FAIL(res != 0);
15009f8d2875Santon 
15019f8d2875Santon 		fl.l_start = 0;
15029f8d2875Santon 		fl.l_len = 50;
15039f8d2875Santon 		fl.l_pid = 0;
15049f8d2875Santon 		fl.l_type = F_RDLCK;
15059f8d2875Santon 		fl.l_whence = 0;
15069f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
15079f8d2875Santon 		FAIL(res != 0);
15089f8d2875Santon 
15099f8d2875Santon 		close(nfd);
15109f8d2875Santon 	}
15119f8d2875Santon 
15129f8d2875Santon 	/* Different type, same start offset. */
15139f8d2875Santon 	{
15149f8d2875Santon 		nfd = dup(fd);
15159f8d2875Santon 		FAIL(nfd == -1);
15169f8d2875Santon 
15179f8d2875Santon 		fl.l_start = 100;
15189f8d2875Santon 		fl.l_len = 100;
15199f8d2875Santon 		fl.l_pid = 0;
15209f8d2875Santon 		fl.l_type = F_RDLCK;
15219f8d2875Santon 		fl.l_whence = 0;
15229f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
15239f8d2875Santon 		FAIL(res != 0);
15249f8d2875Santon 
15259f8d2875Santon 		fl.l_start = 100;
15269f8d2875Santon 		fl.l_len = 50;
15279f8d2875Santon 		fl.l_pid = 0;
15289f8d2875Santon 		fl.l_type = F_WRLCK;
15299f8d2875Santon 		fl.l_whence = 0;
15309f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
15319f8d2875Santon 		FAIL(res != 0);
15329f8d2875Santon 
15339f8d2875Santon 		close(nfd);
15349f8d2875Santon 	}
15359f8d2875Santon 
15369f8d2875Santon 	/* Split fallback. */
15379f8d2875Santon 	{
15389f8d2875Santon 		nfd = dup(fd);
15399f8d2875Santon 		FAIL(nfd == -1);
15409f8d2875Santon 
15419f8d2875Santon 		fl.l_start = 100;
15429f8d2875Santon 		fl.l_len = 100;
15439f8d2875Santon 		fl.l_pid = 0;
15449f8d2875Santon 		fl.l_type = F_RDLCK;
15459f8d2875Santon 		fl.l_whence = 0;
15469f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
15479f8d2875Santon 		FAIL(res != 0);
15489f8d2875Santon 
15499f8d2875Santon 		fl.l_start = 110;
15509f8d2875Santon 		fl.l_len = 50;
15519f8d2875Santon 		fl.l_pid = 0;
15529f8d2875Santon 		fl.l_type = F_WRLCK;
15539f8d2875Santon 		fl.l_whence = 0;
15549f8d2875Santon 		res = fcntl(fd, F_SETLK, &fl);
15559f8d2875Santon 		FAIL(res != 0);
15569f8d2875Santon 
15579f8d2875Santon 		close(nfd);
15589f8d2875Santon 	}
15599f8d2875Santon 
15609f8d2875Santon 	SUCCEED;
15619f8d2875Santon }
15629f8d2875Santon 
15639f8d2875Santon /*
15649f8d2875Santon  * Test 20 - lf_findoverlap() case 3
15659f8d2875Santon  *
15669f8d2875Santon  * Lock contains overlap.
15679f8d2875Santon  */
15689f8d2875Santon static int
test20(int fd)156927fff5e2Santon test20(int fd)
15709f8d2875Santon {
15719f8d2875Santon 	struct flock fl;
15729f8d2875Santon 	int res;
15739f8d2875Santon 
15749f8d2875Santon 	fl.l_start = 0;
15759f8d2875Santon 	fl.l_len = 100;
15769f8d2875Santon 	fl.l_pid = 0;
15779f8d2875Santon 	fl.l_type = F_WRLCK;
15789f8d2875Santon 	fl.l_whence = 0;
15799f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
15809f8d2875Santon 	FAIL(res != 0);
15819f8d2875Santon 
15829f8d2875Santon 	fl.l_start = 0;
15839f8d2875Santon 	fl.l_len = 200;
15849f8d2875Santon 	fl.l_pid = 0;
15859f8d2875Santon 	fl.l_type = F_WRLCK;
15869f8d2875Santon 	fl.l_whence = 0;
15879f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
15889f8d2875Santon 	FAIL(res != 0);
15899f8d2875Santon 
15909f8d2875Santon 	SUCCEED;
15919f8d2875Santon }
15929f8d2875Santon 
15939f8d2875Santon /*
15949f8d2875Santon  * Test 21 - lf_findoverlap() case 4
15959f8d2875Santon  *
15969f8d2875Santon  * Overlap starts before lock.
15979f8d2875Santon  */
15989f8d2875Santon static int
test21(int fd)159927fff5e2Santon test21(int fd)
16009f8d2875Santon {
16019f8d2875Santon 	struct flock fl;
16029f8d2875Santon 	int res;
16039f8d2875Santon 
16049f8d2875Santon 	fl.l_start = 0;
16059f8d2875Santon 	fl.l_len = 100;
16069f8d2875Santon 	fl.l_pid = 0;
16079f8d2875Santon 	fl.l_type = F_WRLCK;
16089f8d2875Santon 	fl.l_whence = 0;
16099f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
16109f8d2875Santon 	FAIL(res != 0);
16119f8d2875Santon 
16129f8d2875Santon 	fl.l_start = 50;
16139f8d2875Santon 	fl.l_len = 100;
16149f8d2875Santon 	fl.l_pid = 0;
16159f8d2875Santon 	fl.l_type = F_WRLCK;
16169f8d2875Santon 	fl.l_whence = 0;
16179f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
16189f8d2875Santon 	FAIL(res != 0);
16199f8d2875Santon 
16209f8d2875Santon 	SUCCEED;
16219f8d2875Santon }
16229f8d2875Santon 
16239f8d2875Santon /*
16249f8d2875Santon  * Test 22 - lf_findoverlap() case 5
16259f8d2875Santon  *
16269f8d2875Santon  * Overlap ends after lock.
16279f8d2875Santon  */
16289f8d2875Santon static int
test22(int fd)162927fff5e2Santon test22(int fd)
16309f8d2875Santon {
16319f8d2875Santon 	struct flock fl;
16329f8d2875Santon 	int res;
16339f8d2875Santon 
16349f8d2875Santon 	fl.l_start = 10;
16359f8d2875Santon 	fl.l_len = 100;
16369f8d2875Santon 	fl.l_pid = 0;
16379f8d2875Santon 	fl.l_type = F_WRLCK;
16389f8d2875Santon 	fl.l_whence = 0;
16399f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
16409f8d2875Santon 	FAIL(res != 0);
16419f8d2875Santon 
16429f8d2875Santon 	fl.l_start = 0;
16439f8d2875Santon 	fl.l_len = 50;
16449f8d2875Santon 	fl.l_pid = 0;
16459f8d2875Santon 	fl.l_type = F_WRLCK;
16469f8d2875Santon 	fl.l_whence = 0;
16479f8d2875Santon 	res = fcntl(fd, F_SETLK, &fl);
16489f8d2875Santon 	FAIL(res != 0);
16499f8d2875Santon 
16509f8d2875Santon 	SUCCEED;
16519f8d2875Santon }
16529f8d2875Santon 
16530d5ae59dSanton /*
16540d5ae59dSanton  * Test 23 - positive length overflow
16550d5ae59dSanton  */
16560d5ae59dSanton static int
test23(int fd)16570d5ae59dSanton test23(int fd)
16580d5ae59dSanton {
16590d5ae59dSanton 	struct flock fl;
16600d5ae59dSanton 	int res;
16610d5ae59dSanton 
16620d5ae59dSanton 	fl.l_pid = 0;
16630d5ae59dSanton 	fl.l_type = F_WRLCK;
16640d5ae59dSanton 	fl.l_whence = SEEK_SET;
16650d5ae59dSanton 	fl.l_start = 2;
16660d5ae59dSanton 	fl.l_len = LLONG_MAX;
16670d5ae59dSanton 	res = fcntl(fd, F_SETLK, &fl);
16680d5ae59dSanton 	FAIL(res != -1);
16690d5ae59dSanton 	FAIL(errno != EOVERFLOW);
16700d5ae59dSanton 
16710d5ae59dSanton 	SUCCEED;
16720d5ae59dSanton }
16730d5ae59dSanton 
16740d5ae59dSanton /*
16750d5ae59dSanton  * Test 24 - negative length
16760d5ae59dSanton  */
16770d5ae59dSanton static int
test24(int fd)16780d5ae59dSanton test24(int fd)
16790d5ae59dSanton {
16800d5ae59dSanton 	struct flock fl;
16810d5ae59dSanton 	pid_t pid;
16820d5ae59dSanton 	int res, status;
16830d5ae59dSanton 
16840d5ae59dSanton 	fl.l_pid = 0;
16850d5ae59dSanton 	fl.l_type = F_WRLCK;
16860d5ae59dSanton 	fl.l_whence = SEEK_SET;
16870d5ae59dSanton 
16880d5ae59dSanton 	/* Start offset plus length must be positive. */
16890d5ae59dSanton 	fl.l_start = 0;
16900d5ae59dSanton 	fl.l_len = LLONG_MIN;
16910d5ae59dSanton 	res = fcntl(fd, F_SETLK, &fl);
16920d5ae59dSanton 	FAIL(res != -1);
16930d5ae59dSanton 	FAIL(errno != EINVAL);
16940d5ae59dSanton 
16950d5ae59dSanton 	/* Set exclusive lock on range [2,3] */
16960d5ae59dSanton 	fl.l_start = 4;
16970d5ae59dSanton 	fl.l_len = -2;
16980d5ae59dSanton 	res = fcntl(fd, F_SETLK, &fl);
16990d5ae59dSanton 	FAIL(res != 0);
17000d5ae59dSanton 
17010d5ae59dSanton 	/* Another process must not be able to lock the same range. */
17020d5ae59dSanton 	pid = fork();
17030d5ae59dSanton 	if (pid == -1)
17040d5ae59dSanton 		err(1, "fork");
17050d5ae59dSanton 	if (pid == 0) {
17060d5ae59dSanton 		fl.l_start = 2;
17070d5ae59dSanton 		fl.l_len = 2;
17080d5ae59dSanton 		res = fcntl(fd, F_GETLK, &fl);
17090d5ae59dSanton 		FAIL(res != 0);
17100d5ae59dSanton 		FAIL(fl.l_type == F_UNLCK);
17110d5ae59dSanton 		_exit(0);
17120d5ae59dSanton 	}
17130d5ae59dSanton 	status = safe_waitpid(pid);
17140d5ae59dSanton 	FAIL(status != 0);
17150d5ae59dSanton 
17160d5ae59dSanton 	SUCCEED;
17170d5ae59dSanton }
17180d5ae59dSanton 
1719afb1c1edSanton /*
1720afb1c1edSanton  * Test 25 - use after free regression
1721afb1c1edSanton  *
1722afb1c1edSanton  * Discovered by syzkaller.
1723afb1c1edSanton  */
1724afb1c1edSanton static int
test25(int fd)1725afb1c1edSanton test25(int fd)
1726afb1c1edSanton {
1727afb1c1edSanton 	struct flock fl;
1728afb1c1edSanton 	int master, res, slave;
1729afb1c1edSanton 
1730afb1c1edSanton 	res = openpty(&master, &slave, NULL, NULL, NULL);
1731afb1c1edSanton 	FAIL(res == -1);
1732afb1c1edSanton 	close(master);
1733afb1c1edSanton 
1734afb1c1edSanton 	fl.l_start = 0;
1735afb1c1edSanton 	fl.l_len = 0;
1736afb1c1edSanton 	fl.l_pid = 0;
1737afb1c1edSanton 	fl.l_type = F_RDLCK;
1738afb1c1edSanton 	fl.l_whence = SEEK_SET;
1739afb1c1edSanton 	res = fcntl(slave, F_SETLKW, &fl);
1740afb1c1edSanton 	FAIL(res != 0);
1741afb1c1edSanton 
1742afb1c1edSanton 	fl.l_start = 3;
1743afb1c1edSanton 	fl.l_len = 0x7ffffffffffffffd;
1744afb1c1edSanton 	fl.l_pid = 0;
1745afb1c1edSanton 	fl.l_type = F_UNLCK;
1746afb1c1edSanton 	fl.l_whence = SEEK_END;
1747afb1c1edSanton 	res = fcntl(slave, F_SETLKW, &fl);
1748afb1c1edSanton 	FAIL(res != 0);
1749afb1c1edSanton 
1750afb1c1edSanton 	fl.l_start = 0;
1751afb1c1edSanton 	fl.l_len = 0;
1752afb1c1edSanton 	fl.l_pid = 0;
1753afb1c1edSanton 	fl.l_type = F_RDLCK;
1754afb1c1edSanton 	fl.l_whence = SEEK_SET;
1755afb1c1edSanton 	res = fcntl(slave, F_SETLKW, &fl);
1756afb1c1edSanton 	FAIL(res != 0);
1757afb1c1edSanton 
1758afb1c1edSanton 	close(slave);
1759afb1c1edSanton 
1760afb1c1edSanton 	SUCCEED;
1761afb1c1edSanton }
1762afb1c1edSanton 
1763*c3602110Svisa /*
1764*c3602110Svisa  * Test 26 - range end point ambiguity regression
1765*c3602110Svisa  *
1766*c3602110Svisa  * When a new lock range [start, LLONG_MAX] overlapped with an existing range,
1767*c3602110Svisa  * kernel's lock data structure could become inconsistent.
1768*c3602110Svisa  */
1769*c3602110Svisa static int
test26(int fd)1770*c3602110Svisa test26(int fd)
1771*c3602110Svisa {
1772*c3602110Svisa 	struct flock fl;
1773*c3602110Svisa 	pid_t pid;
1774*c3602110Svisa 	int res, status;
1775*c3602110Svisa 
1776*c3602110Svisa 	/* Lock the whole range. */
1777*c3602110Svisa 	fl.l_start = 0;
1778*c3602110Svisa 	fl.l_len = 0;
1779*c3602110Svisa 	fl.l_pid = 0;
1780*c3602110Svisa 	fl.l_type = F_RDLCK;
1781*c3602110Svisa 	fl.l_whence = SEEK_SET;
1782*c3602110Svisa 	res = fcntl(fd, F_SETLK, &fl);
1783*c3602110Svisa 	FAIL(res != 0);
1784*c3602110Svisa 
1785*c3602110Svisa 	/*
1786*c3602110Svisa 	 * Split the range at the end.
1787*c3602110Svisa 	 * This should be handled as if l_len == 0.
1788*c3602110Svisa 	 */
1789*c3602110Svisa 	fl.l_start = LLONG_MAX;
1790*c3602110Svisa 	fl.l_len = 1;
1791*c3602110Svisa 	fl.l_pid = 0;
1792*c3602110Svisa 	fl.l_type = F_WRLCK;
1793*c3602110Svisa 	fl.l_whence = SEEK_SET;
1794*c3602110Svisa 	res = fcntl(fd, F_SETLK, &fl);
1795*c3602110Svisa 	FAIL(res != 0);
1796*c3602110Svisa 
1797*c3602110Svisa 	/* Check the resulting ranges. */
1798*c3602110Svisa 	pid = fork();
1799*c3602110Svisa 	if (pid == -1)
1800*c3602110Svisa 		err(1, "fork");
1801*c3602110Svisa 	if (pid == 0) {
1802*c3602110Svisa 		fl.l_start = 0;
1803*c3602110Svisa 		fl.l_len = 0;
1804*c3602110Svisa 		fl.l_type = F_WRLCK;
1805*c3602110Svisa 		fl.l_whence = SEEK_SET;
1806*c3602110Svisa 		res = fcntl(fd, F_GETLK, &fl);
1807*c3602110Svisa 		FAIL(res != 0);
1808*c3602110Svisa 		FAIL(fl.l_type != F_RDLCK);
1809*c3602110Svisa 		FAIL(fl.l_start != 0);
1810*c3602110Svisa 		FAIL(fl.l_len != LLONG_MAX);
1811*c3602110Svisa 
1812*c3602110Svisa 		fl.l_start = LLONG_MAX;
1813*c3602110Svisa 		fl.l_len = 0;
1814*c3602110Svisa 		fl.l_type = F_WRLCK;
1815*c3602110Svisa 		fl.l_whence = SEEK_SET;
1816*c3602110Svisa 		res = fcntl(fd, F_GETLK, &fl);
1817*c3602110Svisa 		FAIL(res != 0);
1818*c3602110Svisa 		FAIL(fl.l_type != F_WRLCK);
1819*c3602110Svisa 		FAIL(fl.l_start != LLONG_MAX);
1820*c3602110Svisa 		FAIL(fl.l_len != 0);
1821*c3602110Svisa 
1822*c3602110Svisa 		_exit(0);
1823*c3602110Svisa 	}
1824*c3602110Svisa 	status = safe_waitpid(pid);
1825*c3602110Svisa 	FAIL(status != 0);
1826*c3602110Svisa 
1827*c3602110Svisa 	/* Release all locks. */
1828*c3602110Svisa 	fl.l_start = 0;
1829*c3602110Svisa 	fl.l_len = 0;
1830*c3602110Svisa 	fl.l_pid = 0;
1831*c3602110Svisa 	fl.l_type = F_UNLCK;
1832*c3602110Svisa 	fl.l_whence = SEEK_SET;
1833*c3602110Svisa 	res = fcntl(fd, F_SETLK, &fl);
1834*c3602110Svisa 	FAIL(res != 0);
1835*c3602110Svisa 
1836*c3602110Svisa 	/* Check the resulting ranges. */
1837*c3602110Svisa 	pid = fork();
1838*c3602110Svisa 	if (pid == -1)
1839*c3602110Svisa 		err(1, "fork");
1840*c3602110Svisa 	if (pid == 0) {
1841*c3602110Svisa 		fl.l_start = 0;
1842*c3602110Svisa 		fl.l_len = 0;
1843*c3602110Svisa 		fl.l_type = F_WRLCK;
1844*c3602110Svisa 		fl.l_whence = SEEK_SET;
1845*c3602110Svisa 		res = fcntl(fd, F_GETLK, &fl);
1846*c3602110Svisa 		FAIL(res != 0);
1847*c3602110Svisa 		FAIL(fl.l_type != F_UNLCK);
1848*c3602110Svisa 		FAIL(fl.l_start != 0);
1849*c3602110Svisa 		FAIL(fl.l_len != 0);
1850*c3602110Svisa 
1851*c3602110Svisa 		_exit(0);
1852*c3602110Svisa 	}
1853*c3602110Svisa 	status = safe_waitpid(pid);
1854*c3602110Svisa 	FAIL(status != 0);
1855*c3602110Svisa 
1856*c3602110Svisa 	SUCCEED;
1857*c3602110Svisa }
1858*c3602110Svisa 
1859cdea53deSanton static struct test tests[] = {
186027fff5e2Santon 	{	test1,		0	},
186127fff5e2Santon 	{	test2,		0	},
186227fff5e2Santon 	{	test3,		1	},
186327fff5e2Santon 	{	test4,		0	},
186427fff5e2Santon 	{	test5,		1	},
186527fff5e2Santon 	{	test6,		1	},
186627fff5e2Santon 	{	test7,		0	},
186727fff5e2Santon 	{	test8,		0	},
186827fff5e2Santon 	{	test9,		0	},
186927fff5e2Santon 	{	test10,		0	},
187027fff5e2Santon 	{	test11,		1	},
187127fff5e2Santon 	{	test12,		0	},
187227fff5e2Santon 	{	test13,		1	},
187327fff5e2Santon 	{	test14,		0	},
187427fff5e2Santon 	{	test15,		1	},
187527fff5e2Santon 	{	test16,		0	},
187627fff5e2Santon 	{	test17,		0	},
187727fff5e2Santon 	{	test18,		0	},
187827fff5e2Santon 	{	test19,		0	},
187927fff5e2Santon 	{	test20,		0	},
188027fff5e2Santon 	{	test21,		0	},
188127fff5e2Santon 	{	test22,		0	},
18820d5ae59dSanton 	{	test23,		0	},
18830d5ae59dSanton 	{	test24,		0	},
1884afb1c1edSanton 	{	test25,		0	},
1885*c3602110Svisa 	{	test26,		0	},
188697a3f8ceSart };
1887cdea53deSanton 
1888cdea53deSanton static int test_count = sizeof(tests) / sizeof(tests[0]);
188997a3f8ceSart 
189097a3f8ceSart int
main(int argc,char * argv[])189127fff5e2Santon main(int argc, char *argv[])
189297a3f8ceSart {
189397a3f8ceSart 	struct sigaction sa;
189427fff5e2Santon 	const char *errstr;
189527fff5e2Santon 	int c, fd, i;
189627fff5e2Santon 	int error = 0;
189727fff5e2Santon 	int testnum = 0;
189897a3f8ceSart 
189927fff5e2Santon 	while ((c = getopt(argc, argv, "v")) != -1)
190027fff5e2Santon 		switch (c) {
190127fff5e2Santon 		case 'v':
190297a3f8ceSart 			verbose = 1;
190327fff5e2Santon 			break;
190427fff5e2Santon 		default:
190527fff5e2Santon 			usage();
190697a3f8ceSart 		}
190727fff5e2Santon 	argc -= optind;
190827fff5e2Santon 	argv += optind;
190927fff5e2Santon 	if (argc > 1)
191027fff5e2Santon 		usage();
191127fff5e2Santon 	if (argc == 1) {
191227fff5e2Santon 		testnum = strtonum(argv[0], 1, test_count, &errstr);
191327fff5e2Santon 		if (testnum == 0)
191427fff5e2Santon 			errx(1, "test number %s", errstr);
191527fff5e2Santon 	}
191627fff5e2Santon 
191727fff5e2Santon 	fd = make_file(1024);
191897a3f8ceSart 
191997a3f8ceSart 	sa.sa_handler = ignore_alarm;
192097a3f8ceSart 	sigemptyset(&sa.sa_mask);
192197a3f8ceSart 	sa.sa_flags = 0;
192297a3f8ceSart 	sigaction(SIGALRM, &sa, 0);
192397a3f8ceSart 
192497a3f8ceSart 	for (i = 0; i < test_count; i++) {
192527fff5e2Santon 		if (testnum == 0 || testnum == i + 1)
192627fff5e2Santon 			error |= tests[i].testfn(fd);
192797a3f8ceSart 	}
192897a3f8ceSart 
192927fff5e2Santon 	return (error ? 1 : 0);
193097a3f8ceSart }
1931