1314817Sngie/*	$NetBSD: t_basic.c,v 1.4 2017/01/13 21:30:40 christos Exp $	*/
2272343Sngie
3272343Sngie#include <sys/types.h>
4272343Sngie#include <sys/mount.h>
5272343Sngie
6272343Sngie#include <atf-c.h>
7272343Sngie#include <err.h>
8272343Sngie#include <errno.h>
9272343Sngie#include <fcntl.h>
10272343Sngie#include <stdio.h>
11272343Sngie#include <unistd.h>
12272343Sngie#include <string.h>
13272343Sngie#include <stdlib.h>
14272343Sngie
15272343Sngie#include <rump/rump.h>
16272343Sngie#include <rump/rump_syscalls.h>
17272343Sngie
18272343Sngie#include <miscfs/nullfs/null.h>
19272343Sngie#include <fs/tmpfs/tmpfs_args.h>
20272343Sngie
21314817Sngie#include "h_macros.h"
22272343Sngie
23272343SngieATF_TC(basic);
24272343SngieATF_TC_HEAD(basic, tc)
25272343Sngie{
26272343Sngie	atf_tc_set_md_var(tc, "descr", "basic nullfs functionality");
27272343Sngie}
28272343Sngie
29272343Sngie#define MSTR "magic bus"
30272343Sngie
31272343Sngiestatic void
32272343Sngiexput_tfile(const char *path, const char *mstr)
33272343Sngie{
34272343Sngie	int fd;
35272343Sngie
36272343Sngie	fd = rump_sys_open(path, O_CREAT | O_RDWR, 0777);
37272343Sngie	if (fd == -1)
38272343Sngie		atf_tc_fail_errno("create %s", path);
39272343Sngie	if (rump_sys_write(fd, MSTR, sizeof(MSTR)) != sizeof(MSTR))
40272343Sngie		atf_tc_fail_errno("write to testfile");
41272343Sngie	rump_sys_close(fd);
42272343Sngie}
43272343Sngie
44272343Sngiestatic int
45272343Sngiexread_tfile(const char *path, const char *mstr)
46272343Sngie{
47272343Sngie	char buf[128];
48272343Sngie	int fd;
49272343Sngie
50272343Sngie	fd = rump_sys_open(path, O_RDONLY);
51272343Sngie	if (fd == -1)
52272343Sngie		return errno;
53272343Sngie	if (rump_sys_read(fd, buf, sizeof(buf)) == -1)
54272343Sngie		atf_tc_fail_errno("read tfile");
55272343Sngie	rump_sys_close(fd);
56272343Sngie	if (strcmp(buf, MSTR) == 0)
57272343Sngie		return 0;
58272343Sngie	return EPROGMISMATCH;
59272343Sngie}
60272343Sngie
61272343Sngiestatic void
62272343Sngiemountnull(const char *what, const char *mp, int flags)
63272343Sngie{
64272343Sngie	struct null_args nargs;
65272343Sngie
66272343Sngie	memset(&nargs, 0, sizeof(nargs));
67272343Sngie	nargs.nulla_target = __UNCONST(what);
68272343Sngie	if (rump_sys_mount(MOUNT_NULL, mp, flags, &nargs, sizeof(nargs)) == -1)
69272343Sngie		atf_tc_fail_errno("could not mount nullfs");
70272343Sngie
71272343Sngie}
72272343Sngie
73272343SngieATF_TC_BODY(basic, tc)
74272343Sngie{
75272343Sngie	struct tmpfs_args targs;
76272343Sngie	struct stat sb;
77272343Sngie	int error;
78272343Sngie
79272343Sngie	rump_init();
80272343Sngie	if (rump_sys_mkdir("/td1", 0777) == -1)
81272343Sngie		atf_tc_fail_errno("mp1");
82272343Sngie	if (rump_sys_mkdir("/td2", 0777) == -1)
83272343Sngie		atf_tc_fail_errno("mp1");
84272343Sngie
85272343Sngie	/* use tmpfs because rumpfs doesn't support regular files */
86272343Sngie	memset(&targs, 0, sizeof(targs));
87272343Sngie	targs.ta_version = TMPFS_ARGS_VERSION;
88272343Sngie	targs.ta_root_mode = 0777;
89272343Sngie	if (rump_sys_mount(MOUNT_TMPFS, "/td1", 0, &targs, sizeof(targs)) == -1)
90272343Sngie		atf_tc_fail_errno("could not mount tmpfs td1");
91272343Sngie
92272343Sngie	mountnull("/td1", "/td2", 0);
93272343Sngie
94272343Sngie	/* test unnull -> null */
95272343Sngie	xput_tfile("/td1/tensti", "jeppe");
96272343Sngie	error = xread_tfile("/td2/tensti", "jeppe");
97272343Sngie	if (error != 0)
98272343Sngie		atf_tc_fail("null compare failed: %d (%s)",
99272343Sngie		    error, strerror(error));
100272343Sngie
101272343Sngie	/* test null -> unnull */
102272343Sngie	xput_tfile("/td2/kiekko", "keppi");
103272343Sngie	error = xread_tfile("/td1/kiekko", "keppi");
104272343Sngie	if (error != 0)
105272343Sngie		atf_tc_fail("unnull compare failed: %d (%s)",
106272343Sngie		    error, strerror(error));
107272343Sngie
108272343Sngie	/* test unnull -> null overwrite */
109272343Sngie	xput_tfile("/td1/tensti", "se oolannin sota");
110272343Sngie	error = xread_tfile("/td2/tensti", "se oolannin sota");
111272343Sngie	if (error != 0)
112272343Sngie		atf_tc_fail("unnull compare failed: %d (%s)",
113272343Sngie		    error, strerror(error));
114272343Sngie
115272343Sngie	/* test that /td2 is unaffected in "real life" */
116272343Sngie	if (rump_sys_unmount("/td2", 0) == -1)
117272343Sngie		atf_tc_fail_errno("cannot unmount nullfs");
118272343Sngie	if ((error = rump_sys_stat("/td2/tensti", &sb)) != -1
119272343Sngie	    || errno != ENOENT) {
120272343Sngie		atf_tc_fail("stat tensti should return ENOENT, got %d", error);
121272343Sngie	}
122272343Sngie	if ((error = rump_sys_stat("/td2/kiekko", &sb)) != -1
123272343Sngie	    || errno != ENOENT) {
124272343Sngie		atf_tc_fail("stat kiekko should return ENOENT, got %d", error);
125272343Sngie	}
126272343Sngie
127272343Sngie	/* done */
128272343Sngie}
129272343Sngie
130272343SngieATF_TC(twistymount);
131272343SngieATF_TC_HEAD(twistymount, tc)
132272343Sngie{
133272343Sngie
134272343Sngie	/* this is expected to fail until the PR is fixed */
135272343Sngie	atf_tc_set_md_var(tc, "descr", "\"recursive\" mounts deadlock"
136272343Sngie	    " (kern/43439)");
137272343Sngie}
138272343Sngie
139272343Sngie/*
140272343Sngie * Mapping to identifiers in kern/43439:
141272343Sngie *  /td		= /home/current/pkgsrc
142272343Sngie *  /td/dist	= /home/current/pkgsrc/distiles
143272343Sngie *  /mp		= /usr/pkgsrc
144272343Sngie *  /mp/dist	= /usr/pkgsrc/distfiles -- "created" by first null mount
145272343Sngie */
146272343Sngie
147272343SngieATF_TC_BODY(twistymount, tc)
148272343Sngie{
149272343Sngie	int mkd = 0;
150272343Sngie
151272343Sngie	rump_init();
152272343Sngie
153272343Sngie	if (rump_sys_mkdir("/td", 0777) == -1)
154272343Sngie		atf_tc_fail_errno("mkdir %d", mkd++);
155272343Sngie	if (rump_sys_mkdir("/td/dist", 0777) == -1)
156272343Sngie		atf_tc_fail_errno("mkdir %d", mkd++);
157272343Sngie	if (rump_sys_mkdir("/mp", 0777) == -1)
158272343Sngie		atf_tc_fail_errno("mkdir %d", mkd++);
159272343Sngie
160272343Sngie	/* MNT_RDONLY doesn't matter, but just for compat with the PR */
161272343Sngie	mountnull("/td", "/mp", MNT_RDONLY);
162272343Sngie	mountnull("/td/dist", "/mp/dist", 0);
163272343Sngie
164272343Sngie	/* if we didn't get a locking-against-meself panic, we passed */
165272343Sngie}
166272343Sngie
167272343SngieATF_TP_ADD_TCS(tp)
168272343Sngie{
169272343Sngie
170272343Sngie	ATF_TP_ADD_TC(tp, basic);
171272343Sngie	ATF_TP_ADD_TC(tp, twistymount);
172272343Sngie
173272343Sngie	return atf_no_error();
174272343Sngie}
175