t_vfsops.c revision 1.8
1/*	$NetBSD: t_vfsops.c,v 1.8 2010/11/19 17:46:02 pooka Exp $	*/
2
3/*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/stat.h>
30#include <sys/statvfs.h>
31
32#include <atf-c.h>
33#include <dirent.h>
34#include <fcntl.h>
35#include <stdlib.h>
36#include <unistd.h>
37
38#include <rump/rump_syscalls.h>
39#include <rump/rump.h>
40
41#include "../common/h_fsmacros.h"
42#include "../../h_macros.h"
43
44static void
45tmount(const atf_tc_t *tc, const char *path)
46{
47
48	return;
49}
50
51static void
52tstatvfs(const atf_tc_t *tc, const char *path)
53{
54	const char *fstype = atf_tc_get_md_var(tc, "X-fs.type");
55	struct statvfs svb;
56
57	if (rump_sys_statvfs1(path, &svb, ST_WAIT) == -1)
58		atf_tc_fail_errno("statvfs");
59
60	ATF_REQUIRE(svb.f_namemax > 0 && svb.f_namemax <= MAXNAMLEN);
61	if (!FSTYPE_PUFFS(tc))
62		ATF_REQUIRE_STREQ(svb.f_fstypename, fstype);
63	ATF_REQUIRE_STREQ(svb.f_mntonname, path);
64}
65
66static void
67tsync(const atf_tc_t *tc, const char *path)
68{
69
70	rump_sys_sync();
71}
72
73#define MAGICSTR "just a string, I like A"
74static void
75tfilehandle(const atf_tc_t *tc, const char *path)
76{
77	char fpath[MAXPATHLEN];
78	char buf[sizeof(MAGICSTR)];
79	size_t fhsize;
80	void *fhp;
81	int fd;
82
83	sprintf(fpath, "%s/file", path);
84	fd = rump_sys_open(fpath, O_RDWR | O_CREAT, 0777);
85	if (fd == -1)
86		atf_tc_fail_errno("open");
87
88	if (rump_sys_write(fd, MAGICSTR, sizeof(MAGICSTR)) != sizeof(MAGICSTR))
89		atf_tc_fail("write to file");
90	rump_sys_close(fd);
91
92	/*
93	 * Get file handle size.
94	 * This also weeds out unsupported file systems.
95	 */
96	fhsize = 0;
97	if (rump_sys_getfh(fpath, NULL, &fhsize) == -1) {
98		if (errno == EOPNOTSUPP) {
99			atf_tc_skip("file handles not supported");
100		} else if (errno != E2BIG) {
101			atf_tc_fail_errno("getfh size");
102		}
103	}
104
105	fhp = malloc(fhsize);
106	if (rump_sys_getfh(fpath, fhp, &fhsize) == -1)
107		atf_tc_fail_errno("getfh");
108
109	/* open file based on file handle */
110	fd = rump_sys_fhopen(fhp, fhsize, O_RDONLY);
111	if (FSTYPE_TMPFS(tc)) {
112		atf_tc_expect_fail("PR kern/43605");
113		if (fd != -1 || errno != EINVAL)
114			atf_tc_expect_pass();
115	}
116	if (fd == -1) {
117		atf_tc_fail_errno("fhopen");
118	}
119
120	/* check that we got the same file */
121	if (rump_sys_read(fd, buf, sizeof(buf)) != sizeof(MAGICSTR))
122		atf_tc_fail("read fhopened file");
123
124	ATF_REQUIRE_STREQ(buf, MAGICSTR);
125
126	rump_sys_close(fd);
127}
128
129#define FNAME "a_file"
130static void
131tfhremove(const atf_tc_t *tc, const char *path)
132{
133	size_t fhsize;
134	void *fhp;
135	int fd;
136
137	RL(rump_sys_chdir(path));
138	RL(fd = rump_sys_open(FNAME, O_RDWR | O_CREAT, 0777));
139	RL(rump_sys_close(fd));
140
141	fhsize = 0;
142	if (rump_sys_getfh(FNAME, NULL, &fhsize) == -1) {
143		if (errno == EOPNOTSUPP) {
144			atf_tc_skip("file handles not supported");
145		} else if (errno != E2BIG) {
146			atf_tc_fail_errno("getfh size");
147		}
148	}
149
150	fhp = malloc(fhsize);
151	RL(rump_sys_getfh(FNAME, fhp, &fhsize));
152	RL(rump_sys_unlink(FNAME));
153
154	if (FSTYPE_MSDOS(tc) || FSTYPE_LFS(tc))
155		atf_tc_expect_fail("fhopen() for removed file succeeds "
156		    "(PR kern/43745)");
157	if (FSTYPE_TMPFS(tc))
158		atf_tc_expect_fail("PR kern/43605");
159	ATF_REQUIRE_ERRNO(ESTALE, rump_sys_fhopen(fhp, fhsize, O_RDONLY) == -1);
160	atf_tc_expect_pass();
161
162	RL(rump_sys_chdir("/"));
163}
164#undef FNAME
165
166/*
167 * This test only checks the file system doesn't crash.  We *might*
168 * try a valid file handle.
169 */
170static void
171tfhinval(const atf_tc_t *tc, const char *path)
172{
173	size_t fhsize;
174	void *fhp;
175	unsigned long seed;
176	int fd;
177
178	/* XXX: this test succeeds "accidentally" on tmpfs, PR kern/43605 */
179
180	srandom(seed = time(NULL));
181	printf("RNG seed %lu\n", seed);
182
183	RL(rump_sys_chdir(path));
184	fhsize = 0;
185	if (rump_sys_getfh(".", NULL, &fhsize) == -1) {
186		if (errno == EOPNOTSUPP) {
187			atf_tc_skip("file handles not supported");
188		} else if (errno != E2BIG) {
189			atf_tc_fail_errno("getfh size");
190		}
191	}
192
193	fhp = malloc(fhsize);
194	tests_makegarbage(fhp, fhsize);
195	fd = rump_sys_fhopen(fhp, fhsize, O_RDWR);
196	if (fd != -1)
197		rump_sys_close(fd);
198
199	RL(rump_sys_chdir("/"));
200}
201
202ATF_TC_FSAPPLY(tmount, "mount/unmount");
203ATF_TC_FSAPPLY(tstatvfs, "statvfs");
204ATF_TC_FSAPPLY(tsync, "sync");
205ATF_TC_FSAPPLY(tfilehandle, "file handles");
206ATF_TC_FSAPPLY(tfhremove, "fhtovp for removed file");
207ATF_TC_FSAPPLY(tfhinval, "fhopen invalid filehandle");
208
209ATF_TP_ADD_TCS(tp)
210{
211
212	ATF_TP_FSAPPLY(tmount);
213	ATF_TP_FSAPPLY(tstatvfs);
214	ATF_TP_FSAPPLY(tsync);
215	ATF_TP_FSAPPLY(tfilehandle);
216	ATF_TP_FSAPPLY(tfhremove);
217	ATF_TP_FSAPPLY(tfhinval);
218
219	return atf_no_error();
220}
221