Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/fifo/fifo_create.c
39534 views
1
/*-
2
* Copyright (c) 2005-2008 Robert N. M. Watson
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
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <sys/stat.h>
28
29
#include <err.h>
30
#include <errno.h>
31
#include <limits.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <unistd.h>
36
37
/*
38
* Simple regression test for the creation and destruction of POSIX fifos in
39
* the file system name space. Using a specially created directory, create
40
* a fifo in it and check that the following properties are present, as
41
* specified in IEEE Std 1003.1, 2004 Edition:
42
*
43
* - When mkfifo() or mknod(S_IFIFO) is called, on success, a fifo is
44
* created.
45
*
46
* - On an error, no fifo is created. (XXX: Not tested)
47
*
48
* - The mode bits on the fifo are a product of combining the umask and
49
* requested mode.
50
*
51
* - The fifo's owner will be the processes effective user ID. (XXX: Not
52
* tested)
53
*
54
* - The fifo's group will be the parent directory's group or the effective
55
* group ID of the process. For historical reasons, BSD prefers the group
56
* ID of the process, so we will generate an error if it's not that. (XXX:
57
* Not tested)
58
*
59
* - The st_atime, st_ctime, st_mtime of the fifo will be set appropriately,
60
* and st_ctime and st_mtime on the directory will be updated. (XXX: We
61
* test they are updated, not correct)
62
*
63
* - EEXIST is returned if the named file already exists.
64
*
65
* In addition, we check that we can unlink the fifo, and that if we do, it
66
* disappears.
67
*
68
* This test must run as root in order to usefully frob the process
69
* credential to test permission parts.
70
*/
71
72
/*
73
* All activity occurs within a temporary directory created early in the
74
* test.
75
*/
76
static char temp_dir[PATH_MAX];
77
78
static void __unused
79
atexit_temp_dir(void)
80
{
81
82
rmdir(temp_dir);
83
}
84
85
/*
86
* Basic creation tests: verify that mkfifo(2) (or mknod(2)) creates a fifo,
87
* that the time stamps on the directory are updated, that if we try twice we
88
* get EEXIST, and that we can unlink it.
89
*/
90
static void
91
fifo_create_test(int use_mkfifo)
92
{
93
struct stat old_dirsb, dirsb, fifosb;
94
const char *testname;
95
char path[] = "testfifo";
96
int error;
97
98
if (use_mkfifo)
99
testname = "mkfifo";
100
else
101
testname = "mknod";
102
103
/*
104
* Sleep to make sure that the time stamp on the directory will be
105
* updated.
106
*/
107
if (stat(".", &old_dirsb) < 0)
108
err(-1, "basic_create_test: %s: stat: %s", testname,
109
temp_dir);
110
111
sleep(2);
112
113
if (use_mkfifo) {
114
if (mkfifo(path, 0600) < 0)
115
err(-1, "basic_create_test: %s: %s", testname, path);
116
} else {
117
if (mknod(path, S_IFIFO | 0600, 0) < 0)
118
err(-1, "basic_create_test: %s: %s", testname, path);
119
}
120
121
if (stat(path, &fifosb) < 0) {
122
error = errno;
123
(void)unlink(path);
124
errno = error;
125
err(-1, "basic_create_test: %s: stat: %s", testname, path);
126
}
127
128
if (!(S_ISFIFO(fifosb.st_mode))) {
129
(void)unlink(path);
130
errx(-1, "basic_create_test: %s produced non-fifo",
131
testname);
132
}
133
134
if (use_mkfifo) {
135
if (mkfifo(path, 0600) == 0)
136
errx(-1, "basic_create_test: dup %s succeeded",
137
testname);
138
} else {
139
if (mknod(path, S_IFIFO | 0600, 0) == 0)
140
errx(-1, "basic_create_test: dup %s succeeded",
141
testname);
142
}
143
144
if (errno != EEXIST)
145
err(-1, "basic_create_test: dup %s unexpected error",
146
testname);
147
148
if (stat(".", &dirsb) < 0) {
149
error = errno;
150
(void)unlink(path);
151
errno = error;
152
err(-1, "basic_create_test: %s: stat: %s", testname,
153
temp_dir);
154
}
155
156
if (old_dirsb.st_ctime == dirsb.st_ctime) {
157
(void)unlink(path);
158
errx(-1, "basic_create_test: %s: old_dirsb.st_ctime == "
159
"dirsb.st_ctime", testname);
160
}
161
162
if (old_dirsb.st_mtime == dirsb.st_mtime) {
163
(void)unlink(path);
164
errx(-1, "basic_create_test: %s: old_dirsb.st_mtime == "
165
"dirsb.st_mtime", testname);
166
}
167
168
if (unlink(path) < 0)
169
err(-1, "basic_create_test: %s: unlink: %s", testname, path);
170
171
if (stat(path, &fifosb) == 0)
172
errx(-1, "basic_create_test: %s: unlink failed to unlink",
173
testname);
174
if (errno != ENOENT)
175
err(-1, "basic_create_test: %s: unlink unexpected error",
176
testname);
177
}
178
179
/*
180
* Having determined that basic create/remove/etc functionality is present
181
* for fifos, now make sure that the umask, requested permissions, and
182
* resulting mode are handled properly.
183
*/
184
static const struct permission_test {
185
mode_t pt_umask;
186
mode_t pt_reqmode;
187
mode_t pt_mode;
188
} permission_test[] = {
189
{0000, 0, S_IFIFO},
190
{0000, S_IRWXU, S_IFIFO | S_IRWXU},
191
{0000, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU | S_IRWXG |
192
S_IRWXO },
193
{0077, S_IRWXU, S_IFIFO | S_IRWXU},
194
{0077, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU},
195
};
196
static const int permission_test_count = sizeof(permission_test) /
197
sizeof(struct permission_test);
198
199
static void
200
fifo_permission_test(int use_mkfifo)
201
{
202
const struct permission_test *ptp;
203
mode_t __unused old_umask;
204
char path[] = "testfifo";
205
const char *testname;
206
struct stat sb;
207
int error, i;
208
209
if (use_mkfifo)
210
testname = "mkfifo";
211
else
212
testname = "mknod";
213
214
old_umask = umask(0022);
215
for (i = 0; i < permission_test_count; i++) {
216
ptp = &permission_test[i];
217
218
umask(ptp->pt_umask);
219
if (use_mkfifo) {
220
if (mkfifo(path, ptp->pt_reqmode) < 0)
221
err(-1, "fifo_permission_test: %s: %08o "
222
"%08o %08o\n", testname, ptp->pt_umask,
223
ptp->pt_reqmode, ptp->pt_mode);
224
} else {
225
if (mknod(path, S_IFIFO | ptp->pt_reqmode, 0) < 0)
226
err(-1, "fifo_permission_test: %s: %08o "
227
"%08o %08o\n", testname, ptp->pt_umask,
228
ptp->pt_reqmode, ptp->pt_mode);
229
}
230
231
if (stat(path, &sb) < 0) {
232
error = errno;
233
(void)unlink(path);
234
errno = error;
235
err(-1, "fifo_permission_test: %s: %s", testname,
236
path);
237
}
238
239
if (sb.st_mode != ptp->pt_mode) {
240
(void)unlink(path);
241
errx(-1, "fifo_permission_test: %s: %08o %08o %08o "
242
"got %08o", testname, ptp->pt_umask,
243
ptp->pt_reqmode, ptp->pt_mode, sb.st_mode);
244
}
245
246
if (unlink(path) < 0)
247
err(-1, "fifo_permission_test: %s: unlink: %s",
248
testname, path);
249
}
250
umask(old_umask);
251
}
252
253
int
254
main(void)
255
{
256
int i;
257
258
if (geteuid() != 0)
259
errx(-1, "must be run as root");
260
261
strcpy(temp_dir, "fifo_create.XXXXXXXXXXX");
262
if (mkdtemp(temp_dir) == NULL)
263
err(-1, "mkdtemp");
264
atexit(atexit_temp_dir);
265
266
if (chdir(temp_dir) < 0)
267
err(-1, "chdir");
268
269
/*
270
* Run each test twice, once with mknod(2) and a second time with
271
* mkfifo(2). Historically, BSD has not allowed mknod(2) to be used
272
* to create fifos, but the Single UNIX Specification requires it.
273
*/
274
for (i = 0; i < 2; i++) {
275
fifo_create_test(i);
276
fifo_permission_test(i);
277
}
278
279
return (0);
280
}
281
282