xref: /freebsd-src/tools/regression/security/open_to_operation/open_to_operation.c (revision 6bfca4dcab07dad45a805879d954876b353c0810)
1b0cfa3c4SRobert Watson /*-
2b0cfa3c4SRobert Watson  * Copyright (c) 2008 Robert N. M. Watson
3b0cfa3c4SRobert Watson  * All rights reserved.
4b0cfa3c4SRobert Watson  *
5b0cfa3c4SRobert Watson  * Redistribution and use in source and binary forms, with or without
6b0cfa3c4SRobert Watson  * modification, are permitted provided that the following conditions
7b0cfa3c4SRobert Watson  * are met:
8b0cfa3c4SRobert Watson  * 1. Redistributions of source code must retain the above copyright
9b0cfa3c4SRobert Watson  *    notice, this list of conditions and the following disclaimer.
10b0cfa3c4SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
11b0cfa3c4SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
12b0cfa3c4SRobert Watson  *    documentation and/or other materials provided with the distribution.
13b0cfa3c4SRobert Watson  *
14b0cfa3c4SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15b0cfa3c4SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16b0cfa3c4SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17b0cfa3c4SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18b0cfa3c4SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19b0cfa3c4SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20b0cfa3c4SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21b0cfa3c4SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22b0cfa3c4SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23b0cfa3c4SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24b0cfa3c4SRobert Watson  * SUCH DAMAGE.
25b0cfa3c4SRobert Watson  */
26b0cfa3c4SRobert Watson 
27b0cfa3c4SRobert Watson /*-
28b0cfa3c4SRobert Watson  * This regression test attempts to confirm that the flags used at open-time
29b0cfa3c4SRobert Watson  * for a file descriptor properly limit system calls that should be affected
30b0cfa3c4SRobert Watson  * by those flags.  Currently:
31b0cfa3c4SRobert Watson  *
32b0cfa3c4SRobert Watson  * System call                    Policy                      Tested
33b0cfa3c4SRobert Watson  * __acl_aclcheck_fd(2)           any                         no
34b0cfa3c4SRobert Watson  * __acl_delete_fd(2)             any                         no
35b0cfa3c4SRobert Watson  * __acl_get_fd(2)                any                         no
36b0cfa3c4SRobert Watson  * __acl_set_fd(2)                any                         no
37b0cfa3c4SRobert Watson  * aio_fsync(2)                   any                         no
38b0cfa3c4SRobert Watson  * aio_read(2)                    O_RDONLY or O_RDWR          yes
39b0cfa3c4SRobert Watson  * aio_write(2)                   O_WRONLY or O_RDWR          yes
40b0cfa3c4SRobert Watson  * dup(2)                         any                         yes
41b0cfa3c4SRobert Watson  * dup2(2)                        any                         yes
42b0cfa3c4SRobert Watson  * extattr_delete_fd(2)           O_WRONLY or O_RDWR          no
43b0cfa3c4SRobert Watson  * extattr_get_fd(2)              O_RDONLY or O_RDWR          no
44b0cfa3c4SRobert Watson  * extattr_list_fd(2)             O_RDONLY or O_RDWR          no
45b0cfa3c4SRobert Watson  * extattr_set_fd(2)              O_WRONLY or O_RDWR          no
46b0cfa3c4SRobert Watson  * fchdir(2)                      any directory               yes
47b0cfa3c4SRobert Watson  * fchflags(2)                    any                         yes
48b0cfa3c4SRobert Watson  * fchmod(2)                      any                         yes
49b0cfa3c4SRobert Watson  * fchown(2)                      any                         yes
50b0cfa3c4SRobert Watson  * flock(2)                       any                         yes
51b0cfa3c4SRobert Watson  * fpathconf(2)                   any                         yes
52b0cfa3c4SRobert Watson  * fstat(2)                       any                         yes
53b0cfa3c4SRobert Watson  * fstatfs(2)                     any                         yes
54b0cfa3c4SRobert Watson  * fsync(2)                       any                         yes
55b0cfa3c4SRobert Watson  * ftruncate(2)                   O_WRONLY or O_RDWR          yes
56b0cfa3c4SRobert Watson  * futimes(2)                     any                         yes
57b0cfa3c4SRobert Watson  * getdents(2)                    O_RDONLY directory          yes
58b0cfa3c4SRobert Watson  * lseek(2)                       any                         yes
59b0cfa3c4SRobert Watson  * mmap(2) PROT_READ              O_RDONLY or O_RDWR          yes
60b0cfa3c4SRobert Watson  * mmap(2) PROT_WRITE             O_WRONLY or O_RDWR          yes
61b0cfa3c4SRobert Watson  * mmap(2) PROT_WRITE + MAP_PRIV  O_RDONLY or O_RDWR          yes
62b0cfa3c4SRobert Watson  * mmap(2) PROT_EXEC              O_RDONLY or O_RDWR          yes
63b0cfa3c4SRobert Watson  * pread(2)                       O_RDONLY or O_RDWR          yes
64b0cfa3c4SRobert Watson  * preadv(2)                      O_RDONLY or O_RDWR          yes
65b0cfa3c4SRobert Watson  * pwrite(2)                      O_WRONLY or O_RDWR          yes
66b0cfa3c4SRobert Watson  * pwritev(2)                     O_WRONLY or O_RDWR          yes
67b0cfa3c4SRobert Watson  * read(2)                        O_RDONLY or O_RDWR          yes
68b0cfa3c4SRobert Watson  * readv(2)                       O_RDONLY or O_RDWR          yes
69b0cfa3c4SRobert Watson  * sendfile(2)                    O_RDONLY or O_RDWR on file  yes
70b0cfa3c4SRobert Watson  * write(2)                       O_WRONLY or O_RDWR          yes
71b0cfa3c4SRobert Watson  * writev(2)                      O_WRONLY or O_RDWR          yes
72b0cfa3c4SRobert Watson  *
73b0cfa3c4SRobert Watson  * These checks do not verify that original permissions would allow the
74b0cfa3c4SRobert Watson  * operation or that open is properly impacted by permissions, just that once
75b0cfa3c4SRobert Watson  * a file descriptor is held, open-time limitations are implemented.
76b0cfa3c4SRobert Watson  *
77b0cfa3c4SRobert Watson  * We do, however, test that directories cannot be opened as writable.
78b0cfa3c4SRobert Watson  *
79b0cfa3c4SRobert Watson  * XXXRW: Arguably we should also test combinations of bits to mmap(2).
80b0cfa3c4SRobert Watson  *
81b0cfa3c4SRobert Watson  * XXXRW: Should verify mprotect() remapping limits.
82b0cfa3c4SRobert Watson  *
83b0cfa3c4SRobert Watson  * XXXRW: kqueue(2)/kevent(2), poll(2), select(2)
84b0cfa3c4SRobert Watson  *
85b0cfa3c4SRobert Watson  * XXXRW: oaio_read(2), oaio_write(2), freebsd6_*(2).
86b0cfa3c4SRobert Watson  *
87b0cfa3c4SRobert Watson  * XXXRW: __mac*(2)
88b0cfa3c4SRobert Watson  *
89b0cfa3c4SRobert Watson  * XXXRW: message queue and shared memory fds?
90b0cfa3c4SRobert Watson  */
91b0cfa3c4SRobert Watson 
92b0cfa3c4SRobert Watson #include <sys/param.h>
93b0cfa3c4SRobert Watson #include <sys/mman.h>
94b0cfa3c4SRobert Watson #include <sys/mount.h>
95b0cfa3c4SRobert Watson #include <sys/socket.h>
96b0cfa3c4SRobert Watson #include <sys/stat.h>
97b0cfa3c4SRobert Watson #include <sys/sysctl.h>
98b0cfa3c4SRobert Watson #include <sys/uio.h>
99b0cfa3c4SRobert Watson 
100b0cfa3c4SRobert Watson #include <aio.h>
101b0cfa3c4SRobert Watson #include <dirent.h>
102b0cfa3c4SRobert Watson #include <err.h>
103b0cfa3c4SRobert Watson #include <errno.h>
104b0cfa3c4SRobert Watson #include <fcntl.h>
105b0cfa3c4SRobert Watson #include <limits.h>
106b0cfa3c4SRobert Watson #include <stdio.h>
107b0cfa3c4SRobert Watson #include <stdlib.h>
108b0cfa3c4SRobert Watson #include <string.h>
109b0cfa3c4SRobert Watson #include <unistd.h>
110b0cfa3c4SRobert Watson 
111b0cfa3c4SRobert Watson #define	PERM_FILE	0644		/* Allow read, write.  Someday exec? */
112b0cfa3c4SRobert Watson #define	PERM_DIR	0755		/* Allow read, write, exec. */
113b0cfa3c4SRobert Watson 
114b0cfa3c4SRobert Watson /*
115b0cfa3c4SRobert Watson  * Modes to try all tests with.
116b0cfa3c4SRobert Watson  */
117b0cfa3c4SRobert Watson static const int file_modes[] = { O_RDONLY, O_WRONLY, O_RDWR,
118b0cfa3c4SRobert Watson     O_RDONLY | O_TRUNC, O_WRONLY | O_TRUNC, O_RDWR | O_TRUNC };
119*0c646040SEnji Cooper static const int file_modes_count = nitems(file_modes);
120b0cfa3c4SRobert Watson 
121b0cfa3c4SRobert Watson static const int dir_modes[] = { O_RDONLY };
122*0c646040SEnji Cooper static const int dir_modes_count = nitems(dir_modes);
123b0cfa3c4SRobert Watson 
124b0cfa3c4SRobert Watson static int testnum;
125b0cfa3c4SRobert Watson static int aio_present;
126b0cfa3c4SRobert Watson 
127b0cfa3c4SRobert Watson static void
ok_mode(const char * testname,const char * comment,int mode)128b0cfa3c4SRobert Watson ok_mode(const char *testname, const char *comment, int mode)
129b0cfa3c4SRobert Watson {
130b0cfa3c4SRobert Watson 
131b0cfa3c4SRobert Watson 	testnum++;
132b0cfa3c4SRobert Watson 	if (comment == NULL)
133b0cfa3c4SRobert Watson 		printf("ok %d - %s # mode 0x%x\n", testnum, testname, mode);
134b0cfa3c4SRobert Watson 	else
135b0cfa3c4SRobert Watson 		printf("ok %d - %s # mode 0x%x - %s\n", testnum, testname,
136b0cfa3c4SRobert Watson 		    mode, comment);
137b0cfa3c4SRobert Watson }
138b0cfa3c4SRobert Watson 
139b0cfa3c4SRobert Watson static void
notok_mode(const char * testname,const char * comment,int mode)140b0cfa3c4SRobert Watson notok_mode(const char *testname, const char *comment, int mode)
141b0cfa3c4SRobert Watson {
142b0cfa3c4SRobert Watson 
143b0cfa3c4SRobert Watson 	testnum++;
144b0cfa3c4SRobert Watson 	if (comment == NULL)
145b0cfa3c4SRobert Watson 		printf("not ok %d - %s # mode 0x%x\n", testnum, testname,
146b0cfa3c4SRobert Watson 		    mode);
147b0cfa3c4SRobert Watson 	else
148b0cfa3c4SRobert Watson 		printf("not ok %d - %s # mode 0x%x - %s\n", testnum, testname,
149b0cfa3c4SRobert Watson 		    mode, comment);
150b0cfa3c4SRobert Watson }
151b0cfa3c4SRobert Watson 
152b0cfa3c4SRobert Watson /*
153b0cfa3c4SRobert Watson  * Before we get started, confirm that we can't open directories writable.
154b0cfa3c4SRobert Watson  */
155b0cfa3c4SRobert Watson static void
try_directory_open(const char * testname,const char * directory,int mode,int expected_errno)156b0cfa3c4SRobert Watson try_directory_open(const char *testname, const char *directory,
157b0cfa3c4SRobert Watson     int mode, int expected_errno)
158b0cfa3c4SRobert Watson {
159b0cfa3c4SRobert Watson 	int dfd;
160b0cfa3c4SRobert Watson 
161b0cfa3c4SRobert Watson 	dfd = open(directory, mode);
162b0cfa3c4SRobert Watson 	if (dfd >= 0) {
163b0cfa3c4SRobert Watson 		if (expected_errno)
164b0cfa3c4SRobert Watson 			notok_mode(testname, "opened", mode);
165b0cfa3c4SRobert Watson 		else
166b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
167b0cfa3c4SRobert Watson 		close(dfd);
168b0cfa3c4SRobert Watson 	} else {
169323b92baSEnji Cooper 		if (expected_errno && expected_errno == errno)
170b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
171323b92baSEnji Cooper 		else if (expected_errno != 0)
172b0cfa3c4SRobert Watson 			notok_mode(testname, "wrong errno", mode);
173b0cfa3c4SRobert Watson 		else
174b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
175b0cfa3c4SRobert Watson 	}
176b0cfa3c4SRobert Watson }
177b0cfa3c4SRobert Watson 
178b0cfa3c4SRobert Watson static void
check_directory_open_modes(const char * directory,const int * modes,int modes_count)179b0cfa3c4SRobert Watson check_directory_open_modes(const char *directory, const int *modes,
180b0cfa3c4SRobert Watson     int modes_count)
181b0cfa3c4SRobert Watson {
182b0cfa3c4SRobert Watson 	int expected_errno, i, mode;
183b0cfa3c4SRobert Watson 
184b0cfa3c4SRobert Watson 	/*
185b0cfa3c4SRobert Watson 	 * Directories should only open with O_RDONLY.  Notice that we use
186b0cfa3c4SRobert Watson 	 * file_modes and not dirmodes.
187b0cfa3c4SRobert Watson 	 */
188b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
189b0cfa3c4SRobert Watson 		mode = modes[i];
190b0cfa3c4SRobert Watson 		if (mode == O_RDONLY)
191b0cfa3c4SRobert Watson 			expected_errno = 0;
192b0cfa3c4SRobert Watson 		else
193b0cfa3c4SRobert Watson 			expected_errno = EISDIR;
194b0cfa3c4SRobert Watson 		try_directory_open(__func__, directory, mode,
195b0cfa3c4SRobert Watson 		    expected_errno);
196b0cfa3c4SRobert Watson 	}
197b0cfa3c4SRobert Watson }
198b0cfa3c4SRobert Watson 
199b0cfa3c4SRobert Watson static void
check_dup(const char * testname,const char * path,const int * modes,int modes_count)200b0cfa3c4SRobert Watson check_dup(const char *testname, const char *path, const int *modes,
201b0cfa3c4SRobert Watson     int modes_count)
202b0cfa3c4SRobert Watson {
203b0cfa3c4SRobert Watson 	int dfd, fd, i, mode;
204b0cfa3c4SRobert Watson 
205b0cfa3c4SRobert Watson 	/*
206b0cfa3c4SRobert Watson 	 * dup() should work regardless of open mode.
207b0cfa3c4SRobert Watson 	 */
208b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
209b0cfa3c4SRobert Watson 		mode = modes[i];
210b0cfa3c4SRobert Watson 		fd = open(path, mode);
211b0cfa3c4SRobert Watson 		if (fd < 0) {
212b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
213b0cfa3c4SRobert Watson 			continue;
214b0cfa3c4SRobert Watson 		}
215b0cfa3c4SRobert Watson 		dfd = dup(fd);
216b0cfa3c4SRobert Watson 		if (dfd >= 0) {
217b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
218b0cfa3c4SRobert Watson 			close(dfd);
219b0cfa3c4SRobert Watson 		} else
220b0cfa3c4SRobert Watson 			notok_mode(testname, NULL, mode);
221b0cfa3c4SRobert Watson 		close(fd);
222b0cfa3c4SRobert Watson 	}
223b0cfa3c4SRobert Watson }
224b0cfa3c4SRobert Watson 
225b0cfa3c4SRobert Watson static void
check_dup2(const char * testname,const char * path,const int * modes,int modes_count)226b0cfa3c4SRobert Watson check_dup2(const char *testname, const char *path, const int *modes,
227b0cfa3c4SRobert Watson     int modes_count)
228b0cfa3c4SRobert Watson {
229b0cfa3c4SRobert Watson 	int dfd, fd, i, mode;
230b0cfa3c4SRobert Watson 
231b0cfa3c4SRobert Watson 	/*
232b0cfa3c4SRobert Watson 	 * dup2() should work regardless of open mode.
233b0cfa3c4SRobert Watson 	 */
234b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
235b0cfa3c4SRobert Watson 		mode = modes[i];
236b0cfa3c4SRobert Watson 		fd = open(path, mode);
237b0cfa3c4SRobert Watson 		if (fd < 0) {
238b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
239b0cfa3c4SRobert Watson 			continue;
240b0cfa3c4SRobert Watson 		}
241b0cfa3c4SRobert Watson 		dfd = dup2(fd, 500);	/* Arbitrary but high number. */
242b0cfa3c4SRobert Watson 		if (dfd >= 0) {
243b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
244b0cfa3c4SRobert Watson 			close(dfd);
245b0cfa3c4SRobert Watson 		} else
246b0cfa3c4SRobert Watson 			notok_mode(testname, NULL, mode);
247b0cfa3c4SRobert Watson 		close(fd);
248b0cfa3c4SRobert Watson 	}
249b0cfa3c4SRobert Watson }
250b0cfa3c4SRobert Watson 
251b0cfa3c4SRobert Watson static void
check_fchdir(const char * testname,const char * path,const int * modes,int modes_count)252b0cfa3c4SRobert Watson check_fchdir(const char *testname, const char *path, const int *modes,
253b0cfa3c4SRobert Watson     int modes_count)
254b0cfa3c4SRobert Watson {
255b0cfa3c4SRobert Watson 	int fd, i, mode;
256b0cfa3c4SRobert Watson 
257b0cfa3c4SRobert Watson 	/*
258b0cfa3c4SRobert Watson 	 * fchdir() should work regardless of open mode.
259b0cfa3c4SRobert Watson 	 */
260b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
261b0cfa3c4SRobert Watson 		mode = modes[i];
262b0cfa3c4SRobert Watson 		fd = open(path, mode);
263b0cfa3c4SRobert Watson 		if (fd < 0) {
264b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
265b0cfa3c4SRobert Watson 			continue;
266b0cfa3c4SRobert Watson 		}
267b0cfa3c4SRobert Watson 		if (fchdir(fd) == 0)
268b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
269b0cfa3c4SRobert Watson 		else
270b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
271b0cfa3c4SRobert Watson 		close(fd);
272b0cfa3c4SRobert Watson 	}
273b0cfa3c4SRobert Watson }
274b0cfa3c4SRobert Watson 
275b0cfa3c4SRobert Watson static void
check_fchflags(const char * testname,const char * path,const int * modes,int modes_count)276b0cfa3c4SRobert Watson check_fchflags(const char *testname, const char *path, const int *modes,
277b0cfa3c4SRobert Watson     int modes_count)
278b0cfa3c4SRobert Watson {
279b0cfa3c4SRobert Watson 	int fd, i, mode;
280b0cfa3c4SRobert Watson 
281b0cfa3c4SRobert Watson 	/*
282b0cfa3c4SRobert Watson 	 * fchflags() should work regardless of open mode.
283b0cfa3c4SRobert Watson 	 */
284b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
285b0cfa3c4SRobert Watson 		mode = modes[i];
286b0cfa3c4SRobert Watson 		fd = open(path, mode);
287b0cfa3c4SRobert Watson 		if (fd < 0) {
288b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
289b0cfa3c4SRobert Watson 			continue;
290b0cfa3c4SRobert Watson 		}
291b0cfa3c4SRobert Watson 		if (fchflags(fd, UF_NODUMP) == 0)
292b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
293b0cfa3c4SRobert Watson 		else
294b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
295b0cfa3c4SRobert Watson 		close(fd);
296b0cfa3c4SRobert Watson 	}
297b0cfa3c4SRobert Watson }
298b0cfa3c4SRobert Watson 
299b0cfa3c4SRobert Watson static void
check_fchmod(const char * testname,const char * path,int setmode,const int * modes,int modes_count)300b0cfa3c4SRobert Watson check_fchmod(const char *testname, const char *path, int setmode,
301b0cfa3c4SRobert Watson     const int *modes, int modes_count)
302b0cfa3c4SRobert Watson {
303b0cfa3c4SRobert Watson 	int fd, i, mode;
304b0cfa3c4SRobert Watson 
305b0cfa3c4SRobert Watson 	/*
306b0cfa3c4SRobert Watson 	 * fchmod() should work regardless of open mode.
307b0cfa3c4SRobert Watson 	 */
308b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
309b0cfa3c4SRobert Watson 		mode = modes[i];
310b0cfa3c4SRobert Watson 		fd = open(path, mode);
311b0cfa3c4SRobert Watson 		if (fd < 0) {
312b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
313b0cfa3c4SRobert Watson 			continue;
314b0cfa3c4SRobert Watson 		}
315b0cfa3c4SRobert Watson 		if (fchmod(fd, setmode) == 0)
316b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
317b0cfa3c4SRobert Watson 		else
318b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
319b0cfa3c4SRobert Watson 		close(fd);
320b0cfa3c4SRobert Watson 	}
321b0cfa3c4SRobert Watson }
322b0cfa3c4SRobert Watson 
323b0cfa3c4SRobert Watson static void
check_fchown(const char * testname,const char * path,const int * modes,int modes_count)324b0cfa3c4SRobert Watson check_fchown(const char *testname, const char *path, const int *modes,
325b0cfa3c4SRobert Watson     int modes_count)
326b0cfa3c4SRobert Watson {
327b0cfa3c4SRobert Watson 	int fd, i, mode;
328b0cfa3c4SRobert Watson 
329b0cfa3c4SRobert Watson 	/*
330b0cfa3c4SRobert Watson 	 * fchown() should work regardless of open mode.
331b0cfa3c4SRobert Watson 	 */
332b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
333b0cfa3c4SRobert Watson 		mode = modes[i];
334b0cfa3c4SRobert Watson 		fd = open(path, mode);
335b0cfa3c4SRobert Watson 		if (fd < 0) {
336b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
337b0cfa3c4SRobert Watson 			continue;
338b0cfa3c4SRobert Watson 		}
339b0cfa3c4SRobert Watson 		if (fchown(fd, -1, -1) == 0)
340b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
341b0cfa3c4SRobert Watson 		else
342b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
343b0cfa3c4SRobert Watson 		close(fd);
344b0cfa3c4SRobert Watson 	}
345b0cfa3c4SRobert Watson }
346b0cfa3c4SRobert Watson 
347b0cfa3c4SRobert Watson static void
check_flock(const char * testname,const char * path,const int * modes,int modes_count)348b0cfa3c4SRobert Watson check_flock(const char *testname, const char *path, const int *modes,
349b0cfa3c4SRobert Watson     int modes_count)
350b0cfa3c4SRobert Watson {
351b0cfa3c4SRobert Watson 	int fd, i, mode;
352b0cfa3c4SRobert Watson 
353b0cfa3c4SRobert Watson 	/*
354b0cfa3c4SRobert Watson 	 * flock() should work regardless of open mode.
355b0cfa3c4SRobert Watson 	 */
356b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
357b0cfa3c4SRobert Watson 		mode = modes[i];
358b0cfa3c4SRobert Watson 		fd = open(path, mode);
359b0cfa3c4SRobert Watson 		if (fd < 0) {
360b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
361b0cfa3c4SRobert Watson 			continue;
362b0cfa3c4SRobert Watson 		}
363b0cfa3c4SRobert Watson 		if (flock(fd, LOCK_EX) == 0)
364b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
365b0cfa3c4SRobert Watson 		else
366b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
367b0cfa3c4SRobert Watson 		close(fd);
368b0cfa3c4SRobert Watson 	}
369b0cfa3c4SRobert Watson }
370b0cfa3c4SRobert Watson 
371b0cfa3c4SRobert Watson static void
check_fpathconf(const char * testname,const char * path,const int * modes,int modes_count)372b0cfa3c4SRobert Watson check_fpathconf(const char *testname, const char *path, const int *modes,
373b0cfa3c4SRobert Watson     int modes_count)
374b0cfa3c4SRobert Watson {
375b0cfa3c4SRobert Watson 	int fd, i, mode;
376b0cfa3c4SRobert Watson 	long l;
377b0cfa3c4SRobert Watson 
378b0cfa3c4SRobert Watson 	/*
379b0cfa3c4SRobert Watson 	 * fpathconf() should work regardless of open mode.
380b0cfa3c4SRobert Watson 	 */
381b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
382b0cfa3c4SRobert Watson 		mode = modes[i];
383b0cfa3c4SRobert Watson 		fd = open(path, mode);
384b0cfa3c4SRobert Watson 		if (fd < 0) {
385b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
386b0cfa3c4SRobert Watson 			continue;
387b0cfa3c4SRobert Watson 		}
388b0cfa3c4SRobert Watson 		l = fpathconf(fd, _PC_FILESIZEBITS);
389b0cfa3c4SRobert Watson 		if (l >= 0)
390b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
391b0cfa3c4SRobert Watson 		else
392b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
393b0cfa3c4SRobert Watson 		close(fd);
394b0cfa3c4SRobert Watson 	}
395b0cfa3c4SRobert Watson }
396b0cfa3c4SRobert Watson 
397b0cfa3c4SRobert Watson static void
check_fstat(const char * testname,const char * path,const int * modes,int modes_count)398b0cfa3c4SRobert Watson check_fstat(const char *testname, const char *path, const int *modes,
399b0cfa3c4SRobert Watson     int modes_count)
400b0cfa3c4SRobert Watson {
401b0cfa3c4SRobert Watson 	struct stat sb;
402b0cfa3c4SRobert Watson 	int fd, i, mode;
403b0cfa3c4SRobert Watson 
404b0cfa3c4SRobert Watson 	/*
405b0cfa3c4SRobert Watson 	 * fstat() should work regardless of open mode.
406b0cfa3c4SRobert Watson 	 */
407b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
408b0cfa3c4SRobert Watson 		mode = modes[i];
409b0cfa3c4SRobert Watson 		fd = open(path, mode);
410b0cfa3c4SRobert Watson 		if (fd < 0) {
411b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
412b0cfa3c4SRobert Watson 			continue;
413b0cfa3c4SRobert Watson 		}
414b0cfa3c4SRobert Watson 		if (fstat(fd, &sb) == 0)
415b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
416b0cfa3c4SRobert Watson 		else
417b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
418b0cfa3c4SRobert Watson 		close(fd);
419b0cfa3c4SRobert Watson 	}
420b0cfa3c4SRobert Watson }
421b0cfa3c4SRobert Watson 
422b0cfa3c4SRobert Watson static void
check_fstatfs(const char * testname,const char * path,const int * modes,int modes_count)423b0cfa3c4SRobert Watson check_fstatfs(const char *testname, const char *path, const int *modes,
424b0cfa3c4SRobert Watson     int modes_count)
425b0cfa3c4SRobert Watson {
426b0cfa3c4SRobert Watson 	struct statfs statfs;
427b0cfa3c4SRobert Watson 	int fd, i, mode;
428b0cfa3c4SRobert Watson 
429b0cfa3c4SRobert Watson 	/*
430b0cfa3c4SRobert Watson 	 * fstatfs() should work regardless of open mode.
431b0cfa3c4SRobert Watson 	 */
432b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
433b0cfa3c4SRobert Watson 		mode = modes[i];
434b0cfa3c4SRobert Watson 		fd = open(path, mode);
435b0cfa3c4SRobert Watson 		if (fd < 0) {
436b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
437b0cfa3c4SRobert Watson 			continue;
438b0cfa3c4SRobert Watson 		}
439b0cfa3c4SRobert Watson 		if (fstatfs(fd, &statfs) == 0)
440b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
441b0cfa3c4SRobert Watson 		else
442b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
443b0cfa3c4SRobert Watson 		close(fd);
444b0cfa3c4SRobert Watson 	}
445b0cfa3c4SRobert Watson }
446b0cfa3c4SRobert Watson 
447b0cfa3c4SRobert Watson static void
check_fsync(const char * testname,const char * path,const int * modes,int modes_count)448b0cfa3c4SRobert Watson check_fsync(const char *testname, const char *path, const int *modes,
449b0cfa3c4SRobert Watson     int modes_count)
450b0cfa3c4SRobert Watson {
451b0cfa3c4SRobert Watson 	int fd, i, mode;
452b0cfa3c4SRobert Watson 
453b0cfa3c4SRobert Watson 	/*
454b0cfa3c4SRobert Watson 	 * fstatfs() should work regardless of open mode.
455b0cfa3c4SRobert Watson 	 */
456b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
457b0cfa3c4SRobert Watson 		mode = modes[i];
458b0cfa3c4SRobert Watson 		fd = open(path, mode);
459b0cfa3c4SRobert Watson 		if (fd < 0) {
460b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
461b0cfa3c4SRobert Watson 			continue;
462b0cfa3c4SRobert Watson 		}
463b0cfa3c4SRobert Watson 		if (fsync(fd) == 0)
464b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
465b0cfa3c4SRobert Watson 		else
466b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
467b0cfa3c4SRobert Watson 		close(fd);
468b0cfa3c4SRobert Watson 	}
469b0cfa3c4SRobert Watson }
470b0cfa3c4SRobert Watson 
471b0cfa3c4SRobert Watson static void
check_ftruncate(const char * testname,const char * path,const int * modes,int modes_count)472b0cfa3c4SRobert Watson check_ftruncate(const char *testname, const char *path, const int *modes,
473b0cfa3c4SRobert Watson     int modes_count)
474b0cfa3c4SRobert Watson {
475b0cfa3c4SRobert Watson 	struct stat sb;
476b0cfa3c4SRobert Watson 	int fd, i, mode;
477b0cfa3c4SRobert Watson 
478b0cfa3c4SRobert Watson 	/*
479b0cfa3c4SRobert Watson 	 * ftruncate() should work as long as long as (mode & O_ACCMODE) is
480b0cfa3c4SRobert Watson 	 * O_RDWR or O_WRONLY.
481b0cfa3c4SRobert Watson 	 *
482b0cfa3c4SRobert Watson 	 * Directories should never be writable, so this test should always
483b0cfa3c4SRobert Watson 	 * pass for directories...
484b0cfa3c4SRobert Watson 	 */
485b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
486b0cfa3c4SRobert Watson 		mode = modes[i];
487b0cfa3c4SRobert Watson 		fd = open(path, mode);
488b0cfa3c4SRobert Watson 		if (fd < 0) {
489b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
490b0cfa3c4SRobert Watson 			notok_mode(testname, "truncate1 skipped", mode);
491b0cfa3c4SRobert Watson 			notok_mode(testname, "truncate2 skipped", mode);
492b0cfa3c4SRobert Watson 			notok_mode(testname, "truncate3 skipped", mode);
493b0cfa3c4SRobert Watson 			continue;
494b0cfa3c4SRobert Watson 		}
495b0cfa3c4SRobert Watson 		if (fstat(fd, &sb) < 0) {
496b0cfa3c4SRobert Watson 			notok_mode(testname, "fstat", mode);
497b0cfa3c4SRobert Watson 			notok_mode(testname, "truncate1 skipped", mode);
498b0cfa3c4SRobert Watson 			notok_mode(testname, "truncate2 skipped", mode);
499b0cfa3c4SRobert Watson 			notok_mode(testname, "truncate3 skipped", mode);
500b0cfa3c4SRobert Watson 			close(fd);
501b0cfa3c4SRobert Watson 			continue;
502b0cfa3c4SRobert Watson 		}
503b0cfa3c4SRobert Watson 		ok_mode(testname, "setup", mode);
504b0cfa3c4SRobert Watson 
505b0cfa3c4SRobert Watson 		/* Truncate to grow file. */
506b0cfa3c4SRobert Watson 		if (ftruncate(fd, sb.st_size + 1) == 0) {
507b0cfa3c4SRobert Watson 			if (((mode & O_ACCMODE) == O_WRONLY) ||
508b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR))
509b0cfa3c4SRobert Watson 				ok_mode(testname, "truncate1 succeeded",
510b0cfa3c4SRobert Watson 				    mode);
511b0cfa3c4SRobert Watson 			else {
512b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate1 succeeded",
513b0cfa3c4SRobert Watson 				    mode);
514b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate2 skipped",
515b0cfa3c4SRobert Watson 				    mode);
516b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate3 skipped",
517b0cfa3c4SRobert Watson 				    mode);
518b0cfa3c4SRobert Watson 				close(fd);
519b0cfa3c4SRobert Watson 				continue;
520b0cfa3c4SRobert Watson 			}
521b0cfa3c4SRobert Watson 		} else {
522b0cfa3c4SRobert Watson 			if (((mode & O_ACCMODE) == O_WRONLY) ||
523b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR)) {
524b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate1 failed",
525b0cfa3c4SRobert Watson 				    mode);
526b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate2 skipped",
527b0cfa3c4SRobert Watson 				    mode);
528b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate3 skipped",
529b0cfa3c4SRobert Watson 				    mode);
530b0cfa3c4SRobert Watson 				close(fd);
531b0cfa3c4SRobert Watson 				continue;
532b0cfa3c4SRobert Watson 			} else
533b0cfa3c4SRobert Watson 				ok_mode(testname, "truncate1 failed", mode);
534b0cfa3c4SRobert Watson 		}
535b0cfa3c4SRobert Watson 
536b0cfa3c4SRobert Watson 		/* Truncate to same size. */
537b0cfa3c4SRobert Watson 		if (ftruncate(fd, sb.st_size + 1) == 0) {
538b0cfa3c4SRobert Watson 			if (((mode & O_ACCMODE) == O_WRONLY) ||
539b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR))
540b0cfa3c4SRobert Watson 				ok_mode(testname, "truncate2 succeeded",
541b0cfa3c4SRobert Watson 				    mode);
542b0cfa3c4SRobert Watson 			else {
543b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate2 succeeded",
544b0cfa3c4SRobert Watson 				    mode);
545b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate3 skipped",
546b0cfa3c4SRobert Watson 				    mode);
547b0cfa3c4SRobert Watson 				close(fd);
548b0cfa3c4SRobert Watson 				continue;
549b0cfa3c4SRobert Watson 			}
550b0cfa3c4SRobert Watson 		} else {
551b0cfa3c4SRobert Watson 			if (((mode & O_ACCMODE) == O_WRONLY) ||
552b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR)) {
553b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate2 failed",
554b0cfa3c4SRobert Watson 				    mode);
555b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate3 skipped",
556b0cfa3c4SRobert Watson 				    mode);
557b0cfa3c4SRobert Watson 				close(fd);
558b0cfa3c4SRobert Watson 				continue;
559b0cfa3c4SRobert Watson 			} else
560b0cfa3c4SRobert Watson 				ok_mode(testname, "truncate2 failed", mode);
561b0cfa3c4SRobert Watson 		}
562b0cfa3c4SRobert Watson 
563b0cfa3c4SRobert Watson 		/* Truncate to shrink. */
564b0cfa3c4SRobert Watson 		if (ftruncate(fd, sb.st_size) == 0) {
565b0cfa3c4SRobert Watson 			if (((mode & O_ACCMODE) == O_WRONLY) ||
566b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR))
567b0cfa3c4SRobert Watson 				ok_mode(testname, "truncate3 succeeded",
568b0cfa3c4SRobert Watson 				    mode);
569b0cfa3c4SRobert Watson 			else
570b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate3 succeeded",
571b0cfa3c4SRobert Watson 				    mode);
572b0cfa3c4SRobert Watson 		} else {
573b0cfa3c4SRobert Watson 			if (((mode & O_ACCMODE) == O_WRONLY) ||
574b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR))
575b0cfa3c4SRobert Watson 				notok_mode(testname, "truncate3 failed",
576b0cfa3c4SRobert Watson 				    mode);
577b0cfa3c4SRobert Watson 			else
578b0cfa3c4SRobert Watson 				ok_mode(testname, "truncate3 failed", mode);
579b0cfa3c4SRobert Watson 		}
580b0cfa3c4SRobert Watson 		close(fd);
581b0cfa3c4SRobert Watson 	}
582b0cfa3c4SRobert Watson }
583b0cfa3c4SRobert Watson 
584b0cfa3c4SRobert Watson static void
check_futimes(const char * testname,const char * path,const int * modes,int modes_count)585b0cfa3c4SRobert Watson check_futimes(const char *testname, const char *path, const int *modes,
586b0cfa3c4SRobert Watson     int modes_count)
587b0cfa3c4SRobert Watson {
588b0cfa3c4SRobert Watson 	int fd, i, mode;
589b0cfa3c4SRobert Watson 
590b0cfa3c4SRobert Watson 	/*
591b0cfa3c4SRobert Watson 	 * futimes() should work regardless of open mode.
592b0cfa3c4SRobert Watson 	 */
593b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
594b0cfa3c4SRobert Watson 		mode = modes[i];
595b0cfa3c4SRobert Watson 		fd = open(path, mode);
596b0cfa3c4SRobert Watson 		if (fd < 0) {
597b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
598b0cfa3c4SRobert Watson 			continue;
599b0cfa3c4SRobert Watson 		}
600b0cfa3c4SRobert Watson 		if (futimes(fd, NULL) == 0)
601b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
602b0cfa3c4SRobert Watson 		else
603b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
604b0cfa3c4SRobert Watson 		close(fd);
605b0cfa3c4SRobert Watson 	}
606b0cfa3c4SRobert Watson }
607b0cfa3c4SRobert Watson 
608b0cfa3c4SRobert Watson static void
check_lseek(const char * testname,const char * path,const int * modes,int modes_count)609b0cfa3c4SRobert Watson check_lseek(const char *testname, const char *path, const int *modes,
610b0cfa3c4SRobert Watson     int modes_count)
611b0cfa3c4SRobert Watson {
612b0cfa3c4SRobert Watson 	int fd, i, mode;
613b0cfa3c4SRobert Watson 
614b0cfa3c4SRobert Watson 	/*
615b0cfa3c4SRobert Watson 	 * lseek() should work regardless of open mode.
616b0cfa3c4SRobert Watson 	 */
617b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
618b0cfa3c4SRobert Watson 		mode = modes[i];
619b0cfa3c4SRobert Watson 		fd = open(path, mode);
620b0cfa3c4SRobert Watson 		if (fd < 0) {
621b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
622b0cfa3c4SRobert Watson 			continue;
623b0cfa3c4SRobert Watson 		}
624b0cfa3c4SRobert Watson 		if (lseek(fd, 100, SEEK_SET) == 100)
625b0cfa3c4SRobert Watson 			ok_mode(testname, NULL, mode);
626b0cfa3c4SRobert Watson 		else
627b0cfa3c4SRobert Watson 			notok_mode(testname, "failed", mode);
628b0cfa3c4SRobert Watson 		close(fd);
629b0cfa3c4SRobert Watson 	}
630b0cfa3c4SRobert Watson }
631b0cfa3c4SRobert Watson 
632b0cfa3c4SRobert Watson static void
check_getdents(const char * testname,const char * path,int isdir,const int * modes,int modes_count)633b0cfa3c4SRobert Watson check_getdents(const char *testname, const char *path, int isdir,
634b0cfa3c4SRobert Watson     const int *modes, int modes_count)
635b0cfa3c4SRobert Watson {
636b0cfa3c4SRobert Watson 	int fd, i, mode;
637b0cfa3c4SRobert Watson 	char buf[8192];
638b0cfa3c4SRobert Watson 
639b0cfa3c4SRobert Watson 	/*
640b0cfa3c4SRobert Watson 	 * getdents() should always work on directories and never on files,
641b0cfa3c4SRobert Watson 	 * assuming directories are always opened for read (which they are).
642b0cfa3c4SRobert Watson 	 */
643b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
644b0cfa3c4SRobert Watson 		mode = modes[i];
645b0cfa3c4SRobert Watson 		fd = open(path, mode);
646b0cfa3c4SRobert Watson 		if (fd < 0) {
647b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
648b0cfa3c4SRobert Watson 			continue;
649b0cfa3c4SRobert Watson 		}
650b0cfa3c4SRobert Watson 		if (getdents(fd, buf, sizeof(buf)) >= 0) {
651b0cfa3c4SRobert Watson 			if (isdir && ((mode & O_ACCMODE) == O_RDONLY))
652b0cfa3c4SRobert Watson 				ok_mode(testname, "directory succeeded",
653b0cfa3c4SRobert Watson 				    mode);
654b0cfa3c4SRobert Watson 			else if (isdir)
655b0cfa3c4SRobert Watson 				notok_mode(testname, "directory succeeded",
656b0cfa3c4SRobert Watson 				    mode);
657b0cfa3c4SRobert Watson 			else
658b0cfa3c4SRobert Watson 				notok_mode(testname, "file succeeded", mode);
659b0cfa3c4SRobert Watson 		} else {
660b0cfa3c4SRobert Watson 			if (isdir && ((mode & O_ACCMODE) == O_RDONLY))
661b0cfa3c4SRobert Watson 				notok_mode(testname, "directory failed",
662b0cfa3c4SRobert Watson 				    mode);
663b0cfa3c4SRobert Watson 			else if (isdir)
664b0cfa3c4SRobert Watson 				ok_mode(testname, "directory failed", mode);
665b0cfa3c4SRobert Watson 			else
666b0cfa3c4SRobert Watson 				ok_mode(testname, "file failed", mode);
667b0cfa3c4SRobert Watson 		}
668b0cfa3c4SRobert Watson 		close(fd);
669b0cfa3c4SRobert Watson 	}
670b0cfa3c4SRobert Watson }
671b0cfa3c4SRobert Watson 
672b0cfa3c4SRobert Watson static void
check_sendfile(const char * testname,const char * path,int isdir,const int * modes,int modes_count)673b0cfa3c4SRobert Watson check_sendfile(const char *testname, const char *path, int isdir,
674b0cfa3c4SRobert Watson     const int *modes, int modes_count)
675b0cfa3c4SRobert Watson {
676b0cfa3c4SRobert Watson 	int fd, i, mode, sv[2];
677b0cfa3c4SRobert Watson 	off_t sent;
678b0cfa3c4SRobert Watson 
679b0cfa3c4SRobert Watson 	/*
680b0cfa3c4SRobert Watson 	 * sendfile() should work only on files, and only when the access mode
681b0cfa3c4SRobert Watson 	 * is O_RDONLY or O_RDWR.
682b0cfa3c4SRobert Watson 	 */
683b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
684b0cfa3c4SRobert Watson 		mode = modes[i];
685b0cfa3c4SRobert Watson 		fd = open(path, mode);
686b0cfa3c4SRobert Watson 		if (fd < 0) {
687b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
688b0cfa3c4SRobert Watson 			continue;
689b0cfa3c4SRobert Watson 		}
690b0cfa3c4SRobert Watson 		if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) < 0) {
691b0cfa3c4SRobert Watson 			notok_mode(testname, "socketpair", mode);
692b0cfa3c4SRobert Watson 			continue;
693b0cfa3c4SRobert Watson 		}
694b0cfa3c4SRobert Watson 		if (sendfile(fd, sv[0], 0, 1, NULL, &sent, 0) == 0) {
695b0cfa3c4SRobert Watson 			if (isdir)
696b0cfa3c4SRobert Watson 				notok_mode(testname, "directory succeeded",
697b0cfa3c4SRobert Watson 				    mode);
698b0cfa3c4SRobert Watson 			else if (((mode & O_ACCMODE) == O_RDONLY) ||
699b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR))
700b0cfa3c4SRobert Watson 				ok_mode(testname, "succeeded", mode);
701b0cfa3c4SRobert Watson 			else
702b0cfa3c4SRobert Watson 				notok_mode(testname, "succeeded", mode);
703b0cfa3c4SRobert Watson 		} else {
704b0cfa3c4SRobert Watson 			if (isdir)
705b0cfa3c4SRobert Watson 				ok_mode(testname, "directory failed", mode);
706b0cfa3c4SRobert Watson 			else if (((mode & O_ACCMODE) == O_RDONLY) ||
707b0cfa3c4SRobert Watson 			    ((mode & O_ACCMODE) == O_RDWR))
708b0cfa3c4SRobert Watson 				notok_mode(testname, "failed", mode);
709b0cfa3c4SRobert Watson 			else
710b0cfa3c4SRobert Watson 				ok_mode(testname, "failed", mode);
711b0cfa3c4SRobert Watson 		}
712b0cfa3c4SRobert Watson 		close(sv[0]);
713b0cfa3c4SRobert Watson 		close(sv[1]);
714b0cfa3c4SRobert Watson 		close(fd);
715b0cfa3c4SRobert Watson 	}
716b0cfa3c4SRobert Watson }
717b0cfa3c4SRobert Watson 
718b0cfa3c4SRobert Watson /*
719b0cfa3c4SRobert Watson  * Various functions write, so just make write-like wrappers for them.
720b0cfa3c4SRobert Watson  */
721b0cfa3c4SRobert Watson typedef ssize_t (*write_fn)(int d, const void *buf, size_t nbytes);
722b0cfa3c4SRobert Watson 
723b0cfa3c4SRobert Watson static ssize_t
writev_wrapper(int d,const void * buf,size_t nbytes)724b0cfa3c4SRobert Watson writev_wrapper(int d, const void *buf, size_t nbytes)
725b0cfa3c4SRobert Watson {
726b0cfa3c4SRobert Watson 	struct iovec iov;
727b0cfa3c4SRobert Watson 
728b0cfa3c4SRobert Watson 	iov.iov_base = (void *)buf;
729b0cfa3c4SRobert Watson 	iov.iov_len = nbytes;
730b0cfa3c4SRobert Watson 	return (writev(d, &iov, 1));
731b0cfa3c4SRobert Watson }
732b0cfa3c4SRobert Watson 
733b0cfa3c4SRobert Watson static ssize_t
pwrite_wrapper(int d,const void * buf,size_t nbytes)734b0cfa3c4SRobert Watson pwrite_wrapper(int d, const void *buf, size_t nbytes)
735b0cfa3c4SRobert Watson {
736b0cfa3c4SRobert Watson 
737b0cfa3c4SRobert Watson 	return (pwrite(d, buf, nbytes, 0));
738b0cfa3c4SRobert Watson }
739b0cfa3c4SRobert Watson 
740b0cfa3c4SRobert Watson static ssize_t
pwritev_wrapper(int d,const void * buf,size_t nbytes)741b0cfa3c4SRobert Watson pwritev_wrapper(int d, const void *buf, size_t nbytes)
742b0cfa3c4SRobert Watson {
743b0cfa3c4SRobert Watson 	struct iovec iov;
744b0cfa3c4SRobert Watson 
745b0cfa3c4SRobert Watson 	iov.iov_base = (void *)buf;
746b0cfa3c4SRobert Watson 	iov.iov_len = nbytes;
747b0cfa3c4SRobert Watson 	return (pwritev(d, &iov, 1, 0));
748b0cfa3c4SRobert Watson }
749b0cfa3c4SRobert Watson 
750b0cfa3c4SRobert Watson static ssize_t
aio_write_wrapper(int d,const void * buf,size_t nbytes)751b0cfa3c4SRobert Watson aio_write_wrapper(int d, const void *buf, size_t nbytes)
752b0cfa3c4SRobert Watson {
753323b92baSEnji Cooper 	struct aiocb aiocb;
754323b92baSEnji Cooper 	struct aiocb const *aiocb_array[] = { &aiocb };
755b0cfa3c4SRobert Watson 
756b0cfa3c4SRobert Watson 	bzero(&aiocb, sizeof(aiocb));
757b0cfa3c4SRobert Watson 	aiocb.aio_fildes = d;
758b0cfa3c4SRobert Watson 	aiocb.aio_buf = (void *)buf;
759b0cfa3c4SRobert Watson 	aiocb.aio_nbytes = nbytes;
760b0cfa3c4SRobert Watson 	if (aio_write(&aiocb) < 0)
761b0cfa3c4SRobert Watson 		return (-1);
762b0cfa3c4SRobert Watson 	aiocb_array[0] = &aiocb;
763b0cfa3c4SRobert Watson 	if (aio_suspend(aiocb_array, 1, NULL) < 0)
764b0cfa3c4SRobert Watson 		return (-1);
765b0cfa3c4SRobert Watson 	return (aio_return(&aiocb));
766b0cfa3c4SRobert Watson }
767b0cfa3c4SRobert Watson 
768b0cfa3c4SRobert Watson static void
check_write(const char * testname,write_fn fn,const char * path,const int * modes,int modes_count)769b0cfa3c4SRobert Watson check_write(const char *testname, write_fn fn, const char *path,
770b0cfa3c4SRobert Watson     const int *modes, int modes_count)
771b0cfa3c4SRobert Watson {
772b0cfa3c4SRobert Watson 	int fd, i, mode;
773b0cfa3c4SRobert Watson 	char ch;
774b0cfa3c4SRobert Watson 
775b0cfa3c4SRobert Watson 	/*
776b0cfa3c4SRobert Watson 	 * write() should never succeed for directories, but especially
777b0cfa3c4SRobert Watson 	 * because they can only be opened read-only.  write() on files
778b0cfa3c4SRobert Watson 	 * should succeed for O_WRONLY and O_RDWR descriptors.
779b0cfa3c4SRobert Watson 	 */
780b0cfa3c4SRobert Watson 
781b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
782b0cfa3c4SRobert Watson 		mode = modes[i];
783b0cfa3c4SRobert Watson 		fd = open(path, mode);
784b0cfa3c4SRobert Watson 		if (fd < 0) {
785b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
786b0cfa3c4SRobert Watson 			continue;
787b0cfa3c4SRobert Watson 		}
788b0cfa3c4SRobert Watson 		if (fn(fd, &ch, sizeof(ch)) < 0) {
789b0cfa3c4SRobert Watson 			if ((mode & O_ACCMODE) == O_WRONLY ||
790b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
791b0cfa3c4SRobert Watson 				notok_mode(testname, "write failed", mode);
792b0cfa3c4SRobert Watson 			else
793b0cfa3c4SRobert Watson 				ok_mode(testname, "write failed", mode);
794b0cfa3c4SRobert Watson 		} else {
795b0cfa3c4SRobert Watson 			if (!((mode & O_ACCMODE) == O_WRONLY ||
796b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR))
7978ce070c1SUlrich Spörlein 				notok_mode(testname, "write succeeded", mode);
798b0cfa3c4SRobert Watson 			else
799b0cfa3c4SRobert Watson 				ok_mode(testname, "write succeeded", mode);
800b0cfa3c4SRobert Watson 		}
801b0cfa3c4SRobert Watson 		close(fd);
802b0cfa3c4SRobert Watson 	}
803b0cfa3c4SRobert Watson }
804b0cfa3c4SRobert Watson 
805b0cfa3c4SRobert Watson /*
806b0cfa3c4SRobert Watson  * Various functions read, so just make read-like wrappers for them.
807b0cfa3c4SRobert Watson  */
808b0cfa3c4SRobert Watson typedef ssize_t (*read_fn)(int d, void *buf, size_t nbytes);
809b0cfa3c4SRobert Watson 
810b0cfa3c4SRobert Watson static ssize_t
readv_wrapper(int d,void * buf,size_t nbytes)811b0cfa3c4SRobert Watson readv_wrapper(int d, void *buf, size_t nbytes)
812b0cfa3c4SRobert Watson {
813b0cfa3c4SRobert Watson 	struct iovec iov;
814b0cfa3c4SRobert Watson 
815b0cfa3c4SRobert Watson 	iov.iov_base = buf;
816b0cfa3c4SRobert Watson 	iov.iov_len = nbytes;
817b0cfa3c4SRobert Watson 	return (readv(d, &iov, 1));
818b0cfa3c4SRobert Watson }
819b0cfa3c4SRobert Watson 
820b0cfa3c4SRobert Watson static ssize_t
pread_wrapper(int d,void * buf,size_t nbytes)821b0cfa3c4SRobert Watson pread_wrapper(int d, void *buf, size_t nbytes)
822b0cfa3c4SRobert Watson {
823b0cfa3c4SRobert Watson 
824b0cfa3c4SRobert Watson 	return (pread(d, buf, nbytes, 0));
825b0cfa3c4SRobert Watson }
826b0cfa3c4SRobert Watson 
827b0cfa3c4SRobert Watson static ssize_t
preadv_wrapper(int d,void * buf,size_t nbytes)828b0cfa3c4SRobert Watson preadv_wrapper(int d, void *buf, size_t nbytes)
829b0cfa3c4SRobert Watson {
830b0cfa3c4SRobert Watson 	struct iovec iov;
831b0cfa3c4SRobert Watson 
832b0cfa3c4SRobert Watson 	iov.iov_base = buf;
833b0cfa3c4SRobert Watson 	iov.iov_len = nbytes;
834b0cfa3c4SRobert Watson 	return (preadv(d, &iov, 1, 0));
835b0cfa3c4SRobert Watson }
836b0cfa3c4SRobert Watson 
837b0cfa3c4SRobert Watson static ssize_t
aio_read_wrapper(int d,void * buf,size_t nbytes)838b0cfa3c4SRobert Watson aio_read_wrapper(int d, void *buf, size_t nbytes)
839b0cfa3c4SRobert Watson {
840323b92baSEnji Cooper 	struct aiocb aiocb;
841323b92baSEnji Cooper 	struct aiocb const *aiocb_array[] = { &aiocb };
842b0cfa3c4SRobert Watson 
843b0cfa3c4SRobert Watson 	bzero(&aiocb, sizeof(aiocb));
844b0cfa3c4SRobert Watson 	aiocb.aio_fildes = d;
845b0cfa3c4SRobert Watson 	aiocb.aio_buf = buf;
846b0cfa3c4SRobert Watson 	aiocb.aio_nbytes = nbytes;
847b0cfa3c4SRobert Watson 	if (aio_read(&aiocb) < 0)
848b0cfa3c4SRobert Watson 		return (-1);
849b0cfa3c4SRobert Watson 	if (aio_suspend(aiocb_array, 1, NULL) < 0)
850b0cfa3c4SRobert Watson 		return (-1);
851b0cfa3c4SRobert Watson 	return (aio_return(&aiocb));
852b0cfa3c4SRobert Watson }
853b0cfa3c4SRobert Watson 
854b0cfa3c4SRobert Watson static void
check_read(const char * testname,read_fn fn,const char * path,const int * modes,int modes_count)855b0cfa3c4SRobert Watson check_read(const char *testname, read_fn fn, const char *path,
856b0cfa3c4SRobert Watson     const int *modes, int modes_count)
857b0cfa3c4SRobert Watson {
858b0cfa3c4SRobert Watson 	int fd, i, mode;
859b0cfa3c4SRobert Watson 	char ch;
860b0cfa3c4SRobert Watson 
861b0cfa3c4SRobert Watson 	/*
862b0cfa3c4SRobert Watson 	 * read() should (generally) succeeded on directories.  read() on
863b0cfa3c4SRobert Watson 	 * files should succeed for O_RDONLY and O_RDWR descriptors.
864b0cfa3c4SRobert Watson 	 */
865b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
866b0cfa3c4SRobert Watson 		mode = modes[i];
867b0cfa3c4SRobert Watson 		fd = open(path, mode);
868b0cfa3c4SRobert Watson 		if (fd < 0) {
869b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
870b0cfa3c4SRobert Watson 			continue;
871b0cfa3c4SRobert Watson 		}
872b0cfa3c4SRobert Watson 		if (fn(fd, &ch, sizeof(ch)) < 0) {
873b0cfa3c4SRobert Watson 			if ((mode & O_ACCMODE) == O_RDONLY ||
874b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
875b0cfa3c4SRobert Watson 				notok_mode(testname, "read failed", mode);
876b0cfa3c4SRobert Watson 			else
877b0cfa3c4SRobert Watson 				ok_mode(testname, "read failed", mode);
878b0cfa3c4SRobert Watson 		} else {
879b0cfa3c4SRobert Watson 			if (!((mode & O_ACCMODE) == O_RDONLY ||
880b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR))
8818ce070c1SUlrich Spörlein 				notok_mode(testname, "read succeeded", mode);
882b0cfa3c4SRobert Watson 			else
883b0cfa3c4SRobert Watson 				ok_mode(testname, "read succeeded", mode);
884b0cfa3c4SRobert Watson 		}
885b0cfa3c4SRobert Watson 		close(fd);
886b0cfa3c4SRobert Watson 	}
887b0cfa3c4SRobert Watson }
888b0cfa3c4SRobert Watson 
889b0cfa3c4SRobert Watson static void
check_mmap_read(const char * testname,const char * path,int isdir,const int * modes,int modes_count)890b0cfa3c4SRobert Watson check_mmap_read(const char *testname, const char *path, int isdir,
891b0cfa3c4SRobert Watson     const int *modes, int modes_count)
892b0cfa3c4SRobert Watson {
893b0cfa3c4SRobert Watson 	int fd, i, mode;
894b0cfa3c4SRobert Watson 	char *addr;
895b0cfa3c4SRobert Watson 
896b0cfa3c4SRobert Watson 	/*
897b0cfa3c4SRobert Watson 	 * mmap() read should fail for directories (ideally?) but succeed for
898b0cfa3c4SRobert Watson 	 * O_RDONLY and O_RDWR file descriptors.
899b0cfa3c4SRobert Watson 	 */
900b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
901b0cfa3c4SRobert Watson 		mode = modes[i];
902b0cfa3c4SRobert Watson 		fd = open(path, mode);
903b0cfa3c4SRobert Watson 		if (fd < 0) {
904b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
905b0cfa3c4SRobert Watson 			continue;
906b0cfa3c4SRobert Watson 		}
907b0cfa3c4SRobert Watson 		addr = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd,
908b0cfa3c4SRobert Watson 		    0);
909b0cfa3c4SRobert Watson 		if (addr == MAP_FAILED) {
910b0cfa3c4SRobert Watson 			if (isdir)
911b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap dir failed", mode);
912b0cfa3c4SRobert Watson 			else if ((mode & O_ACCMODE) == O_RDONLY ||
913b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
914b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap file failed",
915b0cfa3c4SRobert Watson 				    mode);
916b0cfa3c4SRobert Watson 			else
917b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap file failed", mode);
918b0cfa3c4SRobert Watson 		} else {
919b0cfa3c4SRobert Watson 			if (isdir)
920b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap dir succeeded",
921b0cfa3c4SRobert Watson 				    mode);
922b0cfa3c4SRobert Watson 			else if ((mode & O_ACCMODE) == O_RDONLY ||
923b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
924b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap file succeeded",
925b0cfa3c4SRobert Watson 				    mode);
926b0cfa3c4SRobert Watson 			else
927b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap file succeeded",
928b0cfa3c4SRobert Watson 				    mode);
929b0cfa3c4SRobert Watson 			(void)munmap(addr, getpagesize());
930b0cfa3c4SRobert Watson 		}
931b0cfa3c4SRobert Watson 		close(fd);
932b0cfa3c4SRobert Watson 	}
933b0cfa3c4SRobert Watson }
934b0cfa3c4SRobert Watson 
935b0cfa3c4SRobert Watson static void
check_mmap_write(const char * testname,const char * path,const int * modes,int modes_count)936b0cfa3c4SRobert Watson check_mmap_write(const char *testname, const char *path, const int *modes,
937b0cfa3c4SRobert Watson     int modes_count)
938b0cfa3c4SRobert Watson {
939b0cfa3c4SRobert Watson 	int fd, i, mode;
940b0cfa3c4SRobert Watson 	char *addr;
941b0cfa3c4SRobert Watson 
942b0cfa3c4SRobert Watson 	/*
943b0cfa3c4SRobert Watson 	 * mmap() will always fail for directories (ideally) as they are
944b0cfa3c4SRobert Watson 	 * always open O_RDONLY.  Check for O_WRONLY or O_RDWR to permit a
945b0cfa3c4SRobert Watson 	 * write mapping.  This variant does a MAP_SHARED mapping, but we
946b0cfa3c4SRobert Watson 	 * are also interested in MAP_PRIVATE.
947b0cfa3c4SRobert Watson 	 */
948b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
949b0cfa3c4SRobert Watson 		mode = modes[i];
950b0cfa3c4SRobert Watson 		fd = open(path, mode);
951b0cfa3c4SRobert Watson 		if (fd < 0) {
952b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
953b0cfa3c4SRobert Watson 			continue;
954b0cfa3c4SRobert Watson 		}
955b0cfa3c4SRobert Watson 		addr = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd,
956b0cfa3c4SRobert Watson 		    0);
957b0cfa3c4SRobert Watson 		if (addr == MAP_FAILED) {
958b0cfa3c4SRobert Watson 			if ((mode & O_ACCMODE) == O_WRONLY ||
959b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
960b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap failed",
961b0cfa3c4SRobert Watson 				    mode);
962b0cfa3c4SRobert Watson 			else
963b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap failed", mode);
964b0cfa3c4SRobert Watson 		} else {
965b0cfa3c4SRobert Watson 			if ((mode & O_ACCMODE) == O_WRONLY ||
966b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
967b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap succeeded",
968b0cfa3c4SRobert Watson 				    mode);
969b0cfa3c4SRobert Watson 			else
970b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap succeeded", mode);
971b0cfa3c4SRobert Watson 			(void)munmap(addr, getpagesize());
972b0cfa3c4SRobert Watson 		}
973b0cfa3c4SRobert Watson 		close(fd);
974b0cfa3c4SRobert Watson 	}
975b0cfa3c4SRobert Watson }
976b0cfa3c4SRobert Watson 
977b0cfa3c4SRobert Watson static void
check_mmap_exec(const char * testname,const char * path,int isdir,const int * modes,int modes_count)978b0cfa3c4SRobert Watson check_mmap_exec(const char *testname, const char *path, int isdir,
979b0cfa3c4SRobert Watson     const int *modes, int modes_count)
980b0cfa3c4SRobert Watson {
981b0cfa3c4SRobert Watson 	int fd, i, mode;
982b0cfa3c4SRobert Watson 	char *addr;
983b0cfa3c4SRobert Watson 
984b0cfa3c4SRobert Watson 	/*
985b0cfa3c4SRobert Watson 	 * mmap() exec should fail for directories (ideally?) but succeed for
986b0cfa3c4SRobert Watson 	 * O_RDONLY and O_RDWR file descriptors.
987b0cfa3c4SRobert Watson 	 */
988b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
989b0cfa3c4SRobert Watson 		mode = modes[i];
990b0cfa3c4SRobert Watson 		fd = open(path, mode);
991b0cfa3c4SRobert Watson 		if (fd < 0) {
992b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
993b0cfa3c4SRobert Watson 			continue;
994b0cfa3c4SRobert Watson 		}
995b0cfa3c4SRobert Watson 		addr = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd,
996b0cfa3c4SRobert Watson 		    0);
997b0cfa3c4SRobert Watson 		if (addr == MAP_FAILED) {
998b0cfa3c4SRobert Watson 			if (isdir)
999b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap dir failed", mode);
1000b0cfa3c4SRobert Watson 			else if ((mode & O_ACCMODE) == O_RDONLY ||
1001b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
1002b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap file failed",
1003b0cfa3c4SRobert Watson 				    mode);
1004b0cfa3c4SRobert Watson 			else
1005b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap file failed", mode);
1006b0cfa3c4SRobert Watson 		} else {
1007b0cfa3c4SRobert Watson 			if (isdir)
1008b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap dir succeeded",
1009b0cfa3c4SRobert Watson 				    mode);
1010b0cfa3c4SRobert Watson 			else
1011323b92baSEnji Cooper 				ok_mode(testname, "mmap file succeeded",
1012b0cfa3c4SRobert Watson 				    mode);
1013b0cfa3c4SRobert Watson 			(void)munmap(addr, getpagesize());
1014b0cfa3c4SRobert Watson 		}
1015b0cfa3c4SRobert Watson 		close(fd);
1016b0cfa3c4SRobert Watson 	}
1017b0cfa3c4SRobert Watson }
1018b0cfa3c4SRobert Watson 
1019b0cfa3c4SRobert Watson static void
check_mmap_write_private(const char * testname,const char * path,int isdir,const int * modes,int modes_count)1020b0cfa3c4SRobert Watson check_mmap_write_private(const char *testname, const char *path, int isdir,
1021b0cfa3c4SRobert Watson     const int *modes, int modes_count)
1022b0cfa3c4SRobert Watson {
1023b0cfa3c4SRobert Watson 	int fd, i, mode;
1024b0cfa3c4SRobert Watson 	char *addr;
1025b0cfa3c4SRobert Watson 
1026b0cfa3c4SRobert Watson 	/*
1027b0cfa3c4SRobert Watson 	 * mmap() write private should succeed for readable descriptors
1028b0cfa3c4SRobert Watson 	 * except for directories.
1029b0cfa3c4SRobert Watson 	 */
1030b0cfa3c4SRobert Watson 	for (i = 0; i < modes_count; i++) {
1031b0cfa3c4SRobert Watson 		mode = modes[i];
1032b0cfa3c4SRobert Watson 		fd = open(path, mode);
1033b0cfa3c4SRobert Watson 		if (fd < 0) {
1034b0cfa3c4SRobert Watson 			notok_mode(testname, "open", mode);
1035b0cfa3c4SRobert Watson 			continue;
1036b0cfa3c4SRobert Watson 		}
1037b0cfa3c4SRobert Watson 		addr = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE,
1038b0cfa3c4SRobert Watson 		    MAP_PRIVATE, fd, 0);
1039b0cfa3c4SRobert Watson 		if (addr == MAP_FAILED) {
1040b0cfa3c4SRobert Watson 			if (isdir)
1041b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap dir failed", mode);
1042b0cfa3c4SRobert Watson 			else if ((mode & O_ACCMODE) == O_RDONLY ||
1043b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
1044b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap file failed",
1045b0cfa3c4SRobert Watson 				    mode);
1046b0cfa3c4SRobert Watson 			else
1047b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap file failed", mode);
1048b0cfa3c4SRobert Watson 		} else {
1049b0cfa3c4SRobert Watson 			if (isdir)
1050b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap dir succeeded",
1051b0cfa3c4SRobert Watson 				    mode);
1052b0cfa3c4SRobert Watson 			else if ((mode & O_ACCMODE) == O_RDONLY ||
1053b0cfa3c4SRobert Watson 			    (mode & O_ACCMODE) == O_RDWR)
1054b0cfa3c4SRobert Watson 				ok_mode(testname, "mmap file succeeded",
1055b0cfa3c4SRobert Watson 				    mode);
1056b0cfa3c4SRobert Watson 			else
1057b0cfa3c4SRobert Watson 				notok_mode(testname, "mmap file succeeded",
1058b0cfa3c4SRobert Watson 				    mode);
1059b0cfa3c4SRobert Watson 			(void)munmap(addr, getpagesize());
1060b0cfa3c4SRobert Watson 		}
1061b0cfa3c4SRobert Watson 		close(fd);
1062b0cfa3c4SRobert Watson 	}
1063b0cfa3c4SRobert Watson }
1064b0cfa3c4SRobert Watson 
1065b0cfa3c4SRobert Watson int
main(void)1066323b92baSEnji Cooper main(void)
1067b0cfa3c4SRobert Watson {
1068b0cfa3c4SRobert Watson 	char dir_path[PATH_MAX], file_path[PATH_MAX];
1069b0cfa3c4SRobert Watson 	int dummy, fd;
1070b0cfa3c4SRobert Watson 	size_t size;
1071b0cfa3c4SRobert Watson 
1072b0cfa3c4SRobert Watson 	aio_present = 0;
1073b0cfa3c4SRobert Watson 	size = sizeof(dummy);
1074b0cfa3c4SRobert Watson 	if (sysctlbyname("vfs.aio", &dummy, &size, NULL, 0) < 0) {
1075b0cfa3c4SRobert Watson 		if (errno == EISDIR)
1076b0cfa3c4SRobert Watson 			aio_present = 1;
1077b0cfa3c4SRobert Watson 	}
1078b0cfa3c4SRobert Watson 
1079b0cfa3c4SRobert Watson 	strlcpy(dir_path, "/tmp/open-dir.XXXXXXXXXXX", sizeof(dir_path));
1080b0cfa3c4SRobert Watson 	if (mkdtemp(dir_path) == NULL)
1081323b92baSEnji Cooper 		err(1, "mkdtemp");
1082b0cfa3c4SRobert Watson 	if (chmod(dir_path, PERM_DIR) < 0) {
1083b0cfa3c4SRobert Watson 		warn("chmod %s", dir_path);
1084b0cfa3c4SRobert Watson 		(void)rmdir(dir_path);
1085323b92baSEnji Cooper 		exit(1);
1086b0cfa3c4SRobert Watson 	}
1087b0cfa3c4SRobert Watson 	strlcpy(file_path, "/tmp/open-file.XXXXXXXXXXX", sizeof(file_path));
1088b0cfa3c4SRobert Watson 	fd = mkstemp(file_path);
1089b0cfa3c4SRobert Watson 	if (fd < 0) {
1090b0cfa3c4SRobert Watson 		warn("mkstemp");
1091b0cfa3c4SRobert Watson 		(void)rmdir(dir_path);
1092323b92baSEnji Cooper 		exit(1);
1093b0cfa3c4SRobert Watson 	}
1094b0cfa3c4SRobert Watson 	close(fd);
1095b0cfa3c4SRobert Watson 	if (chmod(file_path, PERM_FILE) < 0) {
1096b0cfa3c4SRobert Watson 		warn("chmod %s", file_path);
1097b0cfa3c4SRobert Watson 		(void)unlink(file_path);
1098b0cfa3c4SRobert Watson 		(void)rmdir(dir_path);
1099323b92baSEnji Cooper 		exit(1);
1100b0cfa3c4SRobert Watson 	}
1101b0cfa3c4SRobert Watson 	check_directory_open_modes(dir_path, file_modes, file_modes_count);
1102b0cfa3c4SRobert Watson 
1103b0cfa3c4SRobert Watson 	check_dup("check_dup_dir", dir_path, dir_modes, dir_modes_count);
1104b0cfa3c4SRobert Watson 	check_dup("check_dup_file", file_path, file_modes, file_modes_count);
1105b0cfa3c4SRobert Watson 
1106b0cfa3c4SRobert Watson 	check_dup2("check_dup2_dir", dir_path, dir_modes, dir_modes_count);
1107b0cfa3c4SRobert Watson 	check_dup2("check_dup2_file", file_path, file_modes,
1108b0cfa3c4SRobert Watson 	    file_modes_count);
1109b0cfa3c4SRobert Watson 
1110b0cfa3c4SRobert Watson 	check_fchdir("check_fchdir", dir_path, dir_modes, dir_modes_count);
1111b0cfa3c4SRobert Watson 
1112b0cfa3c4SRobert Watson 	check_fchflags("check_fchflags_dir", dir_path, dir_modes,
1113b0cfa3c4SRobert Watson 	    dir_modes_count);
1114b0cfa3c4SRobert Watson 	check_fchflags("check_fchflags_file", file_path, file_modes,
1115b0cfa3c4SRobert Watson 	    file_modes_count);
1116b0cfa3c4SRobert Watson 
1117b0cfa3c4SRobert Watson 	check_fchmod("check_fchmod_dir", dir_path, PERM_DIR, dir_modes,
1118b0cfa3c4SRobert Watson 	    dir_modes_count);
1119b0cfa3c4SRobert Watson 	check_fchmod("check_fchmod_file", file_path, PERM_FILE, file_modes,
1120b0cfa3c4SRobert Watson 	    file_modes_count);
1121b0cfa3c4SRobert Watson 
1122b0cfa3c4SRobert Watson 	check_fchown("check_fchown_dir", dir_path, dir_modes,
1123b0cfa3c4SRobert Watson 	    dir_modes_count);
1124b0cfa3c4SRobert Watson 	check_fchown("check_fchown_file", file_path, file_modes,
1125b0cfa3c4SRobert Watson 	    file_modes_count);
1126b0cfa3c4SRobert Watson 
1127b0cfa3c4SRobert Watson 	check_flock("check_flock_dir", dir_path, dir_modes, dir_modes_count);
1128b0cfa3c4SRobert Watson 	check_flock("check_flock_file", file_path, file_modes,
1129b0cfa3c4SRobert Watson 	    file_modes_count);
1130b0cfa3c4SRobert Watson 
1131b0cfa3c4SRobert Watson 	check_fpathconf("check_fpathconf_dir", dir_path, dir_modes,
1132b0cfa3c4SRobert Watson 	    dir_modes_count);
1133b0cfa3c4SRobert Watson 	check_fpathconf("check_fpathconf_file", file_path, file_modes,
1134b0cfa3c4SRobert Watson 	    file_modes_count);
1135b0cfa3c4SRobert Watson 
1136b0cfa3c4SRobert Watson 	check_fstat("check_fstat_dir", dir_path, dir_modes, dir_modes_count);
1137b0cfa3c4SRobert Watson 	check_fstat("check_fstat_file", file_path, file_modes,
1138b0cfa3c4SRobert Watson 	    file_modes_count);
1139b0cfa3c4SRobert Watson 
1140b0cfa3c4SRobert Watson 	check_fstatfs("check_fstatfs_dir", dir_path, dir_modes,
1141b0cfa3c4SRobert Watson 	    dir_modes_count);
1142b0cfa3c4SRobert Watson 	check_fstatfs("check_fstatfs_file", file_path, file_modes,
1143b0cfa3c4SRobert Watson 	    file_modes_count);
1144b0cfa3c4SRobert Watson 
1145b0cfa3c4SRobert Watson 	check_fsync("check_fsync_dir", dir_path, dir_modes, dir_modes_count);
1146b0cfa3c4SRobert Watson 	check_fsync("check_fsync_file", file_path, file_modes,
1147b0cfa3c4SRobert Watson 	    file_modes_count);
1148b0cfa3c4SRobert Watson 
1149b0cfa3c4SRobert Watson 	check_ftruncate("check_ftruncate_dir", dir_path, dir_modes,
1150b0cfa3c4SRobert Watson 	    dir_modes_count);
1151b0cfa3c4SRobert Watson 	check_ftruncate("check_ftruncate_file", file_path, file_modes,
1152b0cfa3c4SRobert Watson 	    file_modes_count);
1153b0cfa3c4SRobert Watson 
1154b0cfa3c4SRobert Watson 	check_futimes("check_futimes_dir", dir_path, dir_modes,
1155b0cfa3c4SRobert Watson 	    dir_modes_count);
1156b0cfa3c4SRobert Watson 	check_futimes("check_futimes_file", file_path, file_modes,
1157b0cfa3c4SRobert Watson 	    file_modes_count);
1158b0cfa3c4SRobert Watson 
1159b0cfa3c4SRobert Watson 	check_lseek("check_lseek_dir", dir_path, dir_modes, dir_modes_count);
1160b0cfa3c4SRobert Watson 	check_lseek("check_lseek_file", file_path, file_modes,
1161b0cfa3c4SRobert Watson 	    file_modes_count);
1162b0cfa3c4SRobert Watson 
1163b0cfa3c4SRobert Watson 	check_getdents("check_getdents_dir", dir_path, 1, dir_modes,
1164b0cfa3c4SRobert Watson 	    dir_modes_count);
1165b0cfa3c4SRobert Watson 	check_getdents("check_getdents_file", file_path, 0, file_modes,
1166b0cfa3c4SRobert Watson 	    file_modes_count);
1167b0cfa3c4SRobert Watson 
1168b0cfa3c4SRobert Watson 	check_sendfile("check_sendfile_dir", dir_path, 1, dir_modes,
1169b0cfa3c4SRobert Watson 	    dir_modes_count);
1170b0cfa3c4SRobert Watson 	check_sendfile("check_sendfile_file", file_path, 0, file_modes,
1171b0cfa3c4SRobert Watson 	    file_modes_count);
1172b0cfa3c4SRobert Watson 
1173b0cfa3c4SRobert Watson 	check_write("check_write_dir", write, dir_path, dir_modes,
1174b0cfa3c4SRobert Watson 	    dir_modes_count);
1175b0cfa3c4SRobert Watson 	check_write("check_write_file", write, file_path, file_modes,
1176b0cfa3c4SRobert Watson 	    file_modes_count);
1177b0cfa3c4SRobert Watson 
1178b0cfa3c4SRobert Watson 	check_write("check_writev_dir", writev_wrapper, dir_path, dir_modes,
1179b0cfa3c4SRobert Watson 	    dir_modes_count);
1180b0cfa3c4SRobert Watson 	check_write("check_writev_file", writev_wrapper, file_path,
1181b0cfa3c4SRobert Watson 	    file_modes, file_modes_count);
1182b0cfa3c4SRobert Watson 
1183b0cfa3c4SRobert Watson 	check_write("check_pwrite_dir", pwrite_wrapper, dir_path, dir_modes,
1184b0cfa3c4SRobert Watson 	    dir_modes_count);
1185b0cfa3c4SRobert Watson 	check_write("check_pwrite_file", pwrite_wrapper, file_path,
1186b0cfa3c4SRobert Watson 	    file_modes, file_modes_count);
1187b0cfa3c4SRobert Watson 
1188b0cfa3c4SRobert Watson 	check_write("check_pwritev_dir", pwritev_wrapper, dir_path,
1189b0cfa3c4SRobert Watson 	    dir_modes, dir_modes_count);
1190b0cfa3c4SRobert Watson 	check_write("check_pwritev_file", pwritev_wrapper, file_path,
1191b0cfa3c4SRobert Watson 	    file_modes, file_modes_count);
1192b0cfa3c4SRobert Watson 
1193b0cfa3c4SRobert Watson 	if (aio_present) {
1194b0cfa3c4SRobert Watson 		check_write("check_aio_write_dir", aio_write_wrapper,
1195b0cfa3c4SRobert Watson 		    dir_path, dir_modes, dir_modes_count);
1196b0cfa3c4SRobert Watson 		check_write("check_aio_write_file", aio_write_wrapper,
1197b0cfa3c4SRobert Watson 		    file_path, file_modes, file_modes_count);
1198b0cfa3c4SRobert Watson 	}
1199b0cfa3c4SRobert Watson 
1200b0cfa3c4SRobert Watson 	check_read("check_read_dir", read, dir_path, dir_modes,
1201b0cfa3c4SRobert Watson 	    dir_modes_count);
1202b0cfa3c4SRobert Watson 	check_read("check_read_file", read, file_path, file_modes,
1203b0cfa3c4SRobert Watson 	    file_modes_count);
1204b0cfa3c4SRobert Watson 
1205b0cfa3c4SRobert Watson 	check_read("check_readv_dir", readv_wrapper, dir_path, dir_modes,
1206b0cfa3c4SRobert Watson 	    dir_modes_count);
1207b0cfa3c4SRobert Watson 	check_read("check_readv_file", readv_wrapper, file_path,
1208b0cfa3c4SRobert Watson 	    file_modes, file_modes_count);
1209b0cfa3c4SRobert Watson 
1210b0cfa3c4SRobert Watson 	check_read("check_pread_dir", pread_wrapper, dir_path, dir_modes,
1211b0cfa3c4SRobert Watson 	    dir_modes_count);
1212b0cfa3c4SRobert Watson 	check_read("check_pread_file", pread_wrapper, file_path,
1213b0cfa3c4SRobert Watson 	    file_modes, file_modes_count);
1214b0cfa3c4SRobert Watson 
1215b0cfa3c4SRobert Watson 	check_read("check_preadv_dir", preadv_wrapper, dir_path,
1216b0cfa3c4SRobert Watson 	    dir_modes, dir_modes_count);
1217b0cfa3c4SRobert Watson 	check_read("check_preadv_file", preadv_wrapper, file_path,
1218b0cfa3c4SRobert Watson 	    file_modes, file_modes_count);
1219b0cfa3c4SRobert Watson 
1220b0cfa3c4SRobert Watson 	if (aio_present) {
1221b0cfa3c4SRobert Watson 		check_read("check_aio_read_dir", aio_read_wrapper, dir_path,
1222b0cfa3c4SRobert Watson 		    dir_modes, dir_modes_count);
1223b0cfa3c4SRobert Watson 		check_read("check_aio_read_file", aio_read_wrapper,
1224b0cfa3c4SRobert Watson 		    file_path, file_modes, file_modes_count);
1225b0cfa3c4SRobert Watson 	}
1226b0cfa3c4SRobert Watson 
1227b0cfa3c4SRobert Watson 	check_mmap_read("check_mmap_read_dir", dir_path, 1, dir_modes,
1228b0cfa3c4SRobert Watson 	    dir_modes_count);
1229b0cfa3c4SRobert Watson 	check_mmap_read("check_mmap_read_file", file_path, 0, file_modes,
1230b0cfa3c4SRobert Watson 	    file_modes_count);
1231b0cfa3c4SRobert Watson 
1232b0cfa3c4SRobert Watson 	check_mmap_write("check_mmap_write_dir", dir_path, dir_modes,
1233b0cfa3c4SRobert Watson 	    dir_modes_count);
1234b0cfa3c4SRobert Watson 	check_mmap_write("check_mmap_write_file", file_path, file_modes,
1235b0cfa3c4SRobert Watson 	    file_modes_count);
1236b0cfa3c4SRobert Watson 
1237b0cfa3c4SRobert Watson 	check_mmap_exec("check_mmap_exec_dir", dir_path, 1, dir_modes,
1238b0cfa3c4SRobert Watson 	    dir_modes_count);
1239b0cfa3c4SRobert Watson 	check_mmap_exec("check_mmap_exec_file", file_path, 0, file_modes,
1240b0cfa3c4SRobert Watson 	    file_modes_count);
1241b0cfa3c4SRobert Watson 
1242b0cfa3c4SRobert Watson 	check_mmap_write_private("check_mmap_write_private_dir", dir_path, 1,
1243b0cfa3c4SRobert Watson 	    dir_modes, dir_modes_count);
1244b0cfa3c4SRobert Watson 	check_mmap_write_private("check_mmap_write_private_file", file_path,
1245b0cfa3c4SRobert Watson 	    0, file_modes, file_modes_count);
1246b0cfa3c4SRobert Watson 
1247b0cfa3c4SRobert Watson 	(void)unlink(file_path);
1248b0cfa3c4SRobert Watson 	(void)rmdir(dir_path);
1249b0cfa3c4SRobert Watson 	exit(0);
1250b0cfa3c4SRobert Watson }
1251