1171707Sdes/*-
2199134Sdes * Copyright (c) 2007-2009 Dag-Erling Co��dan Sm��rgrav
3171707Sdes * All rights reserved.
4171707Sdes *
5171707Sdes * Redistribution and use in source and binary forms, with or without
6171707Sdes * modification, are permitted provided that the following conditions
7171707Sdes * are met:
8171707Sdes * 1. Redistributions of source code must retain the above copyright
9171707Sdes *    notice, this list of conditions and the following disclaimer
10171707Sdes *    in this position and unchanged.
11171707Sdes * 2. Redistributions in binary form must reproduce the above copyright
12171707Sdes *    notice, this list of conditions and the following disclaimer in the
13171707Sdes *    documentation and/or other materials provided with the distribution.
14171707Sdes *
15171707Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16171707Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17171707Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18171707Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19171707Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20171707Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21171707Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22171707Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23171707Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24171707Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25171707Sdes * SUCH DAMAGE.
26171707Sdes */
27171707Sdes
28171707Sdes#include <sys/cdefs.h>
29171707Sdes__FBSDID("$FreeBSD$");
30171707Sdes
31171707Sdes#include <sys/types.h>
32171707Sdes#include <sys/fcntl.h>
33171707Sdes
34171707Sdes#include <errno.h>
35199212Sdes#include <signal.h>
36171707Sdes#include <stdint.h>
37171707Sdes#include <stdio.h>
38171707Sdes#include <stdlib.h>
39171707Sdes#include <string.h>
40171707Sdes#include <unistd.h>
41171707Sdes
42171707Sdes#include <libutil.h>
43171707Sdes
44171707Sdes/*
45171707Sdes * Test that flopen() can create a file.
46171707Sdes */
47171707Sdesconst char *
48171707Sdestest_flopen_create(void)
49171707Sdes{
50171707Sdes	const char *fn = "test_flopen_create";
51171707Sdes	const char *result = NULL;
52171707Sdes	int fd;
53171707Sdes
54171707Sdes	unlink(fn);
55171707Sdes	fd = flopen(fn, O_RDWR|O_CREAT, 0640);
56171707Sdes	if (fd < 0) {
57171707Sdes		result = strerror(errno);
58171707Sdes	} else {
59171707Sdes		close(fd);
60171707Sdes	}
61171707Sdes	unlink(fn);
62171707Sdes	return (result);
63171707Sdes}
64171707Sdes
65171707Sdes/*
66171707Sdes * Test that flopen() can open an existing file.
67171707Sdes */
68171707Sdesconst char *
69171707Sdestest_flopen_open(void)
70171707Sdes{
71171707Sdes	const char *fn = "test_flopen_open";
72171707Sdes	const char *result = NULL;
73171707Sdes	int fd;
74171707Sdes
75171707Sdes	fd = open(fn, O_RDWR|O_CREAT, 0640);
76171707Sdes	if (fd < 0) {
77171707Sdes		result = strerror(errno);
78171707Sdes	} else {
79171707Sdes		close(fd);
80171707Sdes		fd = flopen(fn, O_RDWR);
81171707Sdes		if (fd < 0) {
82171707Sdes			result = strerror(errno);
83171707Sdes		} else {
84171707Sdes			close(fd);
85171707Sdes		}
86171707Sdes	}
87171707Sdes	unlink(fn);
88171707Sdes	return (result);
89171707Sdes}
90171707Sdes
91171707Sdes/*
92171707Sdes * Test that flopen() can lock against itself
93171707Sdes */
94171707Sdesconst char *
95171707Sdestest_flopen_lock_self(void)
96171707Sdes{
97193592Sdes	const char *fn = "test_flopen_lock_self";
98171707Sdes	const char *result = NULL;
99171707Sdes	int fd1, fd2;
100171707Sdes
101171707Sdes	unlink(fn);
102171707Sdes	fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
103171707Sdes	if (fd1 < 0) {
104171707Sdes		result = strerror(errno);
105171707Sdes	} else {
106171707Sdes		fd2 = flopen(fn, O_RDWR|O_NONBLOCK);
107171707Sdes		if (fd2 >= 0) {
108171707Sdes			result = "second open succeeded";
109171707Sdes			close(fd2);
110171707Sdes		}
111171707Sdes		close(fd1);
112171707Sdes	}
113171707Sdes	unlink(fn);
114171707Sdes	return (result);
115171707Sdes}
116171707Sdes
117171707Sdes/*
118171707Sdes * Test that flopen() can lock against other processes
119171707Sdes */
120171707Sdesconst char *
121171707Sdestest_flopen_lock_other(void)
122171707Sdes{
123193592Sdes	const char *fn = "test_flopen_lock_other";
124171707Sdes	const char *result = NULL;
125171707Sdes	volatile int fd1, fd2;
126171707Sdes
127171707Sdes	unlink(fn);
128171707Sdes	fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
129171707Sdes	if (fd1 < 0) {
130171707Sdes		result = strerror(errno);
131171707Sdes	} else {
132171707Sdes		fd2 = -42;
133171707Sdes		if (vfork() == 0) {
134171707Sdes			fd2 = flopen(fn, O_RDWR|O_NONBLOCK);
135171707Sdes			close(fd2);
136171707Sdes			_exit(0);
137171707Sdes		}
138171707Sdes		if (fd2 == -42)
139171707Sdes			result = "vfork() doesn't work as expected";
140171707Sdes		if (fd2 >= 0)
141171707Sdes			result = "second open succeeded";
142171707Sdes		close(fd1);
143171707Sdes	}
144171707Sdes	unlink(fn);
145171707Sdes	return (result);
146171707Sdes}
147171707Sdes
148193592Sdes/*
149193592Sdes * Test that child processes inherit the lock
150193592Sdes */
151193592Sdesconst char *
152193592Sdestest_flopen_lock_child(void)
153193592Sdes{
154193592Sdes	const char *fn = "test_flopen_lock_child";
155193592Sdes	const char *result = NULL;
156193592Sdes	pid_t pid;
157193592Sdes	volatile int fd1, fd2;
158193592Sdes
159193592Sdes	unlink(fn);
160193592Sdes	fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
161193592Sdes	if (fd1 < 0) {
162193592Sdes		result = strerror(errno);
163193592Sdes	} else {
164199134Sdes		pid = fork();
165199134Sdes		if (pid == -1) {
166199134Sdes			result = strerror(errno);
167199134Sdes		} else if (pid == 0) {
168193592Sdes			select(0, 0, 0, 0, 0);
169193592Sdes			_exit(0);
170193592Sdes		}
171193592Sdes		close(fd1);
172199212Sdes		if ((fd2 = flopen(fn, O_RDWR|O_NONBLOCK)) != -1) {
173199212Sdes			result = "second open succeeded";
174193592Sdes			close(fd2);
175193592Sdes		}
176193592Sdes		kill(pid, SIGINT);
177193592Sdes	}
178193592Sdes	unlink(fn);
179193592Sdes	return (result);
180193592Sdes}
181193592Sdes
182171707Sdesstatic struct test {
183171707Sdes	const char *name;
184171707Sdes	const char *(*func)(void);
185171707Sdes} t[] = {
186171707Sdes	{ "flopen_create", test_flopen_create },
187171707Sdes	{ "flopen_open", test_flopen_open },
188171707Sdes	{ "flopen_lock_self", test_flopen_lock_self },
189171707Sdes	{ "flopen_lock_other", test_flopen_lock_other },
190193592Sdes	{ "flopen_lock_child", test_flopen_lock_child },
191171707Sdes};
192171707Sdes
193171707Sdesint
194171707Sdesmain(void)
195171707Sdes{
196171707Sdes	const char *result;
197171707Sdes	int i, nt;
198171707Sdes
199171707Sdes	nt = sizeof(t) / sizeof(*t);
200171707Sdes	printf("1..%d\n", nt);
201171707Sdes	for (i = 0; i < nt; ++i) {
202171707Sdes		if ((result = t[i].func()) != NULL)
203171707Sdes			printf("not ok %d - %s # %s\n", i + 1,
204171707Sdes			    t[i].name, result);
205171707Sdes		else
206171707Sdes			printf("ok %d - %s\n", i + 1,
207171707Sdes			    t[i].name);
208171707Sdes	}
209171707Sdes	exit(0);
210171707Sdes}
211