xref: /illumos-gate/usr/src/test/os-tests/tests/vfs/statvfs.c (revision ea7b7d8ad0ddfa6a32fb675e11cc106f686a5bb5)
1*ea7b7d8aSRobert Mustacchi /*
2*ea7b7d8aSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*ea7b7d8aSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*ea7b7d8aSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*ea7b7d8aSRobert Mustacchi  * 1.0 of the CDDL.
6*ea7b7d8aSRobert Mustacchi  *
7*ea7b7d8aSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*ea7b7d8aSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*ea7b7d8aSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*ea7b7d8aSRobert Mustacchi  */
11*ea7b7d8aSRobert Mustacchi 
12*ea7b7d8aSRobert Mustacchi /*
13*ea7b7d8aSRobert Mustacchi  * Copyright 2024 Oxide Computer Company
14*ea7b7d8aSRobert Mustacchi  */
15*ea7b7d8aSRobert Mustacchi 
16*ea7b7d8aSRobert Mustacchi /*
17*ea7b7d8aSRobert Mustacchi  * Basic tests for statvfs and fstatvfs. In particular we want to verify the
18*ea7b7d8aSRobert Mustacchi  * following:
19*ea7b7d8aSRobert Mustacchi  *
20*ea7b7d8aSRobert Mustacchi  *  - We can generate basic statvfs(2) errors like ENOENT, ENOTDIR, and EFAULT.
21*ea7b7d8aSRobert Mustacchi  *  - We can generate basic fstatvfs(2) errors like EBADF and EFAULT.
22*ea7b7d8aSRobert Mustacchi  *  - statvfs and fstatvfs work on basic file systems like /, ctfs, bootfs,
23*ea7b7d8aSRobert Mustacchi  *    objfs, procfs, tmpfs, etc. Additional paths will be allowed on the command
24*ea7b7d8aSRobert Mustacchi  *    line for this.
25*ea7b7d8aSRobert Mustacchi  *  - fstatvfs works on sockets and devices, but not pipes
26*ea7b7d8aSRobert Mustacchi  */
27*ea7b7d8aSRobert Mustacchi 
28*ea7b7d8aSRobert Mustacchi #include <stdlib.h>
29*ea7b7d8aSRobert Mustacchi #include <sys/types.h>
30*ea7b7d8aSRobert Mustacchi #include <sys/statvfs.h>
31*ea7b7d8aSRobert Mustacchi #include <stdbool.h>
32*ea7b7d8aSRobert Mustacchi #include <err.h>
33*ea7b7d8aSRobert Mustacchi #include <string.h>
34*ea7b7d8aSRobert Mustacchi #include <errno.h>
35*ea7b7d8aSRobert Mustacchi #include <unistd.h>
36*ea7b7d8aSRobert Mustacchi #include <sys/mman.h>
37*ea7b7d8aSRobert Mustacchi #include <sys/debug.h>
38*ea7b7d8aSRobert Mustacchi #include <sys/sysmacros.h>
39*ea7b7d8aSRobert Mustacchi #include <fcntl.h>
40*ea7b7d8aSRobert Mustacchi #include <sys/socket.h>
41*ea7b7d8aSRobert Mustacchi #include <port.h>
42*ea7b7d8aSRobert Mustacchi #include <door.h>
43*ea7b7d8aSRobert Mustacchi 
44*ea7b7d8aSRobert Mustacchi static bool
statvfs_fail(const char * path,int exp,struct statvfs * svp)45*ea7b7d8aSRobert Mustacchi statvfs_fail(const char *path, int exp, struct statvfs *svp)
46*ea7b7d8aSRobert Mustacchi {
47*ea7b7d8aSRobert Mustacchi 	struct statvfs st;
48*ea7b7d8aSRobert Mustacchi 
49*ea7b7d8aSRobert Mustacchi 	if (svp == NULL) {
50*ea7b7d8aSRobert Mustacchi 		svp = &st;
51*ea7b7d8aSRobert Mustacchi 	}
52*ea7b7d8aSRobert Mustacchi 
53*ea7b7d8aSRobert Mustacchi 	if (statvfs(path, svp) == 0) {
54*ea7b7d8aSRobert Mustacchi 		warnx("TEST FAILED: statvfs on %s passed, but expected %s",
55*ea7b7d8aSRobert Mustacchi 		    path, strerrorname_np(exp));
56*ea7b7d8aSRobert Mustacchi 		return (false);
57*ea7b7d8aSRobert Mustacchi 	}
58*ea7b7d8aSRobert Mustacchi 
59*ea7b7d8aSRobert Mustacchi 	if (errno != exp) {
60*ea7b7d8aSRobert Mustacchi 		warnx("TEST FAILED: statvfs on %s returned wrong errno: "
61*ea7b7d8aSRobert Mustacchi 		    "expected %s, found %s", path, strerrorname_np(exp),
62*ea7b7d8aSRobert Mustacchi 		    strerrorname_np(errno));
63*ea7b7d8aSRobert Mustacchi 		return (false);
64*ea7b7d8aSRobert Mustacchi 	}
65*ea7b7d8aSRobert Mustacchi 
66*ea7b7d8aSRobert Mustacchi 	(void) printf("TEST PASSED: statvfs on %s correctly returned %s\n",
67*ea7b7d8aSRobert Mustacchi 	    path, strerrorname_np(exp));
68*ea7b7d8aSRobert Mustacchi 	return (true);
69*ea7b7d8aSRobert Mustacchi }
70*ea7b7d8aSRobert Mustacchi 
71*ea7b7d8aSRobert Mustacchi static bool
statvfs_pass(const char * path,const char * fs)72*ea7b7d8aSRobert Mustacchi statvfs_pass(const char *path, const char *fs)
73*ea7b7d8aSRobert Mustacchi {
74*ea7b7d8aSRobert Mustacchi 	struct statvfs sv;
75*ea7b7d8aSRobert Mustacchi 
76*ea7b7d8aSRobert Mustacchi 	if (statvfs(path, &sv) != 0) {
77*ea7b7d8aSRobert Mustacchi 		warnx("TEST FAILED: statvfs on %s failed with %s, but "
78*ea7b7d8aSRobert Mustacchi 		    "expected success", path, strerrorname_np(errno));
79*ea7b7d8aSRobert Mustacchi 		return (false);
80*ea7b7d8aSRobert Mustacchi 	}
81*ea7b7d8aSRobert Mustacchi 
82*ea7b7d8aSRobert Mustacchi 	(void) printf("TEST PASSED: statvfs on %s worked\n", path);
83*ea7b7d8aSRobert Mustacchi 	if (fs == NULL) {
84*ea7b7d8aSRobert Mustacchi 		return (true);
85*ea7b7d8aSRobert Mustacchi 	}
86*ea7b7d8aSRobert Mustacchi 
87*ea7b7d8aSRobert Mustacchi 	if (strcmp(sv.f_basetype, fs) != 0) {
88*ea7b7d8aSRobert Mustacchi 		warnx("TEST FAILED: statvfs on %s has wrong fs: expected %s, "
89*ea7b7d8aSRobert Mustacchi 		    "found %s", path, fs, sv.f_basetype);
90*ea7b7d8aSRobert Mustacchi 		return (false);
91*ea7b7d8aSRobert Mustacchi 	}
92*ea7b7d8aSRobert Mustacchi 
93*ea7b7d8aSRobert Mustacchi 	(void) printf("TEST PASSED: statvfs on %s correctly indicated fs %s\n",
94*ea7b7d8aSRobert Mustacchi 	    path, fs);
95*ea7b7d8aSRobert Mustacchi 	return (true);
96*ea7b7d8aSRobert Mustacchi }
97*ea7b7d8aSRobert Mustacchi 
98*ea7b7d8aSRobert Mustacchi typedef struct {
99*ea7b7d8aSRobert Mustacchi 	const char *sp_path;
100*ea7b7d8aSRobert Mustacchi 	const char *sp_fs;
101*ea7b7d8aSRobert Mustacchi 	int sp_ret;
102*ea7b7d8aSRobert Mustacchi } statvfs_pass_t;
103*ea7b7d8aSRobert Mustacchi 
104*ea7b7d8aSRobert Mustacchi static const statvfs_pass_t statvfs_passes[] = {
105*ea7b7d8aSRobert Mustacchi 	{ "/", NULL },
106*ea7b7d8aSRobert Mustacchi 	{ "/usr/lib/libc.so.1", NULL },
107*ea7b7d8aSRobert Mustacchi 	{ "/var/run", "tmpfs" },
108*ea7b7d8aSRobert Mustacchi 	{ "/etc/svc/volatile", "tmpfs" },
109*ea7b7d8aSRobert Mustacchi 	{ "/system/boot", "bootfs" },
110*ea7b7d8aSRobert Mustacchi 	{ "/system/contract", "ctfs" },
111*ea7b7d8aSRobert Mustacchi 	{ "/system/object", "objfs" },
112*ea7b7d8aSRobert Mustacchi 	{ "/dev/fd", "fd" },
113*ea7b7d8aSRobert Mustacchi 	{ "/etc/mnttab", "mntfs" },
114*ea7b7d8aSRobert Mustacchi 	{ "/dev/net", "dev" },
115*ea7b7d8aSRobert Mustacchi 	/* This is a symlink in the GZ to /devices */
116*ea7b7d8aSRobert Mustacchi 	{ "/dev/zero", "devfs" },
117*ea7b7d8aSRobert Mustacchi 	{ "/devices/pseudo", "devfs" },
118*ea7b7d8aSRobert Mustacchi 	{ "/etc/dfs/sharetab", "sharefs" },
119*ea7b7d8aSRobert Mustacchi 	{ "/proc/self/psinfo", "proc" },
120*ea7b7d8aSRobert Mustacchi 	{ "/var/run/name_service_door", "namefs" }
121*ea7b7d8aSRobert Mustacchi };
122*ea7b7d8aSRobert Mustacchi 
123*ea7b7d8aSRobert Mustacchi typedef struct fstatvfs_test {
124*ea7b7d8aSRobert Mustacchi 	int (*ft_open)(const struct fstatvfs_test *);
125*ea7b7d8aSRobert Mustacchi 	const char *ft_path;
126*ea7b7d8aSRobert Mustacchi 	const char *ft_fs;
127*ea7b7d8aSRobert Mustacchi 	int ft_ret;
128*ea7b7d8aSRobert Mustacchi } fstatvfs_test_t;
129*ea7b7d8aSRobert Mustacchi 
130*ea7b7d8aSRobert Mustacchi static int
statvfs_open_file(const fstatvfs_test_t * test)131*ea7b7d8aSRobert Mustacchi statvfs_open_file(const fstatvfs_test_t *test)
132*ea7b7d8aSRobert Mustacchi {
133*ea7b7d8aSRobert Mustacchi 	int fd = open(test->ft_path, O_RDONLY);
134*ea7b7d8aSRobert Mustacchi 	if (fd < 0) {
135*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to open file %s",
136*ea7b7d8aSRobert Mustacchi 		    test->ft_path);
137*ea7b7d8aSRobert Mustacchi 	}
138*ea7b7d8aSRobert Mustacchi 
139*ea7b7d8aSRobert Mustacchi 	return (fd);
140*ea7b7d8aSRobert Mustacchi }
141*ea7b7d8aSRobert Mustacchi 
142*ea7b7d8aSRobert Mustacchi static int
statvfs_open_socket(const fstatvfs_test_t * test)143*ea7b7d8aSRobert Mustacchi statvfs_open_socket(const fstatvfs_test_t *test)
144*ea7b7d8aSRobert Mustacchi {
145*ea7b7d8aSRobert Mustacchi 	struct sockaddr_in in;
146*ea7b7d8aSRobert Mustacchi 	int fd = socket(PF_INET, SOCK_STREAM, 0);
147*ea7b7d8aSRobert Mustacchi 	if (fd < 0) {
148*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to create basic "
149*ea7b7d8aSRobert Mustacchi 		    "socket");
150*ea7b7d8aSRobert Mustacchi 	}
151*ea7b7d8aSRobert Mustacchi 
152*ea7b7d8aSRobert Mustacchi 	(void) memset(&in, 0, sizeof (in));
153*ea7b7d8aSRobert Mustacchi 	if (bind(fd, (struct sockaddr *)&in, sizeof (in)) != 0) {
154*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to bind socket");
155*ea7b7d8aSRobert Mustacchi 	}
156*ea7b7d8aSRobert Mustacchi 
157*ea7b7d8aSRobert Mustacchi 	return (fd);
158*ea7b7d8aSRobert Mustacchi }
159*ea7b7d8aSRobert Mustacchi 
160*ea7b7d8aSRobert Mustacchi static int
statvfs_open_uds(const fstatvfs_test_t * test)161*ea7b7d8aSRobert Mustacchi statvfs_open_uds(const fstatvfs_test_t *test)
162*ea7b7d8aSRobert Mustacchi {
163*ea7b7d8aSRobert Mustacchi 	int fd = socket(PF_UNIX, SOCK_STREAM, 0);
164*ea7b7d8aSRobert Mustacchi 	if (fd < 0) {
165*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to create UDS");
166*ea7b7d8aSRobert Mustacchi 	}
167*ea7b7d8aSRobert Mustacchi 
168*ea7b7d8aSRobert Mustacchi 	return (fd);
169*ea7b7d8aSRobert Mustacchi }
170*ea7b7d8aSRobert Mustacchi 
171*ea7b7d8aSRobert Mustacchi static int
statvfs_open_pipe(const fstatvfs_test_t * test)172*ea7b7d8aSRobert Mustacchi statvfs_open_pipe(const fstatvfs_test_t *test)
173*ea7b7d8aSRobert Mustacchi {
174*ea7b7d8aSRobert Mustacchi 	int fds[2];
175*ea7b7d8aSRobert Mustacchi 
176*ea7b7d8aSRobert Mustacchi 	if (pipe(fds) != 0) {
177*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to create pipe");
178*ea7b7d8aSRobert Mustacchi 	}
179*ea7b7d8aSRobert Mustacchi 
180*ea7b7d8aSRobert Mustacchi 	VERIFY0(close(fds[1]));
181*ea7b7d8aSRobert Mustacchi 	return (fds[0]);
182*ea7b7d8aSRobert Mustacchi }
183*ea7b7d8aSRobert Mustacchi 
184*ea7b7d8aSRobert Mustacchi static int
statvfs_open_negfd(const fstatvfs_test_t * test)185*ea7b7d8aSRobert Mustacchi statvfs_open_negfd(const fstatvfs_test_t *test)
186*ea7b7d8aSRobert Mustacchi {
187*ea7b7d8aSRobert Mustacchi 	return (-1);
188*ea7b7d8aSRobert Mustacchi }
189*ea7b7d8aSRobert Mustacchi 
190*ea7b7d8aSRobert Mustacchi static int
statvfs_open_bigfd(const fstatvfs_test_t * test)191*ea7b7d8aSRobert Mustacchi statvfs_open_bigfd(const fstatvfs_test_t *test)
192*ea7b7d8aSRobert Mustacchi {
193*ea7b7d8aSRobert Mustacchi 	return (0x7777);
194*ea7b7d8aSRobert Mustacchi }
195*ea7b7d8aSRobert Mustacchi 
196*ea7b7d8aSRobert Mustacchi static int
statvfs_open_portfs(const fstatvfs_test_t * test)197*ea7b7d8aSRobert Mustacchi statvfs_open_portfs(const fstatvfs_test_t *test)
198*ea7b7d8aSRobert Mustacchi {
199*ea7b7d8aSRobert Mustacchi 	int fd = port_create();
200*ea7b7d8aSRobert Mustacchi 	if (fd < 0) {
201*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to create event port");
202*ea7b7d8aSRobert Mustacchi 	}
203*ea7b7d8aSRobert Mustacchi 
204*ea7b7d8aSRobert Mustacchi 	return (fd);
205*ea7b7d8aSRobert Mustacchi }
206*ea7b7d8aSRobert Mustacchi 
207*ea7b7d8aSRobert Mustacchi static void
statvfs_close_door(void * cookie,char * arg,size_t size,door_desc_t * dp,uint_t ndesc)208*ea7b7d8aSRobert Mustacchi statvfs_close_door(void *cookie, char *arg, size_t size, door_desc_t *dp,
209*ea7b7d8aSRobert Mustacchi     uint_t ndesc)
210*ea7b7d8aSRobert Mustacchi {
211*ea7b7d8aSRobert Mustacchi 	(void) door_return(NULL, 0, NULL, 0);
212*ea7b7d8aSRobert Mustacchi }
213*ea7b7d8aSRobert Mustacchi 
214*ea7b7d8aSRobert Mustacchi static int
statvfs_open_door(const fstatvfs_test_t * test)215*ea7b7d8aSRobert Mustacchi statvfs_open_door(const fstatvfs_test_t *test)
216*ea7b7d8aSRobert Mustacchi {
217*ea7b7d8aSRobert Mustacchi 	int fd = door_create(statvfs_close_door, NULL, 0);
218*ea7b7d8aSRobert Mustacchi 	if (fd < 0) {
219*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to create door");
220*ea7b7d8aSRobert Mustacchi 	}
221*ea7b7d8aSRobert Mustacchi 	return (fd);
222*ea7b7d8aSRobert Mustacchi }
223*ea7b7d8aSRobert Mustacchi 
224*ea7b7d8aSRobert Mustacchi static const fstatvfs_test_t fstatvfs_tests[] = {
225*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_socket, "localhost socket", "sockfs", 0 },
226*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_uds, "UDS socket", "sockfs", 0 },
227*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_pipe, "pipe", NULL, ENOSYS },
228*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_file, "/dev/tcp", NULL, ENOSYS },
229*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_negfd, "bad fd (-1)", NULL, EBADF },
230*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_negfd, "bad fd (-1)", NULL, EBADF },
231*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_bigfd, "bad fd (0x7777)", NULL, EBADF },
232*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_portfs, "event port", NULL, ENOSYS },
233*ea7b7d8aSRobert Mustacchi 	{ statvfs_open_door, "door server", NULL, ENOSYS }
234*ea7b7d8aSRobert Mustacchi };
235*ea7b7d8aSRobert Mustacchi 
236*ea7b7d8aSRobert Mustacchi static bool
fstatvfs_test(const fstatvfs_test_t * test)237*ea7b7d8aSRobert Mustacchi fstatvfs_test(const fstatvfs_test_t *test)
238*ea7b7d8aSRobert Mustacchi {
239*ea7b7d8aSRobert Mustacchi 	struct statvfs sv;
240*ea7b7d8aSRobert Mustacchi 	int ret, fd, e;
241*ea7b7d8aSRobert Mustacchi 
242*ea7b7d8aSRobert Mustacchi 	/*
243*ea7b7d8aSRobert Mustacchi 	 * Some tests will specifically use a bad fd value trying to get EBADF.
244*ea7b7d8aSRobert Mustacchi 	 * In those cases don't try to close the fd again.
245*ea7b7d8aSRobert Mustacchi 	 */
246*ea7b7d8aSRobert Mustacchi 	fd = test->ft_open(test);
247*ea7b7d8aSRobert Mustacchi 	ret = fstatvfs(fd, &sv);
248*ea7b7d8aSRobert Mustacchi 	e = errno;
249*ea7b7d8aSRobert Mustacchi 	if (test->ft_ret != EBADF) {
250*ea7b7d8aSRobert Mustacchi 		VERIFY0(close(fd));
251*ea7b7d8aSRobert Mustacchi 	}
252*ea7b7d8aSRobert Mustacchi 
253*ea7b7d8aSRobert Mustacchi 	if (ret != 0) {
254*ea7b7d8aSRobert Mustacchi 		if (test->ft_ret == 0) {
255*ea7b7d8aSRobert Mustacchi 			warnx("TEST FAILED: fstatvfs on %s failed with %s, but "
256*ea7b7d8aSRobert Mustacchi 			    "expected success", test->ft_path,
257*ea7b7d8aSRobert Mustacchi 			    strerrorname_np(errno));
258*ea7b7d8aSRobert Mustacchi 			return (false);
259*ea7b7d8aSRobert Mustacchi 		}
260*ea7b7d8aSRobert Mustacchi 
261*ea7b7d8aSRobert Mustacchi 		if (e != test->ft_ret) {
262*ea7b7d8aSRobert Mustacchi 			warnx("TEST FAILED: fstatvfs on %s returned wrong "
263*ea7b7d8aSRobert Mustacchi 			    "errno: expected %s, found %s", test->ft_path,
264*ea7b7d8aSRobert Mustacchi 			    strerrorname_np(test->ft_ret), strerrorname_np(e));
265*ea7b7d8aSRobert Mustacchi 			return (false);
266*ea7b7d8aSRobert Mustacchi 		}
267*ea7b7d8aSRobert Mustacchi 
268*ea7b7d8aSRobert Mustacchi 		(void) printf("TEST PASSED: fstatvfs on %s correctly failed "
269*ea7b7d8aSRobert Mustacchi 		    "with %s\n", test->ft_path, strerrorname_np(test->ft_ret));
270*ea7b7d8aSRobert Mustacchi 		return (true);
271*ea7b7d8aSRobert Mustacchi 	}
272*ea7b7d8aSRobert Mustacchi 
273*ea7b7d8aSRobert Mustacchi 	if (test->ft_ret != 0) {
274*ea7b7d8aSRobert Mustacchi 		warnx("TEST FAILED: fstatvfs on %s passed, but expected %s",
275*ea7b7d8aSRobert Mustacchi 		    test->ft_path, strerrorname_np(test->ft_ret));
276*ea7b7d8aSRobert Mustacchi 		return (false);
277*ea7b7d8aSRobert Mustacchi 	}
278*ea7b7d8aSRobert Mustacchi 
279*ea7b7d8aSRobert Mustacchi 	(void) printf("TEST PASSED: fstatvfs on %s worked\n", test->ft_path);
280*ea7b7d8aSRobert Mustacchi 	if (test->ft_fs == NULL) {
281*ea7b7d8aSRobert Mustacchi 		return (true);
282*ea7b7d8aSRobert Mustacchi 	}
283*ea7b7d8aSRobert Mustacchi 
284*ea7b7d8aSRobert Mustacchi 	if (strcmp(sv.f_basetype, test->ft_fs) != 0) {
285*ea7b7d8aSRobert Mustacchi 		warnx("TEST FAILED: fstatvfs on %s has wrong fs: expected %s, "
286*ea7b7d8aSRobert Mustacchi 		    "found %s", test->ft_path, test->ft_fs, sv.f_basetype);
287*ea7b7d8aSRobert Mustacchi 		return (false);
288*ea7b7d8aSRobert Mustacchi 	}
289*ea7b7d8aSRobert Mustacchi 
290*ea7b7d8aSRobert Mustacchi 	(void) printf("TEST PASSED: fstatvfs on %s correctly indicated fs %s\n",
291*ea7b7d8aSRobert Mustacchi 	    test->ft_path, test->ft_fs);
292*ea7b7d8aSRobert Mustacchi 	return (true);
293*ea7b7d8aSRobert Mustacchi }
294*ea7b7d8aSRobert Mustacchi 
295*ea7b7d8aSRobert Mustacchi int
main(void)296*ea7b7d8aSRobert Mustacchi main(void)
297*ea7b7d8aSRobert Mustacchi {
298*ea7b7d8aSRobert Mustacchi 	int ret = EXIT_SUCCESS;
299*ea7b7d8aSRobert Mustacchi 	void *unmap;
300*ea7b7d8aSRobert Mustacchi 	long page;
301*ea7b7d8aSRobert Mustacchi 
302*ea7b7d8aSRobert Mustacchi 	page = sysconf(_SC_PAGESIZE);
303*ea7b7d8aSRobert Mustacchi 	VERIFY3S(page, >=, sizeof (struct statvfs));
304*ea7b7d8aSRobert Mustacchi 	unmap = mmap(NULL, page, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
305*ea7b7d8aSRobert Mustacchi 	if (unmap == MAP_FAILED) {
306*ea7b7d8aSRobert Mustacchi 		err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to mmap our "
307*ea7b7d8aSRobert Mustacchi 		    "empty page");
308*ea7b7d8aSRobert Mustacchi 	}
309*ea7b7d8aSRobert Mustacchi 
310*ea7b7d8aSRobert Mustacchi 	if (!statvfs_fail("/elbe12th!", ENOENT, NULL)) {
311*ea7b7d8aSRobert Mustacchi 		ret = EXIT_FAILURE;
312*ea7b7d8aSRobert Mustacchi 	}
313*ea7b7d8aSRobert Mustacchi 
314*ea7b7d8aSRobert Mustacchi 	if (!statvfs_fail("/usr/sbin/dtrace/wait", ENOTDIR, NULL)) {
315*ea7b7d8aSRobert Mustacchi 		ret = EXIT_FAILURE;
316*ea7b7d8aSRobert Mustacchi 	}
317*ea7b7d8aSRobert Mustacchi 
318*ea7b7d8aSRobert Mustacchi 	if (!statvfs_fail("/", EFAULT, unmap)) {
319*ea7b7d8aSRobert Mustacchi 		ret = EXIT_FAILURE;
320*ea7b7d8aSRobert Mustacchi 	}
321*ea7b7d8aSRobert Mustacchi 
322*ea7b7d8aSRobert Mustacchi 	/*
323*ea7b7d8aSRobert Mustacchi 	 * Each passing statvfs test should be a passing fstatvfs test as well.
324*ea7b7d8aSRobert Mustacchi 	 */
325*ea7b7d8aSRobert Mustacchi 	for (size_t i = 0; i < ARRAY_SIZE(statvfs_passes); i++) {
326*ea7b7d8aSRobert Mustacchi 		fstatvfs_test_t ft;
327*ea7b7d8aSRobert Mustacchi 
328*ea7b7d8aSRobert Mustacchi 		if (!statvfs_pass(statvfs_passes[i].sp_path,
329*ea7b7d8aSRobert Mustacchi 		    statvfs_passes[i].sp_fs)) {
330*ea7b7d8aSRobert Mustacchi 			ret = EXIT_FAILURE;
331*ea7b7d8aSRobert Mustacchi 		}
332*ea7b7d8aSRobert Mustacchi 
333*ea7b7d8aSRobert Mustacchi 		ft.ft_open = statvfs_open_file;
334*ea7b7d8aSRobert Mustacchi 		ft.ft_path = statvfs_passes[i].sp_path;
335*ea7b7d8aSRobert Mustacchi 		ft.ft_fs = statvfs_passes[i].sp_fs;
336*ea7b7d8aSRobert Mustacchi 		ft.ft_ret = 0;
337*ea7b7d8aSRobert Mustacchi 
338*ea7b7d8aSRobert Mustacchi 		if (!fstatvfs_test(&ft)) {
339*ea7b7d8aSRobert Mustacchi 			ret = EXIT_FAILURE;
340*ea7b7d8aSRobert Mustacchi 		}
341*ea7b7d8aSRobert Mustacchi 	}
342*ea7b7d8aSRobert Mustacchi 
343*ea7b7d8aSRobert Mustacchi 	for (size_t i = 0; i < ARRAY_SIZE(fstatvfs_tests); i++) {
344*ea7b7d8aSRobert Mustacchi 		if (!fstatvfs_test(&fstatvfs_tests[i])) {
345*ea7b7d8aSRobert Mustacchi 			ret = EXIT_FAILURE;
346*ea7b7d8aSRobert Mustacchi 		}
347*ea7b7d8aSRobert Mustacchi 	}
348*ea7b7d8aSRobert Mustacchi 
349*ea7b7d8aSRobert Mustacchi 	if (ret == EXIT_SUCCESS) {
350*ea7b7d8aSRobert Mustacchi 		(void) printf("All tests completed successfully\n");
351*ea7b7d8aSRobert Mustacchi 	}
352*ea7b7d8aSRobert Mustacchi 	return (ret);
353*ea7b7d8aSRobert Mustacchi }
354