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