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