xref: /f-stack/tools/libutil/tests/flopen_test.c (revision 1eaf0ac3)
1*1eaf0ac3Slogwang /*-
2*1eaf0ac3Slogwang  * Copyright (c) 2007-2009 Dag-Erling Coïdan Smørgrav
3*1eaf0ac3Slogwang  * All rights reserved.
4*1eaf0ac3Slogwang  *
5*1eaf0ac3Slogwang  * Redistribution and use in source and binary forms, with or without
6*1eaf0ac3Slogwang  * modification, are permitted provided that the following conditions
7*1eaf0ac3Slogwang  * are met:
8*1eaf0ac3Slogwang  * 1. Redistributions of source code must retain the above copyright
9*1eaf0ac3Slogwang  *    notice, this list of conditions and the following disclaimer
10*1eaf0ac3Slogwang  *    in this position and unchanged.
11*1eaf0ac3Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
12*1eaf0ac3Slogwang  *    notice, this list of conditions and the following disclaimer in the
13*1eaf0ac3Slogwang  *    documentation and/or other materials provided with the distribution.
14*1eaf0ac3Slogwang  *
15*1eaf0ac3Slogwang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*1eaf0ac3Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*1eaf0ac3Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*1eaf0ac3Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*1eaf0ac3Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*1eaf0ac3Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*1eaf0ac3Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*1eaf0ac3Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*1eaf0ac3Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*1eaf0ac3Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*1eaf0ac3Slogwang  * SUCH DAMAGE.
26*1eaf0ac3Slogwang  */
27*1eaf0ac3Slogwang 
28*1eaf0ac3Slogwang #include <sys/cdefs.h>
29*1eaf0ac3Slogwang __FBSDID("$FreeBSD$");
30*1eaf0ac3Slogwang 
31*1eaf0ac3Slogwang #include <sys/types.h>
32*1eaf0ac3Slogwang #include <sys/fcntl.h>
33*1eaf0ac3Slogwang 
34*1eaf0ac3Slogwang #include <errno.h>
35*1eaf0ac3Slogwang #include <signal.h>
36*1eaf0ac3Slogwang #include <stdint.h>
37*1eaf0ac3Slogwang #include <stdio.h>
38*1eaf0ac3Slogwang #include <stdlib.h>
39*1eaf0ac3Slogwang #include <string.h>
40*1eaf0ac3Slogwang #include <unistd.h>
41*1eaf0ac3Slogwang 
42*1eaf0ac3Slogwang #include <libutil.h>
43*1eaf0ac3Slogwang 
44*1eaf0ac3Slogwang /*
45*1eaf0ac3Slogwang  * Test that flopen() can create a file.
46*1eaf0ac3Slogwang  */
47*1eaf0ac3Slogwang const char *
test_flopen_create(void)48*1eaf0ac3Slogwang test_flopen_create(void)
49*1eaf0ac3Slogwang {
50*1eaf0ac3Slogwang 	const char *fn = "test_flopen_create";
51*1eaf0ac3Slogwang 	const char *result = NULL;
52*1eaf0ac3Slogwang 	int fd;
53*1eaf0ac3Slogwang 
54*1eaf0ac3Slogwang 	unlink(fn);
55*1eaf0ac3Slogwang 	fd = flopen(fn, O_RDWR|O_CREAT, 0640);
56*1eaf0ac3Slogwang 	if (fd < 0) {
57*1eaf0ac3Slogwang 		result = strerror(errno);
58*1eaf0ac3Slogwang 	} else {
59*1eaf0ac3Slogwang 		close(fd);
60*1eaf0ac3Slogwang 	}
61*1eaf0ac3Slogwang 	unlink(fn);
62*1eaf0ac3Slogwang 	return (result);
63*1eaf0ac3Slogwang }
64*1eaf0ac3Slogwang 
65*1eaf0ac3Slogwang /*
66*1eaf0ac3Slogwang  * Test that flopen() can open an existing file.
67*1eaf0ac3Slogwang  */
68*1eaf0ac3Slogwang const char *
test_flopen_open(void)69*1eaf0ac3Slogwang test_flopen_open(void)
70*1eaf0ac3Slogwang {
71*1eaf0ac3Slogwang 	const char *fn = "test_flopen_open";
72*1eaf0ac3Slogwang 	const char *result = NULL;
73*1eaf0ac3Slogwang 	int fd;
74*1eaf0ac3Slogwang 
75*1eaf0ac3Slogwang 	fd = open(fn, O_RDWR|O_CREAT, 0640);
76*1eaf0ac3Slogwang 	if (fd < 0) {
77*1eaf0ac3Slogwang 		result = strerror(errno);
78*1eaf0ac3Slogwang 	} else {
79*1eaf0ac3Slogwang 		close(fd);
80*1eaf0ac3Slogwang 		fd = flopen(fn, O_RDWR);
81*1eaf0ac3Slogwang 		if (fd < 0) {
82*1eaf0ac3Slogwang 			result = strerror(errno);
83*1eaf0ac3Slogwang 		} else {
84*1eaf0ac3Slogwang 			close(fd);
85*1eaf0ac3Slogwang 		}
86*1eaf0ac3Slogwang 	}
87*1eaf0ac3Slogwang 	unlink(fn);
88*1eaf0ac3Slogwang 	return (result);
89*1eaf0ac3Slogwang }
90*1eaf0ac3Slogwang 
91*1eaf0ac3Slogwang /*
92*1eaf0ac3Slogwang  * Test that flopen() can lock against itself
93*1eaf0ac3Slogwang  */
94*1eaf0ac3Slogwang const char *
test_flopen_lock_self(void)95*1eaf0ac3Slogwang test_flopen_lock_self(void)
96*1eaf0ac3Slogwang {
97*1eaf0ac3Slogwang 	const char *fn = "test_flopen_lock_self";
98*1eaf0ac3Slogwang 	const char *result = NULL;
99*1eaf0ac3Slogwang 	int fd1, fd2;
100*1eaf0ac3Slogwang 
101*1eaf0ac3Slogwang 	unlink(fn);
102*1eaf0ac3Slogwang 	fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
103*1eaf0ac3Slogwang 	if (fd1 < 0) {
104*1eaf0ac3Slogwang 		result = strerror(errno);
105*1eaf0ac3Slogwang 	} else {
106*1eaf0ac3Slogwang 		fd2 = flopen(fn, O_RDWR|O_NONBLOCK);
107*1eaf0ac3Slogwang 		if (fd2 >= 0) {
108*1eaf0ac3Slogwang 			result = "second open succeeded";
109*1eaf0ac3Slogwang 			close(fd2);
110*1eaf0ac3Slogwang 		}
111*1eaf0ac3Slogwang 		close(fd1);
112*1eaf0ac3Slogwang 	}
113*1eaf0ac3Slogwang 	unlink(fn);
114*1eaf0ac3Slogwang 	return (result);
115*1eaf0ac3Slogwang }
116*1eaf0ac3Slogwang 
117*1eaf0ac3Slogwang /*
118*1eaf0ac3Slogwang  * Test that flopen() can lock against other processes
119*1eaf0ac3Slogwang  */
120*1eaf0ac3Slogwang const char *
test_flopen_lock_other(void)121*1eaf0ac3Slogwang test_flopen_lock_other(void)
122*1eaf0ac3Slogwang {
123*1eaf0ac3Slogwang 	const char *fn = "test_flopen_lock_other";
124*1eaf0ac3Slogwang 	const char *result = NULL;
125*1eaf0ac3Slogwang 	volatile int fd1, fd2;
126*1eaf0ac3Slogwang 
127*1eaf0ac3Slogwang 	unlink(fn);
128*1eaf0ac3Slogwang 	fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
129*1eaf0ac3Slogwang 	if (fd1 < 0) {
130*1eaf0ac3Slogwang 		result = strerror(errno);
131*1eaf0ac3Slogwang 	} else {
132*1eaf0ac3Slogwang 		fd2 = -42;
133*1eaf0ac3Slogwang 		if (vfork() == 0) {
134*1eaf0ac3Slogwang 			fd2 = flopen(fn, O_RDWR|O_NONBLOCK);
135*1eaf0ac3Slogwang 			close(fd2);
136*1eaf0ac3Slogwang 			_exit(0);
137*1eaf0ac3Slogwang 		}
138*1eaf0ac3Slogwang 		if (fd2 == -42)
139*1eaf0ac3Slogwang 			result = "vfork() doesn't work as expected";
140*1eaf0ac3Slogwang 		if (fd2 >= 0)
141*1eaf0ac3Slogwang 			result = "second open succeeded";
142*1eaf0ac3Slogwang 		close(fd1);
143*1eaf0ac3Slogwang 	}
144*1eaf0ac3Slogwang 	unlink(fn);
145*1eaf0ac3Slogwang 	return (result);
146*1eaf0ac3Slogwang }
147*1eaf0ac3Slogwang 
148*1eaf0ac3Slogwang /*
149*1eaf0ac3Slogwang  * Test that child processes inherit the lock
150*1eaf0ac3Slogwang  */
151*1eaf0ac3Slogwang const char *
test_flopen_lock_child(void)152*1eaf0ac3Slogwang test_flopen_lock_child(void)
153*1eaf0ac3Slogwang {
154*1eaf0ac3Slogwang 	const char *fn = "test_flopen_lock_child";
155*1eaf0ac3Slogwang 	const char *result = NULL;
156*1eaf0ac3Slogwang 	pid_t pid;
157*1eaf0ac3Slogwang 	volatile int fd1, fd2;
158*1eaf0ac3Slogwang 
159*1eaf0ac3Slogwang 	unlink(fn);
160*1eaf0ac3Slogwang 	fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
161*1eaf0ac3Slogwang 	if (fd1 < 0) {
162*1eaf0ac3Slogwang 		result = strerror(errno);
163*1eaf0ac3Slogwang 	} else {
164*1eaf0ac3Slogwang 		pid = fork();
165*1eaf0ac3Slogwang 		if (pid == -1) {
166*1eaf0ac3Slogwang 			result = strerror(errno);
167*1eaf0ac3Slogwang 		} else if (pid == 0) {
168*1eaf0ac3Slogwang 			select(0, 0, 0, 0, 0);
169*1eaf0ac3Slogwang 			_exit(0);
170*1eaf0ac3Slogwang 		}
171*1eaf0ac3Slogwang 		close(fd1);
172*1eaf0ac3Slogwang 		if ((fd2 = flopen(fn, O_RDWR|O_NONBLOCK)) != -1) {
173*1eaf0ac3Slogwang 			result = "second open succeeded";
174*1eaf0ac3Slogwang 			close(fd2);
175*1eaf0ac3Slogwang 		}
176*1eaf0ac3Slogwang 		kill(pid, SIGINT);
177*1eaf0ac3Slogwang 	}
178*1eaf0ac3Slogwang 	unlink(fn);
179*1eaf0ac3Slogwang 	return (result);
180*1eaf0ac3Slogwang }
181*1eaf0ac3Slogwang 
182*1eaf0ac3Slogwang static struct test {
183*1eaf0ac3Slogwang 	const char *name;
184*1eaf0ac3Slogwang 	const char *(*func)(void);
185*1eaf0ac3Slogwang } t[] = {
186*1eaf0ac3Slogwang 	{ "flopen_create", test_flopen_create },
187*1eaf0ac3Slogwang 	{ "flopen_open", test_flopen_open },
188*1eaf0ac3Slogwang 	{ "flopen_lock_self", test_flopen_lock_self },
189*1eaf0ac3Slogwang 	{ "flopen_lock_other", test_flopen_lock_other },
190*1eaf0ac3Slogwang 	{ "flopen_lock_child", test_flopen_lock_child },
191*1eaf0ac3Slogwang };
192*1eaf0ac3Slogwang 
193*1eaf0ac3Slogwang int
main(void)194*1eaf0ac3Slogwang main(void)
195*1eaf0ac3Slogwang {
196*1eaf0ac3Slogwang 	const char *result;
197*1eaf0ac3Slogwang 	int i, nt;
198*1eaf0ac3Slogwang 
199*1eaf0ac3Slogwang 	nt = sizeof(t) / sizeof(*t);
200*1eaf0ac3Slogwang 	printf("1..%d\n", nt);
201*1eaf0ac3Slogwang 	for (i = 0; i < nt; ++i) {
202*1eaf0ac3Slogwang 		if ((result = t[i].func()) != NULL)
203*1eaf0ac3Slogwang 			printf("not ok %d - %s # %s\n", i + 1,
204*1eaf0ac3Slogwang 			    t[i].name, result);
205*1eaf0ac3Slogwang 		else
206*1eaf0ac3Slogwang 			printf("ok %d - %s\n", i + 1,
207*1eaf0ac3Slogwang 			    t[i].name);
208*1eaf0ac3Slogwang 	}
209*1eaf0ac3Slogwang 	exit(0);
210*1eaf0ac3Slogwang }
211