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