xref: /freebsd/tests/sys/file/flock_helper.c (revision 2e3f49888ec8851bafb22011533217487764fdb0)
1 /*-
2  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3  * Authors: Doug Rabson <dfr@rabson.org>
4  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/param.h>
29 #include <sys/file.h>
30 #include <sys/time.h>
31 #ifdef __FreeBSD__
32 #include <sys/mount.h>
33 #endif
34 #include <sys/stat.h>
35 #include <sys/wait.h>
36 
37 #include <err.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <pthread.h>
41 #include <signal.h>
42 #include <stdint.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 
48 #ifdef __FreeBSD__
49 #if __FreeBSD_version >= 800028
50 #define HAVE_SYSID
51 #endif
52 #include <sys/cdefs.h>
53 #else
54 #ifndef nitems
55 #define	nitems(x)	(sizeof((x)) / sizeof((x)[0]))
56 #endif
57 
58 #ifndef __unused
59 #ifdef __GNUC__
60 #define	__unused	__attribute__((__unused__))
61 #else
62 #define __unused
63 #endif
64 #endif
65 #endif
66 
67 static int verbose = 0;
68 
69 static int
70 make_file(const char *pathname, off_t sz)
71 {
72 	struct stat st;
73 	const char *template = "/flocktempXXXXXX";
74 	size_t len;
75 	char *filename;
76 	int fd;
77 
78 	if (stat(pathname, &st) == 0) {
79 		if (S_ISREG(st.st_mode)) {
80 			fd = open(pathname, O_RDWR);
81 			if (fd < 0)
82 				err(1, "open(%s)", pathname);
83 			if (ftruncate(fd, sz) < 0)
84 				err(1, "ftruncate");
85 			return (fd);
86 		}
87 	}
88 
89 	len = strlen(pathname) + strlen(template) + 1;
90 	filename = malloc(len);
91 	strcpy(filename, pathname);
92 	strcat(filename, template);
93 	fd = mkstemp(filename);
94 	if (fd < 0)
95 		err(1, "mkstemp");
96 	if (ftruncate(fd, sz) < 0)
97 		err(1, "ftruncate");
98 	if (unlink(filename) < 0)
99 		err(1, "unlink");
100 	free(filename);
101 
102 	return (fd);
103 }
104 
105 static void
106 ignore_alarm(int __unused sig)
107 {
108 }
109 
110 static int
111 safe_waitpid(pid_t pid)
112 {
113 	int save_errno;
114 	int status;
115 
116 	save_errno = errno;
117 	errno = 0;
118 	while (waitpid(pid, &status, 0) != pid) {
119 		if (errno == EINTR)
120 			continue;
121 		err(1, "waitpid");
122 	}
123 	errno = save_errno;
124 
125 	return (status);
126 }
127 
128 #define FAIL(test)					\
129 	do {						\
130 		if (test) {				\
131 			printf("FAIL (%s)\n", #test);	\
132 			return -1;			\
133 		}					\
134 	} while (0)
135 
136 #define SUCCEED \
137 	do { printf("SUCCEED\n"); return 0; } while (0)
138 
139 /*
140  * Test 1 - F_GETLK on unlocked region
141  *
142  * If no lock is found that would prevent this lock from being
143  * created, the structure is left unchanged by this function call
144  * except for the lock type which is set to F_UNLCK.
145  */
146 static int
147 test1(int fd, __unused int argc, const __unused char **argv)
148 {
149 	struct flock fl1, fl2;
150 
151 	memset(&fl1, 1, sizeof(fl1));
152 	fl1.l_type = F_WRLCK;
153 	fl1.l_whence = SEEK_SET;
154 	fl2 = fl1;
155 
156 	if (fcntl(fd, F_GETLK, &fl1) < 0)
157 		err(1, "F_GETLK");
158 
159 	printf("1 - F_GETLK on unlocked region: ");
160 	FAIL(fl1.l_start != fl2.l_start);
161 	FAIL(fl1.l_len != fl2.l_len);
162 	FAIL(fl1.l_pid != fl2.l_pid);
163 	FAIL(fl1.l_type != F_UNLCK);
164 	FAIL(fl1.l_whence != fl2.l_whence);
165 #ifdef HAVE_SYSID
166 	FAIL(fl1.l_sysid != fl2.l_sysid);
167 #endif
168 
169 	SUCCEED;
170 }
171 
172 /*
173  * Test 2 - F_SETLK on locked region
174  *
175  * If a shared or exclusive lock cannot be set, fcntl returns
176  * immediately with EACCES or EAGAIN.
177  */
178 static int
179 test2(int fd, __unused int argc, const __unused char **argv)
180 {
181 	/*
182 	 * We create a child process to hold the lock which we will
183 	 * test. We use a pipe to communicate with the child.
184 	 */
185 	int pid;
186 	int pfd[2];
187 	struct flock fl;
188 	char ch;
189 	int res;
190 
191 	if (pipe(pfd) < 0)
192 		err(1, "pipe");
193 
194 	fl.l_start = 0;
195 	fl.l_len = 0;
196 	fl.l_type = F_WRLCK;
197 	fl.l_whence = SEEK_SET;
198 
199 	pid = fork();
200 	if (pid < 0)
201 		err(1, "fork");
202 
203 	if (pid == 0) {
204 		/*
205 		 * We are the child. We set a write lock and then
206 		 * write one byte back to the parent to tell it. The
207 		 * parent will kill us when its done.
208 		 */
209 		if (fcntl(fd, F_SETLK, &fl) < 0)
210 			err(1, "F_SETLK (child)");
211 		if (write(pfd[1], "a", 1) < 0)
212 			err(1, "writing to pipe (child)");
213 		pause();
214 		exit(0);
215 	}
216 
217 	/*
218 	 * Wait until the child has set its lock and then perform the
219 	 * test.
220 	 */
221 	if (read(pfd[0], &ch, 1) != 1)
222 		err(1, "reading from pipe (child)");
223 
224 	/*
225 	 * fcntl should return -1 with errno set to either EACCES or
226 	 * EAGAIN.
227 	 */
228 	printf("2 - F_SETLK on locked region: ");
229 	res = fcntl(fd, F_SETLK, &fl);
230 	kill(pid, SIGTERM);
231 	safe_waitpid(pid);
232 	close(pfd[0]);
233 	close(pfd[1]);
234 	FAIL(res == 0);
235 	FAIL(errno != EACCES && errno != EAGAIN);
236 
237 	SUCCEED;
238 }
239 
240 /*
241  * Test 3 - F_SETLKW on locked region
242  *
243  * If a shared or exclusive lock is blocked by other locks, the
244  * process waits until the request can be satisfied.
245  *
246  * XXX this test hangs on FreeBSD NFS filesystems due to limitations
247  * in FreeBSD's client (and server) lockd implementation.
248  */
249 static int
250 test3(int fd, __unused int argc, const __unused char **argv)
251 {
252 	/*
253 	 * We create a child process to hold the lock which we will
254 	 * test. We use a pipe to communicate with the child.
255 	 */
256 	int pid;
257 	int pfd[2];
258 	struct flock fl;
259 	char ch;
260 	int res;
261 
262 	if (pipe(pfd) < 0)
263 		err(1, "pipe");
264 
265 	fl.l_start = 0;
266 	fl.l_len = 0;
267 	fl.l_type = F_WRLCK;
268 	fl.l_whence = SEEK_SET;
269 
270 	pid = fork();
271 	if (pid < 0)
272 		err(1, "fork");
273 
274 	if (pid == 0) {
275 		/*
276 		 * We are the child. We set a write lock and then
277 		 * write one byte back to the parent to tell it. The
278 		 * parent will kill us when its done.
279 		 */
280 		if (fcntl(fd, F_SETLK, &fl) < 0)
281 			err(1, "F_SETLK (child)");
282 		if (write(pfd[1], "a", 1) < 0)
283 			err(1, "writing to pipe (child)");
284 		pause();
285 		exit(0);
286 	}
287 
288 	/*
289 	 * Wait until the child has set its lock and then perform the
290 	 * test.
291 	 */
292 	if (read(pfd[0], &ch, 1) != 1)
293 		err(1, "reading from pipe (child)");
294 
295 	/*
296 	 * fcntl should wait until the alarm and then return -1 with
297 	 * errno set to EINTR.
298 	 */
299 	printf("3 - F_SETLKW on locked region: ");
300 
301 	alarm(1);
302 
303 	res = fcntl(fd, F_SETLKW, &fl);
304 	kill(pid, SIGTERM);
305 	safe_waitpid(pid);
306 	close(pfd[0]);
307 	close(pfd[1]);
308 	FAIL(res == 0);
309 	FAIL(errno != EINTR);
310 
311 	SUCCEED;
312 }
313 
314 /*
315  * Test 4 - F_GETLK on locked region
316  *
317  * Get the first lock that blocks the lock.
318  */
319 static int
320 test4(int fd, __unused int argc, const __unused char **argv)
321 {
322 	/*
323 	 * We create a child process to hold the lock which we will
324 	 * test. We use a pipe to communicate with the child.
325 	 */
326 	int pid;
327 	int pfd[2];
328 	struct flock fl;
329 	char ch;
330 
331 	if (pipe(pfd) < 0)
332 		err(1, "pipe");
333 
334 	fl.l_start = 0;
335 	fl.l_len = 99;
336 	fl.l_type = F_WRLCK;
337 	fl.l_whence = SEEK_SET;
338 
339 	pid = fork();
340 	if (pid < 0)
341 		err(1, "fork");
342 
343 	if (pid == 0) {
344 		/*
345 		 * We are the child. We set a write lock and then
346 		 * write one byte back to the parent to tell it. The
347 		 * parent will kill us when its done.
348 		 */
349 		if (fcntl(fd, F_SETLK, &fl) < 0)
350 			err(1, "F_SETLK (child)");
351 		if (write(pfd[1], "a", 1) < 0)
352 			err(1, "writing to pipe (child)");
353 		pause();
354 		exit(0);
355 	}
356 
357 	/*
358 	 * Wait until the child has set its lock and then perform the
359 	 * test.
360 	 */
361 	if (read(pfd[0], &ch, 1) != 1)
362 		err(1, "reading from pipe (child)");
363 
364 	/*
365 	 * fcntl should return a lock structure reflecting the lock we
366 	 * made in the child process.
367 	 */
368 	if (fcntl(fd, F_GETLK, &fl) < 0)
369 		err(1, "F_GETLK");
370 
371 	printf("4 - F_GETLK on locked region: ");
372 	FAIL(fl.l_start != 0);
373 	FAIL(fl.l_len != 99);
374 	FAIL(fl.l_type != F_WRLCK);
375 	FAIL(fl.l_pid != pid);
376 #ifdef HAVE_SYSID
377 	FAIL(fl.l_sysid != 0);
378 #endif
379 
380 	kill(pid, SIGTERM);
381 	safe_waitpid(pid);
382 	close(pfd[0]);
383 	close(pfd[1]);
384 
385 	SUCCEED;
386 }
387 
388 /*
389  * Test 5 - F_SETLKW simple deadlock
390  *
391  * If a blocking shared lock request would cause a deadlock (i.e. the
392  * lock request is blocked by a process which is itself blocked on a
393  * lock currently owned by the process making the new request),
394  * EDEADLK is returned.
395  */
396 static int
397 test5(int fd, __unused int argc, const __unused char **argv)
398 {
399 	/*
400 	 * We create a child process to hold the lock which we will
401 	 * test. Because our test relies on the child process being
402 	 * blocked on the parent's lock, we can't easily use a pipe to
403 	 * synchronize so we just sleep in the parent to given the
404 	 * child a chance to setup.
405 	 *
406 	 * To create the deadlock condition, we arrange for the parent
407 	 * to lock the first byte of the file and the child to lock
408 	 * the second byte.  After locking the second byte, the child
409 	 * will attempt to lock the first byte of the file, and
410 	 * block. The parent will then attempt to lock the second byte
411 	 * (owned by the child) which should cause deadlock.
412 	 */
413 	int pid;
414 	struct flock fl;
415 	int res;
416 
417 	/*
418 	 * Lock the first byte in the parent.
419 	 */
420 	fl.l_start = 0;
421 	fl.l_len = 1;
422 	fl.l_type = F_WRLCK;
423 	fl.l_whence = SEEK_SET;
424 	if (fcntl(fd, F_SETLK, &fl) < 0)
425 		err(1, "F_SETLK 1 (parent)");
426 
427 	pid = fork();
428 	if (pid < 0)
429 		err(1, "fork");
430 
431 	if (pid == 0) {
432 		/*
433 		 * Lock the second byte in the child and then block on
434 		 * the parent's lock.
435 		 */
436 		fl.l_start = 1;
437 		if (fcntl(fd, F_SETLK, &fl) < 0)
438 			err(1, "F_SETLK (child)");
439 		fl.l_start = 0;
440 		if (fcntl(fd, F_SETLKW, &fl) < 0)
441 			err(1, "F_SETLKW (child)");
442 		exit(0);
443 	}
444 
445 	/*
446 	 * Wait until the child has set its lock and then perform the
447 	 * test.
448 	 */
449 	sleep(1);
450 
451 	/*
452 	 * fcntl should immediately return -1 with errno set to
453 	 * EDEADLK. If the alarm fires, we failed to detect the
454 	 * deadlock.
455 	 */
456 	alarm(1);
457 	printf("5 - F_SETLKW simple deadlock: ");
458 
459 	fl.l_start = 1;
460 	res = fcntl(fd, F_SETLKW, &fl);
461 	kill(pid, SIGTERM);
462 	safe_waitpid(pid);
463 
464 	FAIL(res == 0);
465 	FAIL(errno != EDEADLK);
466 
467 	fl.l_start = 0;
468 	fl.l_len = 0;
469 	fl.l_type = F_UNLCK;
470 	if (fcntl(fd, F_SETLK, &fl) < 0)
471 		err(1, "F_UNLCK");
472 
473 	/*
474 	 * Cancel the alarm to avoid confusing later tests.
475 	 */
476 	alarm(0);
477 
478 	SUCCEED;
479 }
480 
481 /*
482  * Test 6 - F_SETLKW complex deadlock.
483  *
484  * This test involves three process, P, C1 and C2. We set things up so
485  * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We
486  * also block C2 by attempting to lock byte zero. Lastly, P attempts
487  * to lock a range including byte 1 and 2. This represents a deadlock
488  * (due to C2's blocking attempt to lock byte zero).
489  */
490 static int
491 test6(int fd, __unused int argc, const __unused char **argv)
492 {
493 	/*
494 	 * Because our test relies on the child process being blocked
495 	 * on the parent's lock, we can't easily use a pipe to
496 	 * synchronize so we just sleep in the parent to given the
497 	 * children a chance to setup.
498 	 */
499 	int pid1, pid2;
500 	struct flock fl;
501 	int res;
502 
503 	/*
504 	 * Lock the first byte in the parent.
505 	 */
506 	fl.l_start = 0;
507 	fl.l_len = 1;
508 	fl.l_type = F_WRLCK;
509 	fl.l_whence = SEEK_SET;
510 	if (fcntl(fd, F_SETLK, &fl) < 0)
511 		err(1, "F_SETLK 1 (parent)");
512 
513 	pid1 = fork();
514 	if (pid1 < 0)
515 		err(1, "fork");
516 
517 	if (pid1 == 0) {
518 		/*
519 		 * C1
520 		 * Lock the second byte in the child and then sleep
521 		 */
522 		fl.l_start = 1;
523 		if (fcntl(fd, F_SETLK, &fl) < 0)
524 			err(1, "F_SETLK (child1)");
525 		pause();
526 		exit(0);
527 	}
528 
529 	pid2 = fork();
530 	if (pid2 < 0)
531 		err(1, "fork");
532 
533 	if (pid2 == 0) {
534 		/*
535 		 * C2
536 		 * Lock the third byte in the child and then block on
537 		 * the parent's lock.
538 		 */
539 		fl.l_start = 2;
540 		if (fcntl(fd, F_SETLK, &fl) < 0)
541 			err(1, "F_SETLK (child2)");
542 		fl.l_start = 0;
543 		if (fcntl(fd, F_SETLKW, &fl) < 0)
544 			err(1, "F_SETLKW (child2)");
545 		exit(0);
546 	}
547 
548 	/*
549 	 * Wait until the children have set their locks and then
550 	 * perform the test.
551 	 */
552 	sleep(1);
553 
554 	/*
555 	 * fcntl should immediately return -1 with errno set to
556 	 * EDEADLK. If the alarm fires, we failed to detect the
557 	 * deadlock.
558 	 */
559 	alarm(1);
560 	printf("6 - F_SETLKW complex deadlock: ");
561 
562 	fl.l_start = 1;
563 	fl.l_len = 2;
564 	res = fcntl(fd, F_SETLKW, &fl);
565 	kill(pid1, SIGTERM);
566 	safe_waitpid(pid1);
567 	kill(pid2, SIGTERM);
568 	safe_waitpid(pid2);
569 
570 	fl.l_start = 0;
571 	fl.l_len = 0;
572 	fl.l_type = F_UNLCK;
573 	if (fcntl(fd, F_SETLK, &fl) < 0)
574 		err(1, "F_UNLCK");
575 
576 	FAIL(res == 0);
577 	FAIL(errno != EDEADLK);
578 
579 	/*
580 	 * Cancel the alarm to avoid confusing later tests.
581 	 */
582 	alarm(0);
583 
584 	SUCCEED;
585 }
586 
587 /*
588  * Test 7 - F_SETLK shared lock on exclusive locked region
589  *
590  * If a shared or exclusive lock cannot be set, fcntl returns
591  * immediately with EACCES or EAGAIN.
592  */
593 static int
594 test7(int fd, __unused int argc, const __unused char **argv)
595 {
596 	/*
597 	 * We create a child process to hold the lock which we will
598 	 * test. We use a pipe to communicate with the child.
599 	 */
600 	int pid;
601 	int pfd[2];
602 	struct flock fl;
603 	char ch;
604 	int res;
605 
606 	if (pipe(pfd) < 0)
607 		err(1, "pipe");
608 
609 	fl.l_start = 0;
610 	fl.l_len = 0;
611 	fl.l_type = F_WRLCK;
612 	fl.l_whence = SEEK_SET;
613 
614 	pid = fork();
615 	if (pid < 0)
616 		err(1, "fork");
617 
618 	if (pid == 0) {
619 		/*
620 		 * We are the child. We set a write lock and then
621 		 * write one byte back to the parent to tell it. The
622 		 * parent will kill us when its done.
623 		 */
624 		if (fcntl(fd, F_SETLK, &fl) < 0)
625 			err(1, "F_SETLK (child)");
626 		if (write(pfd[1], "a", 1) < 0)
627 			err(1, "writing to pipe (child)");
628 		pause();
629 		exit(0);
630 	}
631 
632 	/*
633 	 * Wait until the child has set its lock and then perform the
634 	 * test.
635 	 */
636 	if (read(pfd[0], &ch, 1) != 1)
637 		err(1, "reading from pipe (child)");
638 
639 	/*
640 	 * fcntl should wait until the alarm and then return -1 with
641 	 * errno set to EINTR.
642 	 */
643 	printf("7 - F_SETLK shared lock on exclusive locked region: ");
644 
645 	fl.l_type = F_RDLCK;
646 	res = fcntl(fd, F_SETLK, &fl);
647 	kill(pid, SIGTERM);
648 	safe_waitpid(pid);
649 	close(pfd[0]);
650 	close(pfd[1]);
651 
652 	FAIL(res == 0);
653 	FAIL(errno != EACCES && errno != EAGAIN);
654 
655 	SUCCEED;
656 }
657 
658 /*
659  * Test 8 - F_SETLK shared lock on share locked region
660  *
661  * When a shared lock is set on a segment of a file, other processes
662  * shall be able to set shared locks on that segment or a portion of
663  * it.
664  */
665 static int
666 test8(int fd, __unused int argc, const __unused char **argv)
667 {
668 	/*
669 	 * We create a child process to hold the lock which we will
670 	 * test. We use a pipe to communicate with the child.
671 	 */
672 	int pid;
673 	int pfd[2];
674 	struct flock fl;
675 	char ch;
676 	int res;
677 
678 	if (pipe(pfd) < 0)
679 		err(1, "pipe");
680 
681 	fl.l_start = 0;
682 	fl.l_len = 0;
683 	fl.l_type = F_RDLCK;
684 	fl.l_whence = SEEK_SET;
685 
686 	pid = fork();
687 	if (pid < 0)
688 		err(1, "fork");
689 
690 	if (pid == 0) {
691 		/*
692 		 * We are the child. We set a write lock and then
693 		 * write one byte back to the parent to tell it. The
694 		 * parent will kill us when its done.
695 		 */
696 		if (fcntl(fd, F_SETLK, &fl) < 0)
697 			err(1, "F_SETLK (child)");
698 		if (write(pfd[1], "a", 1) < 0)
699 			err(1, "writing to pipe (child)");
700 		pause();
701 		exit(0);
702 	}
703 
704 	/*
705 	 * Wait until the child has set its lock and then perform the
706 	 * test.
707 	 */
708 	if (read(pfd[0], &ch, 1) != 1)
709 		err(1, "reading from pipe (child)");
710 
711 	/*
712 	 * fcntl should wait until the alarm and then return -1 with
713 	 * errno set to EINTR.
714 	 */
715 	printf("8 - F_SETLK shared lock on share locked region: ");
716 
717 	fl.l_type = F_RDLCK;
718 	res = fcntl(fd, F_SETLK, &fl);
719 
720 	kill(pid, SIGTERM);
721 	safe_waitpid(pid);
722 	close(pfd[0]);
723 	close(pfd[1]);
724 
725 	fl.l_start = 0;
726 	fl.l_len = 0;
727 	fl.l_type = F_UNLCK;
728 	if (fcntl(fd, F_SETLK, &fl) < 0)
729 		err(1, "F_UNLCK");
730 
731 	FAIL(res != 0);
732 
733 	SUCCEED;
734 }
735 
736 /*
737  * Test 9 - F_SETLK exclusive lock on share locked region
738  *
739  * If a shared or exclusive lock cannot be set, fcntl returns
740  * immediately with EACCES or EAGAIN.
741  */
742 static int
743 test9(int fd, __unused int argc, const __unused char **argv)
744 {
745 	/*
746 	 * We create a child process to hold the lock which we will
747 	 * test. We use a pipe to communicate with the child.
748 	 */
749 	int pid;
750 	int pfd[2];
751 	struct flock fl;
752 	char ch;
753 	int res;
754 
755 	if (pipe(pfd) < 0)
756 		err(1, "pipe");
757 
758 	fl.l_start = 0;
759 	fl.l_len = 0;
760 	fl.l_type = F_RDLCK;
761 	fl.l_whence = SEEK_SET;
762 
763 	pid = fork();
764 	if (pid < 0)
765 		err(1, "fork");
766 
767 	if (pid == 0) {
768 		/*
769 		 * We are the child. We set a write lock and then
770 		 * write one byte back to the parent to tell it. The
771 		 * parent will kill us when its done.
772 		 */
773 		if (fcntl(fd, F_SETLK, &fl) < 0)
774 			err(1, "F_SETLK (child)");
775 		if (write(pfd[1], "a", 1) < 0)
776 			err(1, "writing to pipe (child)");
777 		pause();
778 		exit(0);
779 	}
780 
781 	/*
782 	 * Wait until the child has set its lock and then perform the
783 	 * test.
784 	 */
785 	if (read(pfd[0], &ch, 1) != 1)
786 		err(1, "reading from pipe (child)");
787 
788 	/*
789 	 * fcntl should wait until the alarm and then return -1 with
790 	 * errno set to EINTR.
791 	 */
792 	printf("9 - F_SETLK exclusive lock on share locked region: ");
793 
794 	fl.l_type = F_WRLCK;
795 	res = fcntl(fd, F_SETLK, &fl);
796 	kill(pid, SIGTERM);
797 	safe_waitpid(pid);
798 	close(pfd[0]);
799 	close(pfd[1]);
800 
801 	FAIL(res == 0);
802 	FAIL(errno != EACCES && errno != EAGAIN);
803 
804 	SUCCEED;
805 }
806 
807 /*
808  * Test 10 - trying to set bogus pid or sysid values
809  *
810  * The l_pid and l_sysid fields are only used with F_GETLK to return
811  * the process ID of the process holding a blocking lock and the
812  * system ID of the system that owns that process
813  */
814 static int
815 test10(int fd, __unused int argc, const __unused char **argv)
816 {
817 	/*
818 	 * We create a child process to hold the lock which we will
819 	 * test. We use a pipe to communicate with the child.
820 	 */
821 	int pid;
822 	int pfd[2];
823 	struct flock fl;
824 	char ch;
825 
826 	if (pipe(pfd) < 0)
827 		err(1, "pipe");
828 
829 	fl.l_start = 0;
830 	fl.l_len = 0;
831 	fl.l_type = F_WRLCK;
832 	fl.l_whence = SEEK_SET;
833 	fl.l_pid = 9999;
834 #ifdef HAVE_SYSID
835 	fl.l_sysid = 9999;
836 #endif
837 
838 	pid = fork();
839 	if (pid < 0)
840 		err(1, "fork");
841 
842 	if (pid == 0) {
843 		/*
844 		 * We are the child. We set a write lock and then
845 		 * write one byte back to the parent to tell it. The
846 		 * parent will kill us when its done.
847 		 */
848 		if (fcntl(fd, F_SETLK, &fl) < 0)
849 			err(1, "F_SETLK (child)");
850 		if (write(pfd[1], "a", 1) < 0)
851 			err(1, "writing to pipe (child)");
852 		pause();
853 		exit(0);
854 	}
855 
856 	/*
857 	 * Wait until the child has set its lock and then perform the
858 	 * test.
859 	 */
860 	if (read(pfd[0], &ch, 1) != 1)
861 		err(1, "reading from pipe (child)");
862 
863 	printf("10 - trying to set bogus pid or sysid values: ");
864 
865 	if (fcntl(fd, F_GETLK, &fl) < 0)
866 		err(1, "F_GETLK");
867 
868 	kill(pid, SIGTERM);
869 	safe_waitpid(pid);
870 	close(pfd[0]);
871 	close(pfd[1]);
872 
873 	FAIL(fl.l_pid != pid);
874 #ifdef HAVE_SYSID
875 	FAIL(fl.l_sysid != 0);
876 #endif
877 
878 	SUCCEED;
879 }
880 
881 /*
882  * Test 11 - remote locks
883  *
884  * XXX temporary interface which will be removed when the kernel lockd
885  * is added.
886  */
887 static int
888 test11(int fd, __unused int argc, const __unused char **argv)
889 {
890 #ifdef F_SETLK_REMOTE
891 	struct flock fl;
892 	int res;
893 
894 	if (geteuid() != 0)
895 		return 0;
896 
897 	fl.l_start = 0;
898 	fl.l_len = 0;
899 	fl.l_type = F_WRLCK;
900 	fl.l_whence = SEEK_SET;
901 	fl.l_pid = 9999;
902 	fl.l_sysid = 1001;
903 
904 	printf("11 - remote locks: ");
905 
906 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
907 	FAIL(res != 0);
908 
909 	fl.l_sysid = 1002;
910 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
911 	FAIL(res == 0);
912 	FAIL(errno != EACCES && errno != EAGAIN);
913 
914 	res = fcntl(fd, F_GETLK, &fl);
915 	FAIL(res != 0);
916 	FAIL(fl.l_pid != 9999);
917 	FAIL(fl.l_sysid != 1001);
918 
919 	fl.l_type = F_UNLCK;
920 	fl.l_sysid = 1001;
921 	fl.l_start = 0;
922 	fl.l_len = 0;
923 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
924 	FAIL(res != 0);
925 
926 	fl.l_pid = 1234;
927 	fl.l_sysid = 1001;
928 	fl.l_start = 0;
929 	fl.l_len = 1;
930 	fl.l_whence = SEEK_SET;
931 	fl.l_type = F_RDLCK;
932 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
933 	FAIL(res != 0);
934 
935 	fl.l_sysid = 1002;
936 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
937 	FAIL(res != 0);
938 
939 	fl.l_type = F_UNLCKSYS;
940 	fl.l_sysid = 1001;
941 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
942 	FAIL(res != 0);
943 
944 	fl.l_type = F_WRLCK;
945 	res = fcntl(fd, F_GETLK, &fl);
946 	FAIL(res != 0);
947 	FAIL(fl.l_pid != 1234);
948 	FAIL(fl.l_sysid != 1002);
949 
950 	fl.l_type = F_UNLCKSYS;
951 	fl.l_sysid = 1002;
952 	res = fcntl(fd, F_SETLK_REMOTE, &fl);
953 	FAIL(res != 0);
954 
955 	SUCCEED;
956 #else
957 	return 0;
958 #endif
959 }
960 
961 /*
962  * Test 12 - F_SETLKW on locked region which is then unlocked
963  *
964  * If a shared or exclusive lock is blocked by other locks, the
965  * process waits until the request can be satisfied.
966  */
967 static int
968 test12(int fd, __unused int argc, const __unused char **argv)
969 {
970 	/*
971 	 * We create a child process to hold the lock which we will
972 	 * test. We use a pipe to communicate with the child.
973 	 */
974 	int pid;
975 	int pfd[2];
976 	struct flock fl;
977 	char ch;
978 	int res;
979 
980 	if (pipe(pfd) < 0)
981 		err(1, "pipe");
982 
983 	fl.l_start = 0;
984 	fl.l_len = 0;
985 	fl.l_type = F_WRLCK;
986 	fl.l_whence = SEEK_SET;
987 
988 	pid = fork();
989 	if (pid < 0)
990 		err(1, "fork");
991 
992 	if (pid == 0) {
993 		/*
994 		 * We are the child. We set a write lock and then
995 		 * write one byte back to the parent to tell it. The
996 		 * parent will kill us when its done.
997 		 */
998 		if (fcntl(fd, F_SETLK, &fl) < 0)
999 			err(1, "F_SETLK (child)");
1000 		if (write(pfd[1], "a", 1) < 0)
1001 			err(1, "writing to pipe (child)");
1002 
1003 		sleep(1);
1004 		exit(0);
1005 	}
1006 
1007 	/*
1008 	 * Wait until the child has set its lock and then perform the
1009 	 * test.
1010 	 */
1011 	if (read(pfd[0], &ch, 1) != 1)
1012 		err(1, "reading from pipe (child)");
1013 
1014 	/*
1015 	 * fcntl should wait until the alarm and then return -1 with
1016 	 * errno set to EINTR.
1017 	 */
1018 	printf("12 - F_SETLKW on locked region which is then unlocked: ");
1019 
1020 	//alarm(1);
1021 
1022 	res = fcntl(fd, F_SETLKW, &fl);
1023 	kill(pid, SIGTERM);
1024 	safe_waitpid(pid);
1025 	close(pfd[0]);
1026 	close(pfd[1]);
1027 	FAIL(res != 0);
1028 
1029 	fl.l_start = 0;
1030 	fl.l_len = 0;
1031 	fl.l_type = F_UNLCK;
1032 	if (fcntl(fd, F_SETLK, &fl) < 0)
1033 		err(1, "F_UNLCK");
1034 
1035 	SUCCEED;
1036 }
1037 
1038 /*
1039  * Test 13 - F_SETLKW on locked region, race with owner
1040  *
1041  * If a shared or exclusive lock is blocked by other locks, the
1042  * process waits until the request can be satisfied.
1043  */
1044 static int
1045 test13(int fd, __unused int argc, const __unused char **argv)
1046 {
1047 	/*
1048 	 * We create a child process to hold the lock which we will
1049 	 * test. We use a pipe to communicate with the child.
1050 	 */
1051 	int i;
1052 	int pid;
1053 	int pfd[2];
1054 	struct flock fl;
1055 	char ch;
1056 	int res;
1057 	struct itimerval itv;
1058 
1059 	printf("13 - F_SETLKW on locked region, race with owner: ");
1060 	fflush(stdout);
1061 
1062 	for (i = 0; i < 100; i++) {
1063 		if (pipe(pfd) < 0)
1064 			err(1, "pipe");
1065 
1066 		fl.l_start = 0;
1067 		fl.l_len = 0;
1068 		fl.l_type = F_WRLCK;
1069 		fl.l_whence = SEEK_SET;
1070 
1071 		pid = fork();
1072 		if (pid < 0)
1073 			err(1, "fork");
1074 
1075 		if (pid == 0) {
1076 			/*
1077 			 * We are the child. We set a write lock and then
1078 			 * write one byte back to the parent to tell it. The
1079 			 * parent will kill us when its done.
1080 			 */
1081 			if (fcntl(fd, F_SETLK, &fl) < 0)
1082 				err(1, "F_SETLK (child)");
1083 			if (write(pfd[1], "a", 1) < 0)
1084 				err(1, "writing to pipe (child)");
1085 
1086 			usleep(1);
1087 			exit(0);
1088 		}
1089 
1090 		/*
1091 		 * Wait until the child has set its lock and then perform the
1092 		 * test.
1093 		 */
1094 		while (read(pfd[0], &ch, 1) != 1) {
1095 			if (errno == EINTR)
1096 				continue;
1097 			err(1, "reading from pipe (child)");
1098 		}
1099 
1100 		/*
1101 		 * fcntl should wait until the alarm and then return -1 with
1102 		 * errno set to EINTR.
1103 		 */
1104 		itv.it_interval.tv_sec = 0;
1105 		itv.it_interval.tv_usec = 0;
1106 		itv.it_value.tv_sec = 0;
1107 		itv.it_value.tv_usec = 2;
1108 		setitimer(ITIMER_REAL, &itv, NULL);
1109 
1110 		res = fcntl(fd, F_SETLKW, &fl);
1111 		kill(pid, SIGTERM);
1112 		safe_waitpid(pid);
1113 		close(pfd[0]);
1114 		close(pfd[1]);
1115 		FAIL(!(res == 0 || (res == -1 && errno == EINTR)));
1116 
1117 		fl.l_start = 0;
1118 		fl.l_len = 0;
1119 		fl.l_type = F_UNLCK;
1120 		if (fcntl(fd, F_SETLK, &fl) < 0)
1121 			err(1, "F_UNLCK");
1122 	}
1123 	SUCCEED;
1124 }
1125 
1126 /*
1127  * Test 14 - soak test
1128  */
1129 static int
1130 test14(int fd, int argc, const char **argv)
1131 {
1132 #define CHILD_COUNT 20
1133 	/*
1134 	 * We create a set of child processes and let each one run
1135 	 * through a random sequence of locks and unlocks.
1136 	 */
1137 	int i, j, id, id_base;
1138 	int pids[CHILD_COUNT], pid;
1139 	char buf[128];
1140 	char tbuf[128];
1141 	int map[128];
1142 	char outbuf[512];
1143 	struct flock fl;
1144 	struct itimerval itv;
1145 	int status;
1146 
1147 	id_base = 0;
1148 	if (argc >= 2)
1149 		id_base = strtol(argv[1], NULL, 0);
1150 
1151 	printf("14 - soak test: ");
1152 	fflush(stdout);
1153 
1154 	for (i = 0; i < 128; i++)
1155 		map[i] = F_UNLCK;
1156 
1157 	for (i = 0; i < CHILD_COUNT; i++) {
1158 
1159 		pid = fork();
1160 		if (pid < 0)
1161 			err(1, "fork");
1162 		if (pid) {
1163 			/*
1164 			 * Parent - record the pid and continue.
1165 			 */
1166 			pids[i] = pid;
1167 			continue;
1168 		}
1169 
1170 		/*
1171 		 * Child - do some work and exit.
1172 		 */
1173 		id = id_base + i;
1174 		srandom(getpid());
1175 
1176 		for (j = 0; j < 50; j++) {
1177 			int start, end, len;
1178 			int set, wrlock;
1179 
1180 			do {
1181 				start = random() & 127;
1182 				end = random() & 127;
1183 			} while (end <= start);
1184 
1185 			set = random() & 1;
1186 			wrlock = random() & 1;
1187 
1188 			len = end - start;
1189 			fl.l_start = start;
1190 			fl.l_len = len;
1191 			fl.l_whence = SEEK_SET;
1192 			if (set)
1193 				fl.l_type = wrlock ? F_WRLCK : F_RDLCK;
1194 			else
1195 				fl.l_type = F_UNLCK;
1196 
1197 			itv.it_interval.tv_sec = 0;
1198 			itv.it_interval.tv_usec = 0;
1199 			itv.it_value.tv_sec = 0;
1200 			itv.it_value.tv_usec = 3000;
1201 			setitimer(ITIMER_REAL, &itv, NULL);
1202 
1203 			if (fcntl(fd, F_SETLKW, &fl) < 0) {
1204 				if (errno == EDEADLK || errno == EINTR) {
1205 					if (verbose) {
1206 						snprintf(outbuf, sizeof(outbuf),
1207 						    "%d[%d]: %s [%d .. %d] %s\n",
1208 						    id, j,
1209 						    set ? (wrlock ? "write lock"
1210 							: "read lock")
1211 						    : "unlock", start, end,
1212 						    errno == EDEADLK
1213 						    ? "deadlock"
1214 						    : "interrupted");
1215 						write(1, outbuf,
1216 						    strlen(outbuf));
1217 					}
1218 					continue;
1219 				} else {
1220 					perror("fcntl");
1221 				}
1222 			}
1223 
1224 			itv.it_interval.tv_sec = 0;
1225 			itv.it_interval.tv_usec = 0;
1226 			itv.it_value.tv_sec = 0;
1227 			itv.it_value.tv_usec = 0;
1228 			setitimer(ITIMER_REAL, &itv, NULL);
1229 
1230 			if (verbose) {
1231 				snprintf(outbuf, sizeof(outbuf),
1232 				    "%d[%d]: %s [%d .. %d] succeeded\n",
1233 				    id, j,
1234 				    set ? (wrlock ? "write lock" : "read lock")
1235 				    : "unlock", start, end);
1236 				write(1, outbuf, strlen(outbuf));
1237 			}
1238 
1239 			if (set) {
1240 				if (wrlock) {
1241 					/*
1242 					 * We got a write lock - write
1243 					 * our ID to each byte that we
1244 					 * managed to claim.
1245 					 */
1246 					for (i = start; i < end; i++)
1247 						map[i] = F_WRLCK;
1248 					memset(&buf[start], id, len);
1249 					if (pwrite(fd, &buf[start], len,
1250 						start) != len) {
1251 						printf("%d: short write\n", id);
1252 						exit(1);
1253 					}
1254 				} else {
1255 					/*
1256 					 * We got a read lock - read
1257 					 * the bytes which we claimed
1258 					 * so that we can check that
1259 					 * they don't change
1260 					 * unexpectedly.
1261 					 */
1262 					for (i = start; i < end; i++)
1263 						map[i] = F_RDLCK;
1264 					if (pread(fd, &buf[start], len,
1265 						start) != len) {
1266 						printf("%d: short read\n", id);
1267 						exit(1);
1268 					}
1269 				}
1270 			} else {
1271 				for (i = start; i < end; i++)
1272 					map[i] = F_UNLCK;
1273 			}
1274 
1275 			usleep(1000);
1276 
1277 			/*
1278 			 * Read back the whole region so that we can
1279 			 * check that all the bytes we have some kind
1280 			 * of claim to have the correct value.
1281 			 */
1282 			if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) {
1283 				printf("%d: short read\n", id);
1284 				exit(1);
1285 			}
1286 
1287 			for (i = 0; i < 128; i++) {
1288 				if (map[i] != F_UNLCK && buf[i] != tbuf[i]) {
1289 					snprintf(outbuf, sizeof(outbuf),
1290 					    "%d: byte %d expected %d, "
1291 					    "got %d\n", id, i, buf[i], tbuf[i]);
1292 					write(1, outbuf, strlen(outbuf));
1293 					exit(1);
1294 				}
1295 			}
1296 		}
1297 		if (verbose)
1298 			printf("%d[%d]: done\n", id, j);
1299 
1300 		exit(0);
1301 	}
1302 
1303 	status = 0;
1304 	for (i = 0; i < CHILD_COUNT; i++) {
1305 		status += safe_waitpid(pids[i]);
1306 	}
1307 	if (status)
1308 		FAIL(status != 0);
1309 
1310 	SUCCEED;
1311 }
1312 
1313 /*
1314  * Test 15 - flock(2) semantcs
1315  *
1316  * When a lock holder has a shared lock and attempts to upgrade that
1317  * shared lock to exclusive, it must drop the shared lock before
1318  * blocking on the exclusive lock.
1319  *
1320  * To test this, we first arrange for two shared locks on the file,
1321  * and then attempt to upgrade one of them to exclusive. This should
1322  * drop one of the shared locks and block. We interrupt the blocking
1323  * lock request and examine the lock state of the file after dropping
1324  * the other shared lock - there should be no active locks at this
1325  * point.
1326  */
1327 static int
1328 test15(int fd, __unused int argc, const __unused char **argv)
1329 {
1330 #ifdef LOCK_EX
1331 	/*
1332 	 * We create a child process to hold the lock which we will
1333 	 * test. We use a pipe to communicate with the child.
1334 	 *
1335 	 * Since we only have one file descriptors and lock ownership
1336 	 * for flock(2) goes with the file descriptor, we use fcntl to
1337 	 * set the child's shared lock.
1338 	 */
1339 	int pid;
1340 	int pfd[2];
1341 	struct flock fl;
1342 	char ch;
1343 	int res;
1344 
1345 	if (pipe(pfd) < 0)
1346 		err(1, "pipe");
1347 
1348 	pid = fork();
1349 	if (pid < 0)
1350 		err(1, "fork");
1351 
1352 	if (pid == 0) {
1353 		/*
1354 		 * We are the child. We set a shared lock and then
1355 		 * write one byte back to the parent to tell it. The
1356 		 * parent will kill us when its done.
1357 		 */
1358 		fl.l_start = 0;
1359 		fl.l_len = 0;
1360 		fl.l_type = F_RDLCK;
1361 		fl.l_whence = SEEK_SET;
1362 		if (fcntl(fd, F_SETLK, &fl) < 0)
1363 			err(1, "fcntl(F_SETLK) (child)");
1364 		if (write(pfd[1], "a", 1) < 0)
1365 			err(1, "writing to pipe (child)");
1366 		pause();
1367 		exit(0);
1368 	}
1369 
1370 	/*
1371 	 * Wait until the child has set its lock and then perform the
1372 	 * test.
1373 	 */
1374 	if (read(pfd[0], &ch, 1) != 1)
1375 		err(1, "reading from pipe (child)");
1376 
1377 	(void)dup(fd);
1378 	if (flock(fd, LOCK_SH) < 0)
1379 		err(1, "flock shared");
1380 
1381 	/*
1382 	 * flock should wait until the alarm and then return -1 with
1383 	 * errno set to EINTR.
1384 	 */
1385 	printf("15 - flock(2) semantics: ");
1386 
1387 	alarm(1);
1388 	flock(fd, LOCK_EX);
1389 
1390 	/*
1391 	 * Kill the child to force it to drop its locks.
1392 	 */
1393 	kill(pid, SIGTERM);
1394 	safe_waitpid(pid);
1395 
1396 	fl.l_start = 0;
1397 	fl.l_len = 0;
1398 	fl.l_type = F_WRLCK;
1399 	fl.l_whence = SEEK_SET;
1400 	res = fcntl(fd, F_GETLK, &fl);
1401 
1402 	close(pfd[0]);
1403 	close(pfd[1]);
1404 	FAIL(res != 0);
1405 	FAIL(fl.l_type != F_UNLCK);
1406 
1407 	SUCCEED;
1408 #else
1409 	return 0;
1410 #endif
1411 }
1412 
1413 struct test_ctx {
1414 	struct flock tc_fl;
1415 	int tc_fd;
1416 };
1417 
1418 static void *
1419 test16_func(void *tc_in)
1420 {
1421 	uintptr_t error;
1422 	struct test_ctx *tc = tc_in;
1423 
1424 	error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl);
1425 
1426 	pthread_exit((void *)error);
1427 }
1428 
1429 #define THREADS 10
1430 
1431 /*
1432  * Test 16 - F_SETLKW from two threads
1433  *
1434  * If two threads within a process are blocked on a lock and the lock
1435  * is granted, make sure things are sane.
1436  */
1437 static int
1438 test16(int fd, __unused int argc, const __unused char **argv)
1439 {
1440 	/*
1441 	 * We create a child process to hold the lock which we will
1442 	 * test. We use a pipe to communicate with the child.
1443 	 */
1444 	int pid;
1445 	int pfd[2];
1446 	struct test_ctx tc = { .tc_fd = fd };
1447 	char ch;
1448 	int i;
1449 	int error;
1450 	pthread_t thr[THREADS];
1451 
1452 	if (pipe(pfd) < 0)
1453 		err(1, "pipe");
1454 
1455 	tc.tc_fl.l_start = 0;
1456 	tc.tc_fl.l_len = 0;
1457 	tc.tc_fl.l_type = F_WRLCK;
1458 	tc.tc_fl.l_whence = SEEK_SET;
1459 
1460 	pid = fork();
1461 	if (pid < 0)
1462 		err(1, "fork");
1463 
1464 	if (pid == 0) {
1465 		/*
1466 		 * We are the child. We set a write lock and then
1467 		 * write one byte back to the parent to tell it. The
1468 		 * parent will kill us when its done.
1469 		 */
1470 		if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0)
1471 			err(1, "F_SETLK (child)");
1472 		if (write(pfd[1], "a", 1) < 0)
1473 			err(1, "writing to pipe (child)");
1474 		pause();
1475 		exit(0);
1476 	}
1477 
1478 	/*
1479 	 * Wait until the child has set its lock and then perform the
1480 	 * test.
1481 	 */
1482 	if (read(pfd[0], &ch, 1) != 1)
1483 		err(1, "reading from pipe (child)");
1484 
1485 	/*
1486 	 * fcntl should wait until the alarm and then return -1 with
1487 	 * errno set to EINTR.
1488 	 */
1489 	printf("16 - F_SETLKW on locked region by two threads: ");
1490 
1491 	for (i = 0; i < THREADS; i++) {
1492 		error = pthread_create(&thr[i], NULL, test16_func, &tc);
1493 		if (error)
1494 			err(1, "pthread_create");
1495 	}
1496 
1497 	/*
1498 	 * Sleep, then kill the child. This makes me a little sad, but it's
1499 	 * tricky to tell whether the threads are all really blocked by this
1500 	 * point.
1501 	 */
1502 	sleep(1);
1503 	kill(pid, SIGTERM);
1504 	safe_waitpid(pid);
1505 	close(pfd[0]);
1506 	close(pfd[1]);
1507 
1508 	for (i = 0; i < THREADS; i++) {
1509 		void *res;
1510 		error = pthread_join(thr[i], &res);
1511 		if (error)
1512 			err(1, "pthread_join");
1513 		FAIL((uintptr_t)res != 0);
1514 	}
1515 
1516 	SUCCEED;
1517 }
1518 
1519 struct test {
1520 	int (*testfn)(int, int, const char **);	/* function to perform the test */
1521 	int num;		/* test number */
1522 	int intr;		/* non-zero if the test interrupts a lock */
1523 };
1524 
1525 static struct test tests[] = {
1526 	{	test1,		1,	0	},
1527 	{	test2,		2,	0	},
1528 	{	test3,		3,	1	},
1529 	{	test4,		4,	0	},
1530 	{	test5,		5,	1	},
1531 	{	test6,		6,	1	},
1532 	{	test7,		7,	0	},
1533 	{	test8,		8,	0	},
1534 	{	test9,		9,	0	},
1535 	{	test10,		10,	0	},
1536 	{	test11,		11,	1	},
1537 	{	test12,		12,	0	},
1538 	{	test13,		13,	1	},
1539 	{	test14,		14,	0	},
1540 	{	test15,		15,	1	},
1541 	{	test16,		16,	1	},
1542 };
1543 
1544 int
1545 main(int argc, const char *argv[])
1546 {
1547 	int testnum;
1548 	int fd;
1549 	int nointr;
1550 	unsigned i;
1551 	struct sigaction sa;
1552 	int test_argc;
1553 	const char **test_argv;
1554 
1555 	if (argc < 2) {
1556 		errx(1, "usage: flock <directory> [test number] ...");
1557 	}
1558 
1559 	fd = make_file(argv[1], 1024);
1560 	if (argc >= 3) {
1561 		testnum = strtol(argv[2], NULL, 0);
1562 		test_argc = argc - 2;
1563 		test_argv = argv + 2;
1564 	} else {
1565 		testnum = 0;
1566 		test_argc = 0;
1567 		test_argv = NULL;
1568 	}
1569 
1570 	sa.sa_handler = ignore_alarm;
1571 	sigemptyset(&sa.sa_mask);
1572 	sa.sa_flags = 0;
1573 	sigaction(SIGALRM, &sa, 0);
1574 
1575 	nointr = 0;
1576 #if defined(__FreeBSD__) && __FreeBSD_version < 800040
1577 	{
1578 		/*
1579 		 * FreeBSD with userland NLM can't interrupt a blocked
1580 		 * lock request on an NFS mounted filesystem.
1581 		 */
1582 		struct statfs st;
1583 		fstatfs(fd, &st);
1584 		nointr = !strcmp(st.f_fstypename, "nfs");
1585 	}
1586 #endif
1587 
1588 	for (i = 0; i < nitems(tests); i++) {
1589 		if (tests[i].intr && nointr)
1590 			continue;
1591 		if (!testnum || tests[i].num == testnum)
1592 			tests[i].testfn(fd, test_argc, test_argv);
1593 	}
1594 
1595 	return 0;
1596 }
1597