190221f91SCody Peter Mello /*
290221f91SCody Peter Mello * This file and its contents are supplied under the terms of the
390221f91SCody Peter Mello * Common Development and Distribution License ("CDDL"), version 1.0.
490221f91SCody Peter Mello * You may only use this file in accordance with the terms of version
590221f91SCody Peter Mello * 1.0 of the CDDL.
690221f91SCody Peter Mello *
790221f91SCody Peter Mello * A full copy of the text of the CDDL should have accompanied this
890221f91SCody Peter Mello * source. A copy of the CDDL is also available via the Internet at
990221f91SCody Peter Mello * http://www.illumos.org/license/CDDL.
1090221f91SCody Peter Mello */
1190221f91SCody Peter Mello
1290221f91SCody Peter Mello /*
13*44bf619dSJohn Levon * Copyright 2019 Joyent, Inc.
1490221f91SCody Peter Mello */
1590221f91SCody Peter Mello
1690221f91SCody Peter Mello /*
1790221f91SCody Peter Mello * Validate various fcntl(2) and flock(3C) operations.
1890221f91SCody Peter Mello */
1990221f91SCody Peter Mello
2090221f91SCody Peter Mello #include "util.h"
2190221f91SCody Peter Mello #include <err.h>
2290221f91SCody Peter Mello #include <errno.h>
2390221f91SCody Peter Mello #include <fcntl.h>
2490221f91SCody Peter Mello #include <libgen.h>
2590221f91SCody Peter Mello #include <signal.h>
2690221f91SCody Peter Mello #include <stdlib.h>
2790221f91SCody Peter Mello #include <strings.h>
2890221f91SCody Peter Mello #include <sys/debug.h>
2990221f91SCody Peter Mello #include <sys/file.h>
3090221f91SCody Peter Mello #include <sys/stat.h>
3190221f91SCody Peter Mello #include <sys/wait.h>
3290221f91SCody Peter Mello #include <unistd.h>
3390221f91SCody Peter Mello
3490221f91SCody Peter Mello
3590221f91SCody Peter Mello #define LOCKFILE_FMT "/tmp/.lockfile-%s-%ld"
3690221f91SCody Peter Mello #define LOCKDIR_FMT "/tmp/.lockdir-%s-%ld"
3790221f91SCody Peter Mello
3890221f91SCody Peter Mello typedef struct lockinfo {
3990221f91SCody Peter Mello char *lf_name;
4090221f91SCody Peter Mello char *lf_path;
4190221f91SCody Peter Mello int lf_fd;
4290221f91SCody Peter Mello } lockinfo_t;
4390221f91SCody Peter Mello
4490221f91SCody Peter Mello
4590221f91SCody Peter Mello static void assert_write_locked_by(lockinfo_t *, pid_t);
4690221f91SCody Peter Mello static void assert_read_locked_by(lockinfo_t *, pid_t);
4790221f91SCody Peter Mello static void assert_unlocked(lockinfo_t *);
4890221f91SCody Peter Mello static void assert_all_unlocked(void);
4990221f91SCody Peter Mello
5090221f91SCody Peter Mello static int flock_copyfil(lockinfo_t *, lockinfo_t *);
5190221f91SCody Peter Mello static int flock_mkfil(lockinfo_t *);
5290221f91SCody Peter Mello static int flock_mkdir(lockinfo_t *);
5390221f91SCody Peter Mello static void flock_rminfo(lockinfo_t *);
5490221f91SCody Peter Mello
5590221f91SCody Peter Mello static void flock_fcntl(lockinfo_t *lf, int cmd, struct flock *fl);
5690221f91SCody Peter Mello static void flock_run(lock_style_t, boolean_t, lockinfo_t *,
5790221f91SCody Peter Mello pid_t *, int[]);
5890221f91SCody Peter Mello static int flock_wait(pid_t pid);
5990221f91SCody Peter Mello static void flock_cleanup_child(pid_t, int []);
6090221f91SCody Peter Mello
6190221f91SCody Peter Mello static void flock_test_invalid(lockinfo_t *, int, short, short,
6290221f91SCody Peter Mello off_t, off_t);
639c7f1ae0SJerry Jelinek static void flock_test_invalid64(lockinfo_t *, int, short, short,
649c7f1ae0SJerry Jelinek off_t, off_t);
6590221f91SCody Peter Mello static void flock_test_exclusive(lock_style_t, lock_style_t,
6690221f91SCody Peter Mello lockinfo_t *, lockinfo_t *, boolean_t);
6790221f91SCody Peter Mello static void flock_test_shared(lock_style_t, lock_style_t, lockinfo_t *,
6890221f91SCody Peter Mello lockinfo_t *, boolean_t);
6990221f91SCody Peter Mello static void flock_test_upgrade_downgrade(void);
7090221f91SCody Peter Mello
7190221f91SCody Peter Mello static char *acqprog = NULL;
7290221f91SCody Peter Mello
7390221f91SCody Peter Mello static lockinfo_t flock_fileA = { "a", NULL, -1 };
7490221f91SCody Peter Mello static lockinfo_t flock_fileB = { "b", NULL, -1 };
7590221f91SCody Peter Mello static lockinfo_t flock_dirA = { "a", NULL, -1 };
7690221f91SCody Peter Mello static lockinfo_t flock_dirB = { "b", NULL, -1 };
7790221f91SCody Peter Mello
7890221f91SCody Peter Mello
7990221f91SCody Peter Mello static short cmds[8] = {
8090221f91SCody Peter Mello F_SETLK, F_SETLKW, F_GETLK,
8190221f91SCody Peter Mello F_OFD_SETLK, F_OFD_SETLKW, F_OFD_GETLK,
8290221f91SCody Peter Mello F_FLOCK, F_FLOCKW
8390221f91SCody Peter Mello };
8490221f91SCody Peter Mello
859c7f1ae0SJerry Jelinek static short cmds64[3] = {
869c7f1ae0SJerry Jelinek F_OFD_SETLK64, F_OFD_SETLKW64, F_OFD_GETLK64
879c7f1ae0SJerry Jelinek };
889c7f1ae0SJerry Jelinek
8990221f91SCody Peter Mello
9090221f91SCody Peter Mello static void
flock_kill(pid_t pid)9190221f91SCody Peter Mello flock_kill(pid_t pid)
9290221f91SCody Peter Mello {
9390221f91SCody Peter Mello while (kill(pid, SIGKILL) == -1) {
9490221f91SCody Peter Mello if (errno == EINTR)
9590221f91SCody Peter Mello continue;
9690221f91SCody Peter Mello
9790221f91SCody Peter Mello err(EXIT_FAILURE, "kill failed");
9890221f91SCody Peter Mello }
9990221f91SCody Peter Mello }
10090221f91SCody Peter Mello
10190221f91SCody Peter Mello
10290221f91SCody Peter Mello static void
flock_fcntl(lockinfo_t * lf,int cmd,struct flock * fl)10390221f91SCody Peter Mello flock_fcntl(lockinfo_t *lf, int cmd, struct flock *fl)
10490221f91SCody Peter Mello {
10590221f91SCody Peter Mello if (fcntl(lf->lf_fd, cmd, fl) == -1) {
10690221f91SCody Peter Mello err(EXIT_FAILURE, "fcntl failed");
10790221f91SCody Peter Mello }
10890221f91SCody Peter Mello }
10990221f91SCody Peter Mello
11090221f91SCody Peter Mello
11190221f91SCody Peter Mello static void
assert_write_locked_by(lockinfo_t * lf,pid_t pid)11290221f91SCody Peter Mello assert_write_locked_by(lockinfo_t *lf, pid_t pid)
11390221f91SCody Peter Mello {
11490221f91SCody Peter Mello struct flock fl;
11590221f91SCody Peter Mello
11690221f91SCody Peter Mello flock_reinit(&fl, F_WRLCK);
11790221f91SCody Peter Mello flock_fcntl(lf, F_GETLK, &fl);
11890221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
11990221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
12090221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
12190221f91SCody Peter Mello
12290221f91SCody Peter Mello flock_reinit(&fl, F_WRLCK);
12390221f91SCody Peter Mello flock_fcntl(lf, F_OFD_GETLK, &fl);
12490221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
12590221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
12690221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
12790221f91SCody Peter Mello
12890221f91SCody Peter Mello flock_reinit(&fl, F_RDLCK);
12990221f91SCody Peter Mello flock_fcntl(lf, F_GETLK, &fl);
13090221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
13190221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
13290221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
13390221f91SCody Peter Mello
13490221f91SCody Peter Mello flock_reinit(&fl, F_RDLCK);
13590221f91SCody Peter Mello flock_fcntl(lf, F_OFD_GETLK, &fl);
13690221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
13790221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
13890221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
13990221f91SCody Peter Mello }
14090221f91SCody Peter Mello
14190221f91SCody Peter Mello
14290221f91SCody Peter Mello static void
assert_read_locked_by(lockinfo_t * lf,pid_t pid)14390221f91SCody Peter Mello assert_read_locked_by(lockinfo_t *lf, pid_t pid)
14490221f91SCody Peter Mello {
14590221f91SCody Peter Mello struct flock fl;
14690221f91SCody Peter Mello
14790221f91SCody Peter Mello flock_reinit(&fl, F_WRLCK);
14890221f91SCody Peter Mello flock_fcntl(lf, F_GETLK, &fl);
14990221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_RDLCK, short);
15090221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
15190221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
15290221f91SCody Peter Mello
15390221f91SCody Peter Mello flock_reinit(&fl, F_WRLCK);
15490221f91SCody Peter Mello flock_fcntl(lf, F_OFD_GETLK, &fl);
15590221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_RDLCK, short);
15690221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
15790221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
15890221f91SCody Peter Mello
15990221f91SCody Peter Mello flock_reinit(&fl, F_RDLCK);
16090221f91SCody Peter Mello flock_fcntl(lf, F_GETLK, &fl);
16190221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
16290221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
16390221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
16490221f91SCody Peter Mello
16590221f91SCody Peter Mello flock_reinit(&fl, F_RDLCK);
16690221f91SCody Peter Mello flock_fcntl(lf, F_OFD_GETLK, &fl);
16790221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
16890221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
16990221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
17090221f91SCody Peter Mello }
17190221f91SCody Peter Mello
17290221f91SCody Peter Mello static void
assert_unlocked(lockinfo_t * lf)17390221f91SCody Peter Mello assert_unlocked(lockinfo_t *lf)
17490221f91SCody Peter Mello {
17590221f91SCody Peter Mello struct flock fl;
17690221f91SCody Peter Mello
17790221f91SCody Peter Mello flock_reinit(&fl, F_WRLCK);
17890221f91SCody Peter Mello flock_fcntl(lf, F_GETLK, &fl);
17990221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
18090221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
18190221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
18290221f91SCody Peter Mello
18390221f91SCody Peter Mello flock_reinit(&fl, F_WRLCK);
18490221f91SCody Peter Mello flock_fcntl(lf, F_OFD_GETLK, &fl);
18590221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
18690221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
18790221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
18890221f91SCody Peter Mello
18990221f91SCody Peter Mello flock_reinit(&fl, F_RDLCK);
19090221f91SCody Peter Mello flock_fcntl(lf, F_GETLK, &fl);
19190221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
19290221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
19390221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
19490221f91SCody Peter Mello
19590221f91SCody Peter Mello flock_reinit(&fl, F_RDLCK);
19690221f91SCody Peter Mello flock_fcntl(lf, F_OFD_GETLK, &fl);
19790221f91SCody Peter Mello VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
19890221f91SCody Peter Mello VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
19990221f91SCody Peter Mello VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
20090221f91SCody Peter Mello }
20190221f91SCody Peter Mello
20290221f91SCody Peter Mello
20390221f91SCody Peter Mello static void
assert_all_unlocked(void)20490221f91SCody Peter Mello assert_all_unlocked(void)
20590221f91SCody Peter Mello {
20690221f91SCody Peter Mello assert_unlocked(&flock_fileA);
20790221f91SCody Peter Mello assert_unlocked(&flock_fileB);
20890221f91SCody Peter Mello assert_unlocked(&flock_dirA);
20990221f91SCody Peter Mello assert_unlocked(&flock_dirB);
21090221f91SCody Peter Mello }
21190221f91SCody Peter Mello
21290221f91SCody Peter Mello
21390221f91SCody Peter Mello static int
flock_copyfil(lockinfo_t * src,lockinfo_t * dst)21490221f91SCody Peter Mello flock_copyfil(lockinfo_t *src, lockinfo_t *dst)
21590221f91SCody Peter Mello {
21690221f91SCody Peter Mello dst->lf_name = NULL;
21790221f91SCody Peter Mello dst->lf_path = NULL;
21890221f91SCody Peter Mello if ((dst->lf_fd = open(src->lf_path, O_RDWR)) == -1) {
21990221f91SCody Peter Mello warn("Failed to open %s", src->lf_path);
22090221f91SCody Peter Mello return (-1);
22190221f91SCody Peter Mello }
22290221f91SCody Peter Mello
22390221f91SCody Peter Mello return (0);
22490221f91SCody Peter Mello }
22590221f91SCody Peter Mello
22690221f91SCody Peter Mello
22790221f91SCody Peter Mello static int
flock_mkfil(lockinfo_t * lf)22890221f91SCody Peter Mello flock_mkfil(lockinfo_t *lf)
22990221f91SCody Peter Mello {
23090221f91SCody Peter Mello if (asprintf(&lf->lf_path, LOCKFILE_FMT, lf->lf_name, getpid()) < 0) {
23190221f91SCody Peter Mello warnx("Failed to generate lockfile name");
23290221f91SCody Peter Mello return (-1);
23390221f91SCody Peter Mello }
23490221f91SCody Peter Mello
23590221f91SCody Peter Mello if ((lf->lf_fd = open(lf->lf_path, O_RDWR|O_CREAT, 0600)) == -1) {
23690221f91SCody Peter Mello warn("Failed to open %s", lf->lf_path);
23790221f91SCody Peter Mello return (-1);
23890221f91SCody Peter Mello }
23990221f91SCody Peter Mello
24090221f91SCody Peter Mello return (0);
24190221f91SCody Peter Mello }
24290221f91SCody Peter Mello
24390221f91SCody Peter Mello
24490221f91SCody Peter Mello static int
flock_mkdir(lockinfo_t * lf)24590221f91SCody Peter Mello flock_mkdir(lockinfo_t *lf)
24690221f91SCody Peter Mello {
24790221f91SCody Peter Mello if (asprintf(&lf->lf_path, LOCKDIR_FMT, lf->lf_name, getpid()) < 0) {
24890221f91SCody Peter Mello warnx("Failed to generate lockfile name");
24990221f91SCody Peter Mello return (-1);
25090221f91SCody Peter Mello }
25190221f91SCody Peter Mello
25290221f91SCody Peter Mello if (mkdir(lf->lf_path, 0700) == -1) {
25390221f91SCody Peter Mello warn("Failed to make %s", lf->lf_path);
25490221f91SCody Peter Mello return (-1);
25590221f91SCody Peter Mello }
25690221f91SCody Peter Mello
25790221f91SCody Peter Mello if ((lf->lf_fd = open(lf->lf_path, O_RDONLY)) == -1) {
25890221f91SCody Peter Mello warn("Failed to open %s", lf->lf_path);
25990221f91SCody Peter Mello return (-1);
26090221f91SCody Peter Mello }
26190221f91SCody Peter Mello
26290221f91SCody Peter Mello return (0);
26390221f91SCody Peter Mello }
26490221f91SCody Peter Mello
26590221f91SCody Peter Mello
26690221f91SCody Peter Mello static void
flock_rminfo(lockinfo_t * lf)26790221f91SCody Peter Mello flock_rminfo(lockinfo_t *lf)
26890221f91SCody Peter Mello {
26990221f91SCody Peter Mello if (lf->lf_fd != -1) {
27090221f91SCody Peter Mello (void) close(lf->lf_fd);
27190221f91SCody Peter Mello }
27290221f91SCody Peter Mello if (lf->lf_path != NULL) {
27390221f91SCody Peter Mello (void) unlink(lf->lf_path);
27490221f91SCody Peter Mello free(lf->lf_path);
27590221f91SCody Peter Mello }
27690221f91SCody Peter Mello }
27790221f91SCody Peter Mello
27890221f91SCody Peter Mello
27990221f91SCody Peter Mello static void
flock_run(lock_style_t style,boolean_t is_exclusive,lockinfo_t * lf,pid_t * pid,int fds[])28090221f91SCody Peter Mello flock_run(lock_style_t style, boolean_t is_exclusive, lockinfo_t *lf,
28190221f91SCody Peter Mello pid_t *pid, int fds[])
28290221f91SCody Peter Mello {
28390221f91SCody Peter Mello char *stylestr = flock_stylestr(style);
28490221f91SCody Peter Mello char *modestr = is_exclusive ? "exclusive" : "shared";
28590221f91SCody Peter Mello char *argv[5] = { acqprog, stylestr, modestr, lf->lf_path, NULL };
28690221f91SCody Peter Mello int ret = pipe(fds);
28790221f91SCody Peter Mello if (ret == -1) {
28890221f91SCody Peter Mello err(EXIT_FAILURE, "pipe failed");
28990221f91SCody Peter Mello }
29090221f91SCody Peter Mello
29190221f91SCody Peter Mello *pid = fork();
29290221f91SCody Peter Mello if (*pid == (pid_t)-1) {
29390221f91SCody Peter Mello err(EXIT_FAILURE, "fork failed");
29490221f91SCody Peter Mello } else if (*pid == (pid_t)0) {
29590221f91SCody Peter Mello /* Set up pipe for communicating with child */
29690221f91SCody Peter Mello ret = dup2(fds[1], 0);
29790221f91SCody Peter Mello if (ret == -1) {
29890221f91SCody Peter Mello err(EXIT_FAILURE, "dup2 failed");
29990221f91SCody Peter Mello }
30090221f91SCody Peter Mello ret = dup2(fds[1], 1);
30190221f91SCody Peter Mello if (ret == -1) {
30290221f91SCody Peter Mello err(EXIT_FAILURE, "dup2 failed");
30390221f91SCody Peter Mello }
30490221f91SCody Peter Mello closefrom(3);
30590221f91SCody Peter Mello
30690221f91SCody Peter Mello (void) execv(acqprog, argv);
30790221f91SCody Peter Mello err(EXIT_FAILURE, "Failed to execute %s", acqprog);
30890221f91SCody Peter Mello }
30990221f91SCody Peter Mello }
31090221f91SCody Peter Mello
31190221f91SCody Peter Mello
31290221f91SCody Peter Mello static int
flock_wait(pid_t pid)31390221f91SCody Peter Mello flock_wait(pid_t pid)
31490221f91SCody Peter Mello {
31590221f91SCody Peter Mello int childstat = 0;
31690221f91SCody Peter Mello
31790221f91SCody Peter Mello while (waitpid(pid, &childstat, 0) == -1) {
31890221f91SCody Peter Mello if (errno == EINTR)
31990221f91SCody Peter Mello continue;
32090221f91SCody Peter Mello
32190221f91SCody Peter Mello err(EXIT_FAILURE, "Failed to wait on child");
32290221f91SCody Peter Mello }
32390221f91SCody Peter Mello
32490221f91SCody Peter Mello if (WIFEXITED(childstat)) {
32590221f91SCody Peter Mello return (WEXITSTATUS(childstat));
32690221f91SCody Peter Mello } else if (WIFSIGNALED(childstat)) {
32790221f91SCody Peter Mello return (1);
32890221f91SCody Peter Mello } else {
32990221f91SCody Peter Mello abort();
33090221f91SCody Peter Mello }
33190221f91SCody Peter Mello }
33290221f91SCody Peter Mello
33390221f91SCody Peter Mello
33490221f91SCody Peter Mello static void
flock_cleanup_child(pid_t pid,int fds[])33590221f91SCody Peter Mello flock_cleanup_child(pid_t pid, int fds[])
33690221f91SCody Peter Mello {
33790221f91SCody Peter Mello (void) flock_wait(pid);
33890221f91SCody Peter Mello (void) close(fds[0]);
33990221f91SCody Peter Mello (void) close(fds[1]);
34090221f91SCody Peter Mello }
34190221f91SCody Peter Mello
34290221f91SCody Peter Mello
34390221f91SCody Peter Mello static void
flock_test_upgrade_downgrade(void)34490221f91SCody Peter Mello flock_test_upgrade_downgrade(void)
34590221f91SCody Peter Mello {
34690221f91SCody Peter Mello lockinfo_t afd1, afd2, afd3;
34790221f91SCody Peter Mello pid_t pid;
34890221f91SCody Peter Mello int fds[2];
34990221f91SCody Peter Mello
35090221f91SCody Peter Mello VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
35190221f91SCody Peter Mello VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
35290221f91SCody Peter Mello VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
35390221f91SCody Peter Mello
35490221f91SCody Peter Mello flock_log("Acquiring shared locks 1, 2 and 3...");
35590221f91SCody Peter Mello VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
35690221f91SCody Peter Mello VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
35790221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
35890221f91SCody Peter Mello assert_read_locked_by(&flock_fileA, -1);
35990221f91SCody Peter Mello flock_log(" ok\n");
36090221f91SCody Peter Mello
36190221f91SCody Peter Mello flock_log("Upgrading lock 3 should fail w/ EWOULDBLOCK...");
36290221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
36390221f91SCody Peter Mello VERIFY3U(errno, ==, EWOULDBLOCK);
36490221f91SCody Peter Mello assert_read_locked_by(&flock_fileA, -1);
36590221f91SCody Peter Mello flock_log(" ok\n");
36690221f91SCody Peter Mello
36790221f91SCody Peter Mello flock_log("Upgrading 3 should succeed after releasing locks 1 & 2...");
36890221f91SCody Peter Mello VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
36990221f91SCody Peter Mello VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
37090221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
37190221f91SCody Peter Mello assert_write_locked_by(&flock_fileA, -1);
37290221f91SCody Peter Mello flock_log(" ok\n");
37390221f91SCody Peter Mello
37490221f91SCody Peter Mello
37590221f91SCody Peter Mello flock_log("Starting up child, then downgrading lock 3 to shared...");
37690221f91SCody Peter Mello flock_run(LSTYLE_FLOCK, B_FALSE, &flock_fileA, &pid, fds);
37790221f91SCody Peter Mello VERIFY3_IMPL(flock_nodata(fds[0]), ==, B_TRUE, boolean_t);
37890221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
37990221f91SCody Peter Mello flock_block(fds[0]);
38090221f91SCody Peter Mello assert_read_locked_by(&flock_fileA, -1);
38190221f91SCody Peter Mello flock_log(" ok\n");
38290221f91SCody Peter Mello
38390221f91SCody Peter Mello flock_log("Releasing child and upgrading...");
38490221f91SCody Peter Mello flock_alert(fds[0]);
38590221f91SCody Peter Mello flock_cleanup_child(pid, fds);
38690221f91SCody Peter Mello assert_read_locked_by(&flock_fileA, -1);
38790221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
38890221f91SCody Peter Mello assert_write_locked_by(&flock_fileA, -1);
38990221f91SCody Peter Mello flock_log(" ok\n");
39090221f91SCody Peter Mello
39190221f91SCody Peter Mello flock_log("Releasing lock 3...");
39290221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
39390221f91SCody Peter Mello flock_rminfo(&afd1);
39490221f91SCody Peter Mello flock_rminfo(&afd2);
39590221f91SCody Peter Mello flock_rminfo(&afd3);
39690221f91SCody Peter Mello assert_all_unlocked();
39790221f91SCody Peter Mello flock_log(" ok\n");
39890221f91SCody Peter Mello }
39990221f91SCody Peter Mello
40090221f91SCody Peter Mello
40190221f91SCody Peter Mello static void
flock_test_invalid(lockinfo_t * lf,int cmd,short l_type,short l_whence,off_t l_start,off_t l_len)40290221f91SCody Peter Mello flock_test_invalid(lockinfo_t *lf, int cmd, short l_type, short l_whence,
40390221f91SCody Peter Mello off_t l_start, off_t l_len)
40490221f91SCody Peter Mello {
40590221f91SCody Peter Mello struct flock fl = {
40690221f91SCody Peter Mello .l_type = l_type,
40790221f91SCody Peter Mello .l_whence = l_whence,
40890221f91SCody Peter Mello .l_start = l_start,
40990221f91SCody Peter Mello .l_len = l_len
41090221f91SCody Peter Mello };
41190221f91SCody Peter Mello
41290221f91SCody Peter Mello flock_log("fcntl(fd, %s, { %hd, %hd, %ld, %ld, ... })...",
41390221f91SCody Peter Mello flock_cmdname(cmd), l_type, l_whence, l_start, l_len);
41490221f91SCody Peter Mello VERIFY3S(fcntl(lf->lf_fd, cmd, &fl), ==, -1);
41590221f91SCody Peter Mello VERIFY3U(errno, ==, EINVAL);
41690221f91SCody Peter Mello flock_log(" ok\n");
41790221f91SCody Peter Mello }
41890221f91SCody Peter Mello
4199c7f1ae0SJerry Jelinek static void
flock_test_invalid64(lockinfo_t * lf,int cmd,short l_type,short l_whence,off_t l_start,off_t l_len)4209c7f1ae0SJerry Jelinek flock_test_invalid64(lockinfo_t *lf, int cmd, short l_type, short l_whence,
4219c7f1ae0SJerry Jelinek off_t l_start, off_t l_len)
4229c7f1ae0SJerry Jelinek {
4239c7f1ae0SJerry Jelinek struct flock64 fl = {
4249c7f1ae0SJerry Jelinek .l_type = l_type,
4259c7f1ae0SJerry Jelinek .l_whence = l_whence,
4269c7f1ae0SJerry Jelinek .l_start = l_start,
4279c7f1ae0SJerry Jelinek .l_len = l_len
4289c7f1ae0SJerry Jelinek };
4299c7f1ae0SJerry Jelinek
4309c7f1ae0SJerry Jelinek flock_log("fcntl(fd, %s, { %hd, %hd, %ld, %ld, ... })...",
4319c7f1ae0SJerry Jelinek flock_cmdname(cmd), l_type, l_whence, l_start, l_len);
4329c7f1ae0SJerry Jelinek VERIFY3S(fcntl(lf->lf_fd, cmd, &fl), ==, -1);
4339c7f1ae0SJerry Jelinek VERIFY3U(errno, ==, EINVAL);
4349c7f1ae0SJerry Jelinek flock_log(" ok\n");
4359c7f1ae0SJerry Jelinek }
43690221f91SCody Peter Mello
43790221f91SCody Peter Mello static void
flock_test_exclusive(lock_style_t styleA,lock_style_t styleB,lockinfo_t * lock1,lockinfo_t * lock2,boolean_t kill_firstborn)43890221f91SCody Peter Mello flock_test_exclusive(lock_style_t styleA, lock_style_t styleB,
43990221f91SCody Peter Mello lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
44090221f91SCody Peter Mello {
44190221f91SCody Peter Mello pid_t pidA, pidB;
44290221f91SCody Peter Mello int fdsA[2], fdsB[2];
44390221f91SCody Peter Mello
44490221f91SCody Peter Mello flock_log("Running %s + %s tests (%s)...",
44590221f91SCody Peter Mello flock_stylename(styleA), flock_stylename(styleB),
44690221f91SCody Peter Mello kill_firstborn ? "kill child" : "child exits");
44790221f91SCody Peter Mello
44890221f91SCody Peter Mello /* Create child, and wait for it to acquire the lock */
44990221f91SCody Peter Mello flock_run(styleA, B_TRUE, lock1, &pidA, fdsA);
45090221f91SCody Peter Mello flock_block(fdsA[0]);
45190221f91SCody Peter Mello
45290221f91SCody Peter Mello /* Create second child, which shouldn't acquire & signal */
45390221f91SCody Peter Mello flock_run(styleB, B_TRUE, lock1, &pidB, fdsB);
45490221f91SCody Peter Mello VERIFY3_IMPL(flock_nodata(fdsB[0]), ==, B_TRUE, boolean_t);
45590221f91SCody Peter Mello
45690221f91SCody Peter Mello /* lock1 is blocked for reading and writing */
45790221f91SCody Peter Mello assert_write_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
45890221f91SCody Peter Mello assert_unlocked(lock2);
45990221f91SCody Peter Mello
46090221f91SCody Peter Mello /* Tell pidA to exit */
46190221f91SCody Peter Mello if (kill_firstborn) {
46290221f91SCody Peter Mello flock_kill(pidA);
46390221f91SCody Peter Mello } else {
46490221f91SCody Peter Mello flock_alert(fdsA[0]);
46590221f91SCody Peter Mello }
46690221f91SCody Peter Mello flock_cleanup_child(pidA, fdsA);
46790221f91SCody Peter Mello
46890221f91SCody Peter Mello /* Wait for pidB to signal us */
46990221f91SCody Peter Mello flock_block(fdsB[0]);
47090221f91SCody Peter Mello
47190221f91SCody Peter Mello /* lock1 is blocked for reading and writing */
47290221f91SCody Peter Mello assert_write_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
47390221f91SCody Peter Mello assert_unlocked(lock2);
47490221f91SCody Peter Mello
47590221f91SCody Peter Mello /* Tell pidB to exit */
47690221f91SCody Peter Mello flock_alert(fdsB[0]);
47790221f91SCody Peter Mello
47890221f91SCody Peter Mello flock_cleanup_child(pidB, fdsB);
47990221f91SCody Peter Mello
48090221f91SCody Peter Mello /*
48190221f91SCody Peter Mello * Tests after child has released lock
48290221f91SCody Peter Mello */
48390221f91SCody Peter Mello assert_all_unlocked();
48490221f91SCody Peter Mello
48590221f91SCody Peter Mello flock_log(" ok\n");
48690221f91SCody Peter Mello }
48790221f91SCody Peter Mello
48890221f91SCody Peter Mello
48990221f91SCody Peter Mello static void
flock_test_shared(lock_style_t styleA,lock_style_t styleB,lockinfo_t * lock1,lockinfo_t * lock2,boolean_t kill_firstborn)49090221f91SCody Peter Mello flock_test_shared(lock_style_t styleA, lock_style_t styleB,
49190221f91SCody Peter Mello lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
49290221f91SCody Peter Mello {
49390221f91SCody Peter Mello pid_t pidA, pidB;
49490221f91SCody Peter Mello int fdsA[2], fdsB[2];
49590221f91SCody Peter Mello
49690221f91SCody Peter Mello flock_log("Running %s + %s tests (%s)...",
49790221f91SCody Peter Mello flock_stylename(styleA), flock_stylename(styleB),
49890221f91SCody Peter Mello kill_firstborn ? "kill child" : "child exits");
49990221f91SCody Peter Mello
50090221f91SCody Peter Mello /* Create children, and wait for it to acquire the lock */
50190221f91SCody Peter Mello flock_run(styleB, B_FALSE, lock1, &pidB, fdsB);
50290221f91SCody Peter Mello flock_block(fdsB[0]);
50390221f91SCody Peter Mello flock_run(styleA, B_FALSE, lock1, &pidA, fdsA);
50490221f91SCody Peter Mello flock_block(fdsA[0]);
50590221f91SCody Peter Mello
50690221f91SCody Peter Mello /* testfileA is only blocked for writing */
50790221f91SCody Peter Mello assert_read_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
50890221f91SCody Peter Mello assert_unlocked(lock2);
50990221f91SCody Peter Mello
51090221f91SCody Peter Mello /* Tell pidA to exit */
51190221f91SCody Peter Mello if (kill_firstborn) {
51290221f91SCody Peter Mello flock_kill(pidA);
51390221f91SCody Peter Mello } else {
51490221f91SCody Peter Mello flock_alert(fdsA[0]);
51590221f91SCody Peter Mello }
51690221f91SCody Peter Mello flock_cleanup_child(pidA, fdsA);
51790221f91SCody Peter Mello
51890221f91SCody Peter Mello /* testfileA is still blocked for writing by pidB */
51990221f91SCody Peter Mello assert_read_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
52090221f91SCody Peter Mello assert_unlocked(lock2);
52190221f91SCody Peter Mello
52290221f91SCody Peter Mello /* Tell pidB to exit */
52390221f91SCody Peter Mello flock_alert(fdsB[0]);
52490221f91SCody Peter Mello flock_cleanup_child(pidB, fdsB);
52590221f91SCody Peter Mello
52690221f91SCody Peter Mello assert_all_unlocked();
52790221f91SCody Peter Mello
52890221f91SCody Peter Mello flock_log(" ok\n");
52990221f91SCody Peter Mello }
53090221f91SCody Peter Mello
53190221f91SCody Peter Mello
53290221f91SCody Peter Mello static void
flock_test_ofd_sameproc(void)53390221f91SCody Peter Mello flock_test_ofd_sameproc(void)
53490221f91SCody Peter Mello {
53590221f91SCody Peter Mello lockinfo_t afd1, afd2, afd3;
53690221f91SCody Peter Mello
53790221f91SCody Peter Mello VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
53890221f91SCody Peter Mello VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
53990221f91SCody Peter Mello VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
54090221f91SCody Peter Mello
54190221f91SCody Peter Mello flock_log("Acquiring first two shared locks...");
54290221f91SCody Peter Mello VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
54390221f91SCody Peter Mello VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
54490221f91SCody Peter Mello assert_read_locked_by(&flock_fileA, -1);
54590221f91SCody Peter Mello flock_log(" ok\n");
54690221f91SCody Peter Mello
54790221f91SCody Peter Mello flock_log("Acquiring an exclusive lock should fail w/ EWOULDBLOCK...");
54890221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
54990221f91SCody Peter Mello VERIFY3U(errno, ==, EWOULDBLOCK);
55090221f91SCody Peter Mello flock_log(" ok\n");
55190221f91SCody Peter Mello
55290221f91SCody Peter Mello flock_log("Releasing to acquire an exclusive lock...");
55390221f91SCody Peter Mello VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
55490221f91SCody Peter Mello VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
55590221f91SCody Peter Mello flock_log(" ok\n");
55690221f91SCody Peter Mello
55790221f91SCody Peter Mello flock_log("Acquiring an exclusive lock...");
55890221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
55990221f91SCody Peter Mello assert_write_locked_by(&flock_fileA, -1);
56090221f91SCody Peter Mello flock_log(" ok\n");
56190221f91SCody Peter Mello
56290221f91SCody Peter Mello flock_log("Acquiring a shared lock should fail w/ EWOULDBLOCK...");
56390221f91SCody Peter Mello VERIFY3S(flock(afd1.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
56490221f91SCody Peter Mello VERIFY3U(errno, ==, EWOULDBLOCK);
56590221f91SCody Peter Mello VERIFY3S(flock(afd2.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
56690221f91SCody Peter Mello VERIFY3U(errno, ==, EWOULDBLOCK);
56790221f91SCody Peter Mello flock_log(" ok\n");
56890221f91SCody Peter Mello
56990221f91SCody Peter Mello flock_log("Releasing exclusive lock...");
57090221f91SCody Peter Mello VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
57190221f91SCody Peter Mello assert_all_unlocked();
57290221f91SCody Peter Mello flock_log(" ok\n");
57390221f91SCody Peter Mello
57490221f91SCody Peter Mello flock_rminfo(&afd1);
57590221f91SCody Peter Mello flock_rminfo(&afd2);
57690221f91SCody Peter Mello flock_rminfo(&afd3);
57790221f91SCody Peter Mello }
57890221f91SCody Peter Mello
57990221f91SCody Peter Mello
58090221f91SCody Peter Mello static void
flock_runtests(void)58190221f91SCody Peter Mello flock_runtests(void)
58290221f91SCody Peter Mello {
58390221f91SCody Peter Mello lock_style_t first, second;
58490221f91SCody Peter Mello int i;
58590221f91SCody Peter Mello
58690221f91SCody Peter Mello flock_log("# Exclusive lock tests\n");
58790221f91SCody Peter Mello for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
58890221f91SCody Peter Mello for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
58990221f91SCody Peter Mello flock_test_exclusive(first, second,
59090221f91SCody Peter Mello &flock_fileA, &flock_fileB, B_TRUE);
59190221f91SCody Peter Mello flock_test_exclusive(first, second,
59290221f91SCody Peter Mello &flock_fileA, &flock_fileB, B_FALSE);
59390221f91SCody Peter Mello }
59490221f91SCody Peter Mello }
59590221f91SCody Peter Mello
59690221f91SCody Peter Mello flock_log("# Shared lock tests\n");
59790221f91SCody Peter Mello for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
59890221f91SCody Peter Mello for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
59990221f91SCody Peter Mello flock_test_shared(first, second,
60090221f91SCody Peter Mello &flock_fileA, &flock_fileB, B_TRUE);
60190221f91SCody Peter Mello flock_test_shared(first, second,
60290221f91SCody Peter Mello &flock_fileA, &flock_fileB, B_FALSE);
60390221f91SCody Peter Mello }
60490221f91SCody Peter Mello }
60590221f91SCody Peter Mello
60690221f91SCody Peter Mello flock_log("# flock(3C) directory lock tests\n");
60790221f91SCody Peter Mello flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
60890221f91SCody Peter Mello &flock_dirA, &flock_dirB, B_TRUE);
60990221f91SCody Peter Mello flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
61090221f91SCody Peter Mello &flock_dirA, &flock_dirB, B_FALSE);
61190221f91SCody Peter Mello flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
61290221f91SCody Peter Mello &flock_dirA, &flock_dirB, B_TRUE);
61390221f91SCody Peter Mello flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
61490221f91SCody Peter Mello &flock_dirA, &flock_dirB, B_FALSE);
61590221f91SCody Peter Mello
61690221f91SCody Peter Mello
61790221f91SCody Peter Mello flock_log("# Invalid fcntl(2) parameters tests\n");
61890221f91SCody Peter Mello for (i = 0; i < sizeof (cmds) / sizeof (short); i++) {
61990221f91SCody Peter Mello flock_test_invalid(&flock_fileA, cmds[i], 200, 0, 0, 0);
62090221f91SCody Peter Mello flock_test_invalid(&flock_fileA, cmds[i], -1, 0, 0, 0);
62190221f91SCody Peter Mello }
62290221f91SCody Peter Mello for (i = 3; i < sizeof (cmds) / sizeof (short); i++) {
62390221f91SCody Peter Mello flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 1, 0, 0);
62490221f91SCody Peter Mello flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 1, 0);
62590221f91SCody Peter Mello flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 0, 1);
62690221f91SCody Peter Mello }
6279c7f1ae0SJerry Jelinek for (i = 0; i < sizeof (cmds64) / sizeof (short); i++) {
6289c7f1ae0SJerry Jelinek flock_test_invalid64(&flock_fileA, cmds64[i], F_WRLCK, 1, 0, 0);
6299c7f1ae0SJerry Jelinek flock_test_invalid64(&flock_fileA, cmds64[i], F_WRLCK, 0, 1, 0);
6309c7f1ae0SJerry Jelinek flock_test_invalid64(&flock_fileA, cmds64[i], F_WRLCK, 0, 0, 1);
6319c7f1ae0SJerry Jelinek }
63290221f91SCody Peter Mello
63390221f91SCody Peter Mello flock_log("# Testing that multiple OFD locks work in a process\n");
63490221f91SCody Peter Mello flock_test_ofd_sameproc();
63590221f91SCody Peter Mello
63690221f91SCody Peter Mello flock_log("# Testing flock(3C) upgrade/downgrade tests\n");
63790221f91SCody Peter Mello flock_test_upgrade_downgrade();
63890221f91SCody Peter Mello }
63990221f91SCody Peter Mello
64090221f91SCody Peter Mello
64190221f91SCody Peter Mello int
main(int argc,char * argv[])64290221f91SCody Peter Mello main(int argc, char *argv[])
64390221f91SCody Peter Mello {
64490221f91SCody Peter Mello char *basestr, *suffix, *dirstr, *dirpath;
64590221f91SCody Peter Mello pid_t testrunner;
64690221f91SCody Peter Mello int exval;
64790221f91SCody Peter Mello
64890221f91SCody Peter Mello LOG = B_TRUE;
64990221f91SCody Peter Mello
65090221f91SCody Peter Mello if (argc < 1) {
65190221f91SCody Peter Mello errx(EXIT_FAILURE, "Can't find program name!");
65290221f91SCody Peter Mello }
65390221f91SCody Peter Mello
65490221f91SCody Peter Mello dirstr = strdup(argv[0]);
65590221f91SCody Peter Mello dirpath = dirname(dirstr);
65690221f91SCody Peter Mello basestr = strdup(argv[0]);
65790221f91SCody Peter Mello suffix = basename(basestr);
65890221f91SCody Peter Mello
65990221f91SCody Peter Mello while (*suffix != '.' && *suffix != '\0') {
66090221f91SCody Peter Mello suffix += 1;
66190221f91SCody Peter Mello }
66290221f91SCody Peter Mello
66390221f91SCody Peter Mello if (asprintf(&acqprog, "%s/acquire-lock%s", dirpath, suffix) < 0) {
66490221f91SCody Peter Mello errx(EXIT_FAILURE,
66590221f91SCody Peter Mello "Can't generate lock acquisition program name!");
66690221f91SCody Peter Mello }
66790221f91SCody Peter Mello
66890221f91SCody Peter Mello if (access(acqprog, X_OK) != 0) {
66990221f91SCody Peter Mello err(EXIT_FAILURE,
67090221f91SCody Peter Mello "Can't run lock acquisition program %s", acqprog);
67190221f91SCody Peter Mello }
67290221f91SCody Peter Mello
67390221f91SCody Peter Mello /* Create several lockfiles for testing */
67490221f91SCody Peter Mello if (flock_mkfil(&flock_fileA) != 0 ||
67590221f91SCody Peter Mello flock_mkfil(&flock_fileB) != 0 ||
67690221f91SCody Peter Mello flock_mkdir(&flock_dirA) != 0 ||
67790221f91SCody Peter Mello flock_mkdir(&flock_dirB) != 0) {
67890221f91SCody Peter Mello exval = 1;
67990221f91SCody Peter Mello goto cleanup;
68090221f91SCody Peter Mello }
68190221f91SCody Peter Mello
68290221f91SCody Peter Mello /*
68390221f91SCody Peter Mello * We run the tests in a child process so that when tests fail
68490221f91SCody Peter Mello * we can still clean up our temporary files.
68590221f91SCody Peter Mello */
68690221f91SCody Peter Mello testrunner = fork();
68790221f91SCody Peter Mello if (testrunner == (pid_t)-1) {
68890221f91SCody Peter Mello err(EXIT_FAILURE, "Unable to fork to run tests");
68990221f91SCody Peter Mello } else if (testrunner == (pid_t)0) {
69090221f91SCody Peter Mello flock_runtests();
69190221f91SCody Peter Mello return (0);
69290221f91SCody Peter Mello }
69390221f91SCody Peter Mello
69490221f91SCody Peter Mello exval = flock_wait(testrunner);
69590221f91SCody Peter Mello
69690221f91SCody Peter Mello cleanup:
69790221f91SCody Peter Mello free(basestr);
69890221f91SCody Peter Mello free(dirstr);
69990221f91SCody Peter Mello flock_rminfo(&flock_fileA);
70090221f91SCody Peter Mello flock_rminfo(&flock_fileB);
70190221f91SCody Peter Mello flock_rminfo(&flock_dirA);
70290221f91SCody Peter Mello flock_rminfo(&flock_dirB);
70390221f91SCody Peter Mello return (exval);
70490221f91SCody Peter Mello }
705