xref: /minix3/tests/fs/ffs/h_quota2_tests.c (revision 11be35a165022172ed3cea20f2b5df0307540b0e)
1*11be35a1SLionel Sambuc /*	$NetBSD: h_quota2_tests.c,v 1.4 2012/09/30 21:26:57 bouyer Exp $	*/
2*11be35a1SLionel Sambuc 
3*11be35a1SLionel Sambuc /*
4*11be35a1SLionel Sambuc  * rump server for advanced quota tests
5*11be35a1SLionel Sambuc  * this one includes functions to run against the filesystem before
6*11be35a1SLionel Sambuc  * starting to handle rump requests from clients.
7*11be35a1SLionel Sambuc  */
8*11be35a1SLionel Sambuc 
9*11be35a1SLionel Sambuc #include "../common/h_fsmacros.h"
10*11be35a1SLionel Sambuc 
11*11be35a1SLionel Sambuc #include <err.h>
12*11be35a1SLionel Sambuc #include <semaphore.h>
13*11be35a1SLionel Sambuc #include <sys/types.h>
14*11be35a1SLionel Sambuc #include <sys/mount.h>
15*11be35a1SLionel Sambuc 
16*11be35a1SLionel Sambuc #include <stdlib.h>
17*11be35a1SLionel Sambuc #include <unistd.h>
18*11be35a1SLionel Sambuc 
19*11be35a1SLionel Sambuc #include <ufs/ufs/ufsmount.h>
20*11be35a1SLionel Sambuc #include <dev/fssvar.h>
21*11be35a1SLionel Sambuc 
22*11be35a1SLionel Sambuc #include <rump/rump.h>
23*11be35a1SLionel Sambuc #include <rump/rump_syscalls.h>
24*11be35a1SLionel Sambuc 
25*11be35a1SLionel Sambuc #include "../../h_macros.h"
26*11be35a1SLionel Sambuc 
27*11be35a1SLionel Sambuc int background = 0;
28*11be35a1SLionel Sambuc 
29*11be35a1SLionel Sambuc #define TEST_NONROOT_ID 1
30*11be35a1SLionel Sambuc 
31*11be35a1SLionel Sambuc static int
quota_test0(const char * testopts)32*11be35a1SLionel Sambuc quota_test0(const char *testopts)
33*11be35a1SLionel Sambuc {
34*11be35a1SLionel Sambuc 	static char buf[512];
35*11be35a1SLionel Sambuc 	int fd;
36*11be35a1SLionel Sambuc 	int error;
37*11be35a1SLionel Sambuc 	unsigned int i;
38*11be35a1SLionel Sambuc 	int chowner = 1;
39*11be35a1SLionel Sambuc 	for (i =0; testopts && i < strlen(testopts); i++) {
40*11be35a1SLionel Sambuc 		switch(testopts[i]) {
41*11be35a1SLionel Sambuc 		case 'C':
42*11be35a1SLionel Sambuc 			chowner = 0;
43*11be35a1SLionel Sambuc 			break;
44*11be35a1SLionel Sambuc 		default:
45*11be35a1SLionel Sambuc 			errx(1, "test4: unknown option %c", testopts[i]);
46*11be35a1SLionel Sambuc 		}
47*11be35a1SLionel Sambuc 	}
48*11be35a1SLionel Sambuc 	if (chowner)
49*11be35a1SLionel Sambuc 		rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
50*11be35a1SLionel Sambuc 	rump_sys_chmod(".", 0777);
51*11be35a1SLionel Sambuc 	if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
52*11be35a1SLionel Sambuc 		error = errno;
53*11be35a1SLionel Sambuc 		warn("rump_sys_setegid");
54*11be35a1SLionel Sambuc 		return error;
55*11be35a1SLionel Sambuc 	}
56*11be35a1SLionel Sambuc 	if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
57*11be35a1SLionel Sambuc 		error = errno;
58*11be35a1SLionel Sambuc 		warn("rump_sys_seteuid");
59*11be35a1SLionel Sambuc 		return error;
60*11be35a1SLionel Sambuc 	}
61*11be35a1SLionel Sambuc 	fd = rump_sys_open("test_fillup", O_CREAT | O_RDWR, 0644);
62*11be35a1SLionel Sambuc 	if (fd < 0) {
63*11be35a1SLionel Sambuc 		error = errno;
64*11be35a1SLionel Sambuc 		warn("rump_sys_open");
65*11be35a1SLionel Sambuc 	} else {
66*11be35a1SLionel Sambuc 		while (rump_sys_write(fd, buf, sizeof(buf)) == sizeof(buf))
67*11be35a1SLionel Sambuc 			error = 0;
68*11be35a1SLionel Sambuc 		error = errno;
69*11be35a1SLionel Sambuc 	}
70*11be35a1SLionel Sambuc 	rump_sys_close(fd);
71*11be35a1SLionel Sambuc 	rump_sys_seteuid(0);
72*11be35a1SLionel Sambuc 	rump_sys_setegid(0);
73*11be35a1SLionel Sambuc 	return error;
74*11be35a1SLionel Sambuc }
75*11be35a1SLionel Sambuc 
76*11be35a1SLionel Sambuc static int
quota_test1(const char * testopts)77*11be35a1SLionel Sambuc quota_test1(const char *testopts)
78*11be35a1SLionel Sambuc {
79*11be35a1SLionel Sambuc 	static char buf[512];
80*11be35a1SLionel Sambuc 	int fd;
81*11be35a1SLionel Sambuc 	int error;
82*11be35a1SLionel Sambuc 	rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
83*11be35a1SLionel Sambuc 	rump_sys_chmod(".", 0777);
84*11be35a1SLionel Sambuc 	if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
85*11be35a1SLionel Sambuc 		error = errno;
86*11be35a1SLionel Sambuc 		warn("rump_sys_setegid");
87*11be35a1SLionel Sambuc 		return error;
88*11be35a1SLionel Sambuc 	}
89*11be35a1SLionel Sambuc 	if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
90*11be35a1SLionel Sambuc 		error = errno;
91*11be35a1SLionel Sambuc 		warn("rump_sys_seteuid");
92*11be35a1SLionel Sambuc 		return error;
93*11be35a1SLionel Sambuc 	}
94*11be35a1SLionel Sambuc 	fd = rump_sys_open("test_fillup", O_CREAT | O_RDWR, 0644);
95*11be35a1SLionel Sambuc 	if (fd < 0) {
96*11be35a1SLionel Sambuc 		error = errno;
97*11be35a1SLionel Sambuc 		warn("rump_sys_open");
98*11be35a1SLionel Sambuc 	} else {
99*11be35a1SLionel Sambuc 		/*
100*11be35a1SLionel Sambuc 		 * write up to the soft limit, wait a bit, an try to
101*11be35a1SLionel Sambuc 		 * keep on writing
102*11be35a1SLionel Sambuc 		 */
103*11be35a1SLionel Sambuc 		int i;
104*11be35a1SLionel Sambuc 
105*11be35a1SLionel Sambuc 		/* write 2k: with the directory this makes 2.5K */
106*11be35a1SLionel Sambuc 		for (i = 0; i < 4; i++) {
107*11be35a1SLionel Sambuc 			error = rump_sys_write(fd, buf, sizeof(buf));
108*11be35a1SLionel Sambuc 			if (error != sizeof(buf))
109*11be35a1SLionel Sambuc 				err(1, "write failed early");
110*11be35a1SLionel Sambuc 		}
111*11be35a1SLionel Sambuc 		sleep(2);
112*11be35a1SLionel Sambuc 		/* now try to write an extra .5k */
113*11be35a1SLionel Sambuc 		if (rump_sys_write(fd, buf, sizeof(buf)) != sizeof(buf))
114*11be35a1SLionel Sambuc 			error = errno;
115*11be35a1SLionel Sambuc 		else
116*11be35a1SLionel Sambuc 			error = 0;
117*11be35a1SLionel Sambuc 	}
118*11be35a1SLionel Sambuc 	rump_sys_close(fd);
119*11be35a1SLionel Sambuc 	rump_sys_seteuid(0);
120*11be35a1SLionel Sambuc 	rump_sys_setegid(0);
121*11be35a1SLionel Sambuc 	return error;
122*11be35a1SLionel Sambuc }
123*11be35a1SLionel Sambuc 
124*11be35a1SLionel Sambuc static int
quota_test2(const char * testopts)125*11be35a1SLionel Sambuc quota_test2(const char *testopts)
126*11be35a1SLionel Sambuc {
127*11be35a1SLionel Sambuc 	static char buf[512];
128*11be35a1SLionel Sambuc 	int fd;
129*11be35a1SLionel Sambuc 	int error;
130*11be35a1SLionel Sambuc 	int i;
131*11be35a1SLionel Sambuc 	rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
132*11be35a1SLionel Sambuc 	rump_sys_chmod(".", 0777);
133*11be35a1SLionel Sambuc 	if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
134*11be35a1SLionel Sambuc 		error = errno;
135*11be35a1SLionel Sambuc 		warn("rump_sys_setegid");
136*11be35a1SLionel Sambuc 		return error;
137*11be35a1SLionel Sambuc 	}
138*11be35a1SLionel Sambuc 	if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
139*11be35a1SLionel Sambuc 		error = errno;
140*11be35a1SLionel Sambuc 		warn("rump_sys_seteuid");
141*11be35a1SLionel Sambuc 		return error;
142*11be35a1SLionel Sambuc 	}
143*11be35a1SLionel Sambuc 
144*11be35a1SLionel Sambuc 	for (i = 0; ; i++) {
145*11be35a1SLionel Sambuc 		sprintf(buf, "file%d", i);
146*11be35a1SLionel Sambuc 		fd = rump_sys_open(buf, O_CREAT | O_RDWR, 0644);
147*11be35a1SLionel Sambuc 		if (fd < 0)
148*11be35a1SLionel Sambuc 			break;
149*11be35a1SLionel Sambuc 		sprintf(buf, "test file no %d", i);
150*11be35a1SLionel Sambuc 		rump_sys_write(fd, buf, strlen(buf));
151*11be35a1SLionel Sambuc 		rump_sys_close(fd);
152*11be35a1SLionel Sambuc 	}
153*11be35a1SLionel Sambuc 	error = errno;
154*11be35a1SLionel Sambuc 
155*11be35a1SLionel Sambuc 	rump_sys_close(fd);
156*11be35a1SLionel Sambuc 	rump_sys_seteuid(0);
157*11be35a1SLionel Sambuc 	rump_sys_setegid(0);
158*11be35a1SLionel Sambuc 	return error;
159*11be35a1SLionel Sambuc }
160*11be35a1SLionel Sambuc 
161*11be35a1SLionel Sambuc static int
quota_test3(const char * testopts)162*11be35a1SLionel Sambuc quota_test3(const char *testopts)
163*11be35a1SLionel Sambuc {
164*11be35a1SLionel Sambuc 	static char buf[512];
165*11be35a1SLionel Sambuc 	int fd;
166*11be35a1SLionel Sambuc 	int error;
167*11be35a1SLionel Sambuc 	int i;
168*11be35a1SLionel Sambuc 	rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
169*11be35a1SLionel Sambuc 	rump_sys_chmod(".", 0777);
170*11be35a1SLionel Sambuc 	if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
171*11be35a1SLionel Sambuc 		error = errno;
172*11be35a1SLionel Sambuc 		warn("rump_sys_setegid");
173*11be35a1SLionel Sambuc 		return error;
174*11be35a1SLionel Sambuc 	}
175*11be35a1SLionel Sambuc 	if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
176*11be35a1SLionel Sambuc 		error = errno;
177*11be35a1SLionel Sambuc 		warn("rump_sys_seteuid");
178*11be35a1SLionel Sambuc 		return error;
179*11be35a1SLionel Sambuc 	}
180*11be35a1SLionel Sambuc 
181*11be35a1SLionel Sambuc 	/*
182*11be35a1SLionel Sambuc 	 * create files one past the soft limit: one less as we already own the
183*11be35a1SLionel Sambuc 	 * root directory
184*11be35a1SLionel Sambuc 	 */
185*11be35a1SLionel Sambuc 	for (i = 0; i < 4; i++) {
186*11be35a1SLionel Sambuc 		sprintf(buf, "file%d", i);
187*11be35a1SLionel Sambuc 		fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644);
188*11be35a1SLionel Sambuc 		if (fd < 0)
189*11be35a1SLionel Sambuc 			err(1, "file create failed early");
190*11be35a1SLionel Sambuc 		sprintf(buf, "test file no %d", i);
191*11be35a1SLionel Sambuc 		rump_sys_write(fd, buf, strlen(buf));
192*11be35a1SLionel Sambuc 		rump_sys_close(fd);
193*11be35a1SLionel Sambuc 	}
194*11be35a1SLionel Sambuc 	/* now create an extra file after grace time: this should fail */
195*11be35a1SLionel Sambuc 	sleep(2);
196*11be35a1SLionel Sambuc 	sprintf(buf, "file%d", i);
197*11be35a1SLionel Sambuc 	fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644);
198*11be35a1SLionel Sambuc 	if (fd < 0)
199*11be35a1SLionel Sambuc 		error = errno;
200*11be35a1SLionel Sambuc 	else
201*11be35a1SLionel Sambuc 		error = 0;
202*11be35a1SLionel Sambuc 
203*11be35a1SLionel Sambuc 	rump_sys_close(fd);
204*11be35a1SLionel Sambuc 	rump_sys_seteuid(0);
205*11be35a1SLionel Sambuc 	rump_sys_setegid(0);
206*11be35a1SLionel Sambuc 	return error;
207*11be35a1SLionel Sambuc }
208*11be35a1SLionel Sambuc 
209*11be35a1SLionel Sambuc static int
quota_test4(const char * testopts)210*11be35a1SLionel Sambuc quota_test4(const char *testopts)
211*11be35a1SLionel Sambuc {
212*11be35a1SLionel Sambuc 	static char buf[512];
213*11be35a1SLionel Sambuc 	int fd, fssfd;
214*11be35a1SLionel Sambuc 	struct fss_set fss;
215*11be35a1SLionel Sambuc 	unsigned int i;
216*11be35a1SLionel Sambuc 	int unl=0;
217*11be35a1SLionel Sambuc 	int unconf=0;
218*11be35a1SLionel Sambuc 
219*11be35a1SLionel Sambuc 	/*
220*11be35a1SLionel Sambuc 	 * take an internal snapshot of the filesystem, and create a new
221*11be35a1SLionel Sambuc 	 * file with some data
222*11be35a1SLionel Sambuc 	 */
223*11be35a1SLionel Sambuc 	rump_sys_chown(".", 0, 0);
224*11be35a1SLionel Sambuc 	rump_sys_chmod(".", 0777);
225*11be35a1SLionel Sambuc 
226*11be35a1SLionel Sambuc 	for (i =0; testopts && i < strlen(testopts); i++) {
227*11be35a1SLionel Sambuc 		switch(testopts[i]) {
228*11be35a1SLionel Sambuc 		case 'L':
229*11be35a1SLionel Sambuc 			unl++;
230*11be35a1SLionel Sambuc 			break;
231*11be35a1SLionel Sambuc 		case 'C':
232*11be35a1SLionel Sambuc 			unconf++;
233*11be35a1SLionel Sambuc 			break;
234*11be35a1SLionel Sambuc 		default:
235*11be35a1SLionel Sambuc 			errx(1, "test4: unknown option %c", testopts[i]);
236*11be35a1SLionel Sambuc 		}
237*11be35a1SLionel Sambuc 	}
238*11be35a1SLionel Sambuc 
239*11be35a1SLionel Sambuc 	/* first create the snapshot */
240*11be35a1SLionel Sambuc 
241*11be35a1SLionel Sambuc 	 fd = rump_sys_open(FSTEST_MNTNAME "/le_snap", O_CREAT | O_RDWR, 0777);
242*11be35a1SLionel Sambuc 	 if (fd == -1)
243*11be35a1SLionel Sambuc 		err(1, "create " FSTEST_MNTNAME "/le_snap");
244*11be35a1SLionel Sambuc 	 rump_sys_close(fd);
245*11be35a1SLionel Sambuc 	 fssfd = rump_sys_open("/dev/rfss0", O_RDWR);
246*11be35a1SLionel Sambuc 	 if (fssfd == -1)
247*11be35a1SLionel Sambuc 		err(1, "cannot open fss");
248*11be35a1SLionel Sambuc 	memset(&fss, 0, sizeof(fss));
249*11be35a1SLionel Sambuc 	fss.fss_mount = __UNCONST("/mnt");
250*11be35a1SLionel Sambuc 	fss.fss_bstore = __UNCONST(FSTEST_MNTNAME "/le_snap");
251*11be35a1SLionel Sambuc 	fss.fss_csize = 0;
252*11be35a1SLionel Sambuc 	if (rump_sys_ioctl(fssfd, FSSIOCSET, &fss) == -1)
253*11be35a1SLionel Sambuc 		err(1, "create snapshot");
254*11be35a1SLionel Sambuc 	if (unl) {
255*11be35a1SLionel Sambuc 		if (rump_sys_unlink(FSTEST_MNTNAME "/le_snap") == -1)
256*11be35a1SLionel Sambuc 			err(1, "unlink snapshot");
257*11be35a1SLionel Sambuc 	}
258*11be35a1SLionel Sambuc 
259*11be35a1SLionel Sambuc 	/* now create some extra files */
260*11be35a1SLionel Sambuc 
261*11be35a1SLionel Sambuc 	for (i = 0; i < 4; i++) {
262*11be35a1SLionel Sambuc 		sprintf(buf, "file%d", i);
263*11be35a1SLionel Sambuc 		fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644);
264*11be35a1SLionel Sambuc 		if (fd < 0)
265*11be35a1SLionel Sambuc 			err(1, "create %s", buf);
266*11be35a1SLionel Sambuc 		sprintf(buf, "test file no %d", i);
267*11be35a1SLionel Sambuc 		rump_sys_write(fd, buf, strlen(buf));
268*11be35a1SLionel Sambuc 		rump_sys_close(fd);
269*11be35a1SLionel Sambuc 	}
270*11be35a1SLionel Sambuc 	if (unconf)
271*11be35a1SLionel Sambuc 		if (rump_sys_ioctl(fssfd, FSSIOCCLR, NULL) == -1)
272*11be35a1SLionel Sambuc 			err(1, "unconfigure snapshot");
273*11be35a1SLionel Sambuc 	return 0;
274*11be35a1SLionel Sambuc }
275*11be35a1SLionel Sambuc 
276*11be35a1SLionel Sambuc static int
quota_test5(const char * testopts)277*11be35a1SLionel Sambuc quota_test5(const char *testopts)
278*11be35a1SLionel Sambuc {
279*11be35a1SLionel Sambuc 	static char buf[512];
280*11be35a1SLionel Sambuc 	int fd;
281*11be35a1SLionel Sambuc 	int remount = 0;
282*11be35a1SLionel Sambuc 	int unlnk = 0;
283*11be35a1SLionel Sambuc 	int log = 0;
284*11be35a1SLionel Sambuc 	unsigned int i;
285*11be35a1SLionel Sambuc 
286*11be35a1SLionel Sambuc 	for (i =0; testopts && i < strlen(testopts); i++) {
287*11be35a1SLionel Sambuc 		switch(testopts[i]) {
288*11be35a1SLionel Sambuc 		case 'L':
289*11be35a1SLionel Sambuc 			log++;
290*11be35a1SLionel Sambuc 			break;
291*11be35a1SLionel Sambuc 		case 'R':
292*11be35a1SLionel Sambuc 			remount++;
293*11be35a1SLionel Sambuc 			break;
294*11be35a1SLionel Sambuc 		case 'U':
295*11be35a1SLionel Sambuc 			unlnk++;
296*11be35a1SLionel Sambuc 			break;
297*11be35a1SLionel Sambuc 		default:
298*11be35a1SLionel Sambuc 			errx(1, "test4: unknown option %c", testopts[i]);
299*11be35a1SLionel Sambuc 		}
300*11be35a1SLionel Sambuc 	}
301*11be35a1SLionel Sambuc 	if (remount) {
302*11be35a1SLionel Sambuc 		struct ufs_args uargs;
303*11be35a1SLionel Sambuc 		uargs.fspec = __UNCONST("/diskdev");
304*11be35a1SLionel Sambuc 		/* remount the fs read/write */
305*11be35a1SLionel Sambuc 		if (rump_sys_mount(MOUNT_FFS, FSTEST_MNTNAME,
306*11be35a1SLionel Sambuc 		    MNT_UPDATE | (log ? MNT_LOG : 0),
307*11be35a1SLionel Sambuc 		    &uargs, sizeof(uargs)) == -1)
308*11be35a1SLionel Sambuc 			err(1, "mount ffs rw %s", FSTEST_MNTNAME);
309*11be35a1SLionel Sambuc 	}
310*11be35a1SLionel Sambuc 
311*11be35a1SLionel Sambuc 	if (unlnk) {
312*11be35a1SLionel Sambuc 		/*
313*11be35a1SLionel Sambuc 		 * open and unlink a file
314*11be35a1SLionel Sambuc 		 */
315*11be35a1SLionel Sambuc 
316*11be35a1SLionel Sambuc 		fd = rump_sys_open("unlinked_file",
317*11be35a1SLionel Sambuc 		    O_EXCL| O_CREAT | O_RDWR, 0644);
318*11be35a1SLionel Sambuc 		if (fd < 0)
319*11be35a1SLionel Sambuc 			err(1, "create %s", "unlinked_file");
320*11be35a1SLionel Sambuc 		sprintf(buf, "test unlinked_file");
321*11be35a1SLionel Sambuc 		rump_sys_write(fd, buf, strlen(buf));
322*11be35a1SLionel Sambuc 		if (rump_sys_unlink("unlinked_file") == -1)
323*11be35a1SLionel Sambuc 			err(1, "unlink unlinked_file");
324*11be35a1SLionel Sambuc 		if (rump_sys_fsync(fd) == -1)
325*11be35a1SLionel Sambuc 			err(1, "fsync unlinked_file");
326*11be35a1SLionel Sambuc 		rump_sys_reboot(RUMP_RB_NOSYNC, NULL);
327*11be35a1SLionel Sambuc 		errx(1, "reboot failed");
328*11be35a1SLionel Sambuc 		return 1;
329*11be35a1SLionel Sambuc 	}
330*11be35a1SLionel Sambuc 	return 0;
331*11be35a1SLionel Sambuc }
332*11be35a1SLionel Sambuc 
333*11be35a1SLionel Sambuc struct quota_test {
334*11be35a1SLionel Sambuc 	int (*func)(const char *);
335*11be35a1SLionel Sambuc 	const char *desc;
336*11be35a1SLionel Sambuc };
337*11be35a1SLionel Sambuc 
338*11be35a1SLionel Sambuc struct quota_test quota_tests[] = {
339*11be35a1SLionel Sambuc 	{ quota_test0, "write up to hard limit"},
340*11be35a1SLionel Sambuc 	{ quota_test1, "write beyond the soft limit after grace time"},
341*11be35a1SLionel Sambuc 	{ quota_test2, "create file up to hard limit"},
342*11be35a1SLionel Sambuc 	{ quota_test3, "create file beyond the soft limit after grace time"},
343*11be35a1SLionel Sambuc 	{ quota_test4, "take a snapshot and add some data"},
344*11be35a1SLionel Sambuc 	{ quota_test5, "open and unlink a file"},
345*11be35a1SLionel Sambuc };
346*11be35a1SLionel Sambuc 
347*11be35a1SLionel Sambuc static void
usage(void)348*11be35a1SLionel Sambuc usage(void)
349*11be35a1SLionel Sambuc {
350*11be35a1SLionel Sambuc 	unsigned int test;
351*11be35a1SLionel Sambuc 	fprintf(stderr, "usage: %s [-b] [-l] test# diskimage bindurl\n",
352*11be35a1SLionel Sambuc 	    getprogname());
353*11be35a1SLionel Sambuc 	fprintf(stderr, "available tests:\n");
354*11be35a1SLionel Sambuc 	for (test = 0; test < sizeof(quota_tests) / sizeof(quota_tests[0]);
355*11be35a1SLionel Sambuc 	    test++)
356*11be35a1SLionel Sambuc 		fprintf(stderr, "\t%d: %s\n", test, quota_tests[test].desc);
357*11be35a1SLionel Sambuc 	exit(1);
358*11be35a1SLionel Sambuc }
359*11be35a1SLionel Sambuc 
360*11be35a1SLionel Sambuc static void
die(const char * reason,int error)361*11be35a1SLionel Sambuc die(const char *reason, int error)
362*11be35a1SLionel Sambuc {
363*11be35a1SLionel Sambuc 
364*11be35a1SLionel Sambuc 	warnx("%s: %s", reason, strerror(error));
365*11be35a1SLionel Sambuc 	if (background)
366*11be35a1SLionel Sambuc 		rump_daemonize_done(error);
367*11be35a1SLionel Sambuc 	exit(1);
368*11be35a1SLionel Sambuc }
369*11be35a1SLionel Sambuc 
370*11be35a1SLionel Sambuc static sem_t sigsem;
371*11be35a1SLionel Sambuc static void
sigreboot(int sig)372*11be35a1SLionel Sambuc sigreboot(int sig)
373*11be35a1SLionel Sambuc {
374*11be35a1SLionel Sambuc 
375*11be35a1SLionel Sambuc 	sem_post(&sigsem);
376*11be35a1SLionel Sambuc }
377*11be35a1SLionel Sambuc 
378*11be35a1SLionel Sambuc int
main(int argc,char ** argv)379*11be35a1SLionel Sambuc main(int argc, char **argv)
380*11be35a1SLionel Sambuc {
381*11be35a1SLionel Sambuc 	int error;
382*11be35a1SLionel Sambuc 	u_long test;
383*11be35a1SLionel Sambuc 	char *end;
384*11be35a1SLionel Sambuc 	struct ufs_args uargs;
385*11be35a1SLionel Sambuc 	const char *filename;
386*11be35a1SLionel Sambuc 	const char *serverurl;
387*11be35a1SLionel Sambuc 	const char *topts = NULL;
388*11be35a1SLionel Sambuc 	int mntopts = 0;
389*11be35a1SLionel Sambuc 	int ch;
390*11be35a1SLionel Sambuc 
391*11be35a1SLionel Sambuc 	while ((ch = getopt(argc, argv, "blo:r")) != -1) {
392*11be35a1SLionel Sambuc 		switch(ch) {
393*11be35a1SLionel Sambuc 		case 'b':
394*11be35a1SLionel Sambuc 			background = 1;
395*11be35a1SLionel Sambuc 			break;
396*11be35a1SLionel Sambuc 		case 'l':
397*11be35a1SLionel Sambuc 			mntopts |= MNT_LOG;
398*11be35a1SLionel Sambuc 			break;
399*11be35a1SLionel Sambuc 		case 'r':
400*11be35a1SLionel Sambuc 			mntopts |= MNT_RDONLY;
401*11be35a1SLionel Sambuc 			break;
402*11be35a1SLionel Sambuc 		case 'o':
403*11be35a1SLionel Sambuc 			topts = optarg;
404*11be35a1SLionel Sambuc 			break;
405*11be35a1SLionel Sambuc 		default:
406*11be35a1SLionel Sambuc 			usage();
407*11be35a1SLionel Sambuc 		}
408*11be35a1SLionel Sambuc 	}
409*11be35a1SLionel Sambuc 	argc -= optind;
410*11be35a1SLionel Sambuc 	argv += optind;
411*11be35a1SLionel Sambuc 
412*11be35a1SLionel Sambuc 	if (argc != 3)
413*11be35a1SLionel Sambuc 		usage();
414*11be35a1SLionel Sambuc 
415*11be35a1SLionel Sambuc 	filename = argv[1];
416*11be35a1SLionel Sambuc 	serverurl = argv[2];
417*11be35a1SLionel Sambuc 
418*11be35a1SLionel Sambuc 	test = strtoul(argv[0], &end, 10);
419*11be35a1SLionel Sambuc 	if (*end != '\0') {
420*11be35a1SLionel Sambuc 		usage();
421*11be35a1SLionel Sambuc 	}
422*11be35a1SLionel Sambuc 	if (test > sizeof(quota_tests) / sizeof(quota_tests[0])) {
423*11be35a1SLionel Sambuc 		usage();
424*11be35a1SLionel Sambuc 	}
425*11be35a1SLionel Sambuc 
426*11be35a1SLionel Sambuc 	if (background) {
427*11be35a1SLionel Sambuc 		error = rump_daemonize_begin();
428*11be35a1SLionel Sambuc 		if (error)
429*11be35a1SLionel Sambuc 			errx(1, "rump daemonize: %s", strerror(error));
430*11be35a1SLionel Sambuc 	}
431*11be35a1SLionel Sambuc 
432*11be35a1SLionel Sambuc 	error = rump_init();
433*11be35a1SLionel Sambuc 	if (error)
434*11be35a1SLionel Sambuc 		die("rump init failed", error);
435*11be35a1SLionel Sambuc 
436*11be35a1SLionel Sambuc 	if (rump_sys_mkdir(FSTEST_MNTNAME, 0777) == -1)
437*11be35a1SLionel Sambuc 		err(1, "mount point create");
438*11be35a1SLionel Sambuc 	rump_pub_etfs_register("/diskdev", filename, RUMP_ETFS_BLK);
439*11be35a1SLionel Sambuc 	uargs.fspec = __UNCONST("/diskdev");
440*11be35a1SLionel Sambuc 	if (rump_sys_mount(MOUNT_FFS, FSTEST_MNTNAME, mntopts,
441*11be35a1SLionel Sambuc 	    &uargs, sizeof(uargs)) == -1)
442*11be35a1SLionel Sambuc 		die("mount ffs", errno);
443*11be35a1SLionel Sambuc 
444*11be35a1SLionel Sambuc 	if (rump_sys_chdir(FSTEST_MNTNAME) == -1)
445*11be35a1SLionel Sambuc 		err(1, "cd %s", FSTEST_MNTNAME);
446*11be35a1SLionel Sambuc 	error = quota_tests[test].func(topts);
447*11be35a1SLionel Sambuc 	if (error) {
448*11be35a1SLionel Sambuc 		fprintf(stderr, " test %lu: %s returned %d: %s\n",
449*11be35a1SLionel Sambuc 		    test, quota_tests[test].desc, error, strerror(error));
450*11be35a1SLionel Sambuc 	}
451*11be35a1SLionel Sambuc 	if (rump_sys_chdir("/") == -1)
452*11be35a1SLionel Sambuc 		err(1, "cd /");
453*11be35a1SLionel Sambuc 
454*11be35a1SLionel Sambuc 	error = rump_init_server(serverurl);
455*11be35a1SLionel Sambuc 	if (error)
456*11be35a1SLionel Sambuc 		die("rump server init failed", error);
457*11be35a1SLionel Sambuc 	if (background)
458*11be35a1SLionel Sambuc 		rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS);
459*11be35a1SLionel Sambuc 
460*11be35a1SLionel Sambuc 	sem_init(&sigsem, 0, 0);
461*11be35a1SLionel Sambuc 	signal(SIGTERM, sigreboot);
462*11be35a1SLionel Sambuc 	signal(SIGINT, sigreboot);
463*11be35a1SLionel Sambuc 	sem_wait(&sigsem);
464*11be35a1SLionel Sambuc 
465*11be35a1SLionel Sambuc 	rump_sys_reboot(0, NULL);
466*11be35a1SLionel Sambuc 	/*NOTREACHED*/
467*11be35a1SLionel Sambuc 	return 0;
468*11be35a1SLionel Sambuc }
469