h_quota2_tests.c revision 1.1.2.3 1 /* $NetBSD: h_quota2_tests.c,v 1.1.2.3 2011/02/07 16:22:50 bouyer Exp $ */
2
3 /*
4 * rump server for advanced quota tests
5 * this one includes functions to run against the filesystem before
6 * starting to handle rump requests from clients.
7 */
8
9 #include "../common/h_fsmacros.h"
10
11 #include <err.h>
12 #include <semaphore.h>
13 #include <sys/types.h>
14 #include <sys/mount.h>
15
16 #include <stdlib.h>
17 #include <unistd.h>
18
19 #include <ufs/ufs/ufsmount.h>
20
21 #include <rump/rump.h>
22 #include <rump/rump_syscalls.h>
23
24 #include "../../h_macros.h"
25
26 int background = 0;
27
28 #define TEST_NONROOT_ID 1
29
30 static int
31 quota_test0(void)
32 {
33 static char buf[512];
34 int fd;
35 int error;
36 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
37 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
38 error = errno;
39 perror("rump_sys_setegid");
40 return error;
41 }
42 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
43 error = errno;
44 perror("rump_sys_seteuid");
45 return error;
46 }
47 fd = rump_sys_open("test_fillup", O_CREAT | O_RDWR, 0644);
48 if (fd < 0) {
49 error = errno;
50 perror("rump_sys_open");
51 } else {
52 while (rump_sys_write(fd, buf, sizeof(buf)) == sizeof(buf))
53 error = 0;
54 error = errno;
55 }
56 rump_sys_close(fd);
57 rump_sys_seteuid(0);
58 rump_sys_setegid(0);
59 return error;
60 }
61
62 static int
63 quota_test1(void)
64 {
65 static char buf[512];
66 int fd;
67 int error;
68 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
69 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
70 error = errno;
71 perror("rump_sys_setegid");
72 return error;
73 }
74 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
75 error = errno;
76 perror("rump_sys_seteuid");
77 return error;
78 }
79 fd = rump_sys_open("test_fillup", O_CREAT | O_RDWR, 0644);
80 if (fd < 0) {
81 error = errno;
82 perror("rump_sys_open");
83 } else {
84 /*
85 * write up to the soft limit, wait a bit, an try to
86 * keep on writing
87 */
88 int i;
89
90 /* write 2k: with the directory this makes 2.5K */
91 for (i = 0; i < 4; i++) {
92 error = rump_sys_write(fd, buf, sizeof(buf));
93 if (error != sizeof(buf))
94 err(1, "write failed early");
95 }
96 sleep(2);
97 /* now try to write an extra .5k */
98 if (rump_sys_write(fd, buf, sizeof(buf)) != sizeof(buf))
99 error = errno;
100 else
101 error = 0;
102 }
103 rump_sys_close(fd);
104 rump_sys_seteuid(0);
105 rump_sys_setegid(0);
106 return error;
107 }
108
109 static int
110 quota_test2(void)
111 {
112 static char buf[512];
113 int fd;
114 int error;
115 int i;
116 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
117 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
118 error = errno;
119 perror("rump_sys_setegid");
120 return error;
121 }
122 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
123 error = errno;
124 perror("rump_sys_seteuid");
125 return error;
126 }
127
128 for (i = 0; ; i++) {
129 sprintf(buf, "file%d", i);
130 fd = rump_sys_open(buf, O_CREAT | O_RDWR, 0644);
131 if (fd < 0)
132 break;
133 sprintf(buf, "test file no %d", i);
134 rump_sys_write(fd, buf, strlen(buf));
135 rump_sys_close(fd);
136 }
137 error = errno;
138
139 rump_sys_close(fd);
140 rump_sys_seteuid(0);
141 rump_sys_setegid(0);
142 return error;
143 }
144
145 static int
146 quota_test3(void)
147 {
148 static char buf[512];
149 int fd;
150 int error;
151 int i;
152 rump_sys_chown(".", TEST_NONROOT_ID, TEST_NONROOT_ID);
153 if (rump_sys_setegid(TEST_NONROOT_ID) != 0) {
154 error = errno;
155 perror("rump_sys_setegid");
156 return error;
157 }
158 if (rump_sys_seteuid(TEST_NONROOT_ID) != 0) {
159 error = errno;
160 perror("rump_sys_seteuid");
161 return error;
162 }
163
164 /*
165 * create files one past the soft limit: one less as we already own the
166 * root directory
167 */
168 for (i = 0; i < 4; i++) {
169 sprintf(buf, "file%d", i);
170 fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644);
171 if (fd < 0)
172 err(1, "file create failed early");
173 sprintf(buf, "test file no %d", i);
174 rump_sys_write(fd, buf, strlen(buf));
175 rump_sys_close(fd);
176 }
177 /* now create an extra file after grace time: this should fail */
178 sleep(2);
179 sprintf(buf, "file%d", i);
180 fd = rump_sys_open(buf, O_EXCL| O_CREAT | O_RDWR, 0644);
181 if (fd < 0)
182 error = errno;
183 else
184 error = 0;
185
186 rump_sys_close(fd);
187 rump_sys_seteuid(0);
188 rump_sys_setegid(0);
189 return error;
190 }
191
192 struct quota_test {
193 int (*func)(void);
194 const char *desc;
195 };
196
197 struct quota_test quota_tests[] = {
198 { quota_test0, "write up to hard limit"},
199 { quota_test1, "write beyond the soft limit after grace time"},
200 { quota_test2, "create file up to hard limit"},
201 { quota_test3, "create file beyond the soft limit after grace time"},
202 };
203
204 static void
205 usage(void)
206 {
207 fprintf(stderr, "usage: %s [-b] [-l] test# diskimage bindurl\n",
208 getprogname());
209 exit(1);
210 }
211
212 static void
213 die(const char *reason, int error)
214 {
215
216 warnx("%s: %s", reason, strerror(error));
217 if (background)
218 rump_daemonize_done(error);
219 exit(1);
220 }
221
222 static sem_t sigsem;
223 static void
224 sigreboot(int sig)
225 {
226
227 sem_post(&sigsem);
228 }
229
230 int
231 main(int argc, char **argv)
232 {
233 int error;
234 u_long test;
235 char *end;
236 struct ufs_args uargs;
237 const char *filename;
238 const char *serverurl;
239 int log = 0;
240 int ch;
241
242 while ((ch = getopt(argc, argv, "bl")) != -1) {
243 switch(ch) {
244 case 'b':
245 background = 1;
246 break;
247 case 'l':
248 log = 1;
249 break;
250 default:
251 usage();
252 }
253 }
254 argc -= optind;
255 argv += optind;
256
257 if (argc != 3)
258 usage();
259
260 filename = argv[1];
261 serverurl = argv[2];
262
263 test = strtoul(argv[0], &end, 10);
264 if (*end != '\0') {
265 usage();
266 }
267 if (test > sizeof(quota_tests) / sizeof(quota_tests[0])) {
268 fprintf(stderr, "test number %lu too big\n", test);
269 exit(1);
270 }
271
272 if (background) {
273 error = rump_daemonize_begin();
274 if (error)
275 errx(1, "rump daemonize: %s", strerror(error));
276 }
277
278 error = rump_init();
279 if (error)
280 die("rump init failed", error);
281
282 if (rump_sys_mkdir(FSTEST_MNTNAME, 0777) == -1)
283 err(1, "mount point create");
284 rump_pub_etfs_register("/diskdev", filename, RUMP_ETFS_BLK);
285 uargs.fspec = __UNCONST("/diskdev");
286 if (rump_sys_mount(MOUNT_FFS, FSTEST_MNTNAME, (log) ? MNT_LOG : 0,
287 &uargs, sizeof(uargs)) == -1)
288 die("mount ffs", errno);
289
290 if (rump_sys_chdir(FSTEST_MNTNAME) == -1)
291 err(1, "cd %s", FSTEST_MNTNAME);
292 rump_sys_chown(".", 0, 0);
293 rump_sys_chmod(".", 0777);
294 error = quota_tests[test].func();
295 if (error) {
296 fprintf(stderr, " test %lu: %s returned %d: %s\n",
297 test, quota_tests[test].desc, error, strerror(error));
298 }
299 if (rump_sys_chdir("/") == -1)
300 err(1, "cd /");
301
302 error = rump_init_server(serverurl);
303 if (error)
304 die("rump server init failed", error);
305 if (background)
306 rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS);
307
308 sem_init(&sigsem, 0, 0);
309 signal(SIGTERM, sigreboot);
310 signal(SIGINT, sigreboot);
311 sem_wait(&sigsem);
312
313 rump_sys_reboot(0, NULL);
314 /*NOTREACHED*/
315 return 0;
316 }
317