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