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