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