]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - tools/regression/fifo/fifo_create/fifo_create.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / tools / regression / fifo / fifo_create / fifo_create.c
1 /*-
2  * Copyright (c) 2005 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  * $FreeBSD$
27  */
28
29 #include <sys/stat.h>
30
31 #include <err.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 /*
40  * Simple regression test for the creation and destruction of POSIX fifos in
41  * the file system name space.  Using a specially created directory, create
42  * a fifo in it and check that the following properties are present, as
43  * specified in IEEE Std 1003.1, 2004 Edition:
44  *
45  * - When mkfifo() is called, on success, a fifo is created.
46  *
47  * - On an error, no fifo is created. (XXX: Not tested)
48  *
49  * - The mode bits on the fifo are a product of combining the umask and
50  *   requested mode.
51  *
52  * - The fifo's owner will be the processes effective user ID. (XXX: Not
53  *   tested)
54  *
55  * - The fifo's group will be the parent directory's group or the effective
56  *   group ID of the process.  For historical reasons, BSD prefers the group
57  *   ID of the process, so we will generate an error if it's not that. (XXX:
58  *   Not tested)
59  *
60  * - The st_atime, st_ctime, st_mtime of the fifo will be set appropriately,
61  *   and st_ctime and st_mtime on the directory will be updated. (XXX: We
62  *   test they are updated, not correct)
63  *
64  * - EEXIST is returned if the named file already exists.
65  *
66  * In addition, we check that we can unlink the fifo, and that if we do, it
67  * disappears.
68  *
69  * This test must run as root in order to usefully frob the process
70  * credential to test permission parts.
71  */
72
73 /*
74  * All activity occurs within a temporary directory created early in the
75  * test.
76  */
77 char    temp_dir[PATH_MAX];
78
79 static void __unused
80 atexit_temp_dir(void)
81 {
82
83         rmdir(temp_dir);
84 }
85
86 /*
87  * Basic creation tests: verify that mkfifo() creates a fifo, that the time
88  * stamps on the directory are updated, that if we try twice we get EEXIST,
89  * and that we can unlink it.
90  */
91 static void
92 fifo_create_test(void)
93 {
94         struct stat old_dirsb, dirsb, fifosb;
95         char path[PATH_MAX];
96         int error;
97
98         /*
99          * Sleep to make sure that the time stamp on the directory will be
100          * updated.
101          */
102         sleep(2);
103
104         if (stat(temp_dir, &old_dirsb) < 0)
105                 err(-1, "basic_create_test: stat: %s", temp_dir);
106
107         snprintf(path, PATH_MAX, "%s/testfifo", temp_dir);
108
109         if (mkfifo(path, 0600) < 0)
110                 err(-1, "basic_create_test: mkfifo: %s", path);
111
112         if (stat(path, &fifosb) < 0) {
113                 error = errno;
114                 (void)unlink(path);
115                 errno = error;
116                 err(-1, "basic_create_test: stat: %s", path);
117         }
118
119         if (!(S_ISFIFO(fifosb.st_mode))) {
120                 (void)unlink(path);
121                 errx(-1, "basic_create_test: mkfifo produced non-fifo");
122         }
123
124         if (mkfifo(path, 0600) == 0)
125                 errx(-1, "basic_create_test: dup mkfifo succeeded");
126
127         if (errno != EEXIST)
128                 err(-1, "basic_create_test: dup mkfifo unexpected error");
129
130         if (stat(temp_dir, &dirsb) < 0) {
131                 error = errno;
132                 (void)unlink(path);
133                 errno = error;
134                 err(-1, "basic_create_test: stat: %s", temp_dir);
135         }
136
137         if (old_dirsb.st_ctime == dirsb.st_ctime) {
138                 (void)unlink(path);
139                 errx(-1, "basic_create_test: old_dirsb.st_ctime == "
140                     "dirsb.st_ctime");
141         }
142
143         if (old_dirsb.st_mtime == dirsb.st_mtime) {
144                 (void)unlink(path);
145                 errx(-1, "basic_create_test: old_dirsb.st_mtime == "
146                     "dirsb.st_mtime");
147         }
148
149         if (unlink(path) < 0)
150                 err(-1, "basic_create_test: unlink: %s", path);
151
152         if (stat(path, &fifosb) == 0)
153                 errx(-1, "basic_create_test: unlink failed to unlink");
154         if (errno != ENOENT)
155                 err(-1, "basic_create_test: unlink unexpected error");
156 }
157
158 /*
159  * Having determined that basic create/remove/etc functionality is present
160  * for fifos, now make sure that the umask, requested permissions, and
161  * resulting mode are handled properly.
162  */
163 static const struct permission_test {
164         mode_t  pt_umask;
165         mode_t  pt_reqmode;
166         mode_t  pt_mode;
167 } permission_test[] = {
168         {0000, 0, S_IFIFO},
169         {0000, S_IRWXU, S_IFIFO | S_IRWXU},
170         {0000, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU | S_IRWXG |
171             S_IRWXO },
172         {0077, S_IRWXU, S_IFIFO | S_IRWXU},
173         {0077, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU},
174 };
175 static const int permission_test_count = sizeof(permission_test) /
176     sizeof(struct permission_test);
177
178 static void
179 fifo_permission_test(void)
180 {
181         const struct permission_test *ptp;
182         mode_t __unused old_umask;
183         char path[PATH_MAX];
184         struct stat sb;
185         int error, i;
186
187         snprintf(path, PATH_MAX, "%s/testfifo", temp_dir);
188         old_umask = umask(0022);
189         for (i = 0; i < permission_test_count; i++) {
190                 ptp = &permission_test[i];
191
192                 umask(ptp->pt_umask);
193                 if (mkfifo(path, ptp->pt_reqmode) < 0)
194                         err(-1, "fifo_permission_test: %08o %08o %08o\n",
195                             ptp->pt_umask, ptp->pt_reqmode, ptp->pt_mode);
196
197                 if (stat(path, &sb) < 0) {
198                         error = errno;
199                         (void)unlink(path);
200                         errno = error;
201                         err(-1, "fifo_permission_test: %s", path);
202                 }
203
204                 if (sb.st_mode != ptp->pt_mode) {
205                         (void)unlink(path);
206                         errx(-1, "fifo_permission_test: %08o %08o %08o "
207                             "got %08o", ptp->pt_umask, ptp->pt_reqmode,
208                             ptp->pt_mode, sb.st_mode);
209                 }
210
211                 if (unlink(path) < 0)
212                         err(-1, "fifo_permission_test: unlink: %s", path);
213         }
214         umask(old_umask);
215 }
216
217 int
218 main(int argc, char *argv[])
219 {
220
221         if (geteuid() != 0)
222                 errx(-1, "must be run as root");
223
224         strcpy(temp_dir, "/tmp/fifo_create.XXXXXXXXXXX");
225         if (mkdtemp(temp_dir) == NULL)
226                 err(-1, "mkdtemp");
227         atexit(atexit_temp_dir);
228
229         if (chdir(temp_dir) < 0)
230                 err(-1, "chdir");
231
232         fifo_create_test();
233
234         fifo_permission_test();
235
236         return (0);
237 }