Annotation of src/tests/fs/vfs/t_vnops.c, Revision 1.49
1.49 ! riastrad 1: /* $NetBSD: t_vnops.c,v 1.48 2015/04/09 05:32:53 riastradh Exp $ */
1.1 pooka 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:
1.13 pooka 32: #include <assert.h>
1.1 pooka 33: #include <atf-c.h>
34: #include <fcntl.h>
35: #include <libgen.h>
1.5 njoly 36: #include <stdlib.h>
1.13 pooka 37: #include <string.h>
1.1 pooka 38: #include <unistd.h>
39:
40: #include <rump/rump_syscalls.h>
41: #include <rump/rump.h>
42:
43: #include "../common/h_fsmacros.h"
44: #include "../../h_macros.h"
45:
1.11 pooka 46: #define TESTFILE "afile"
47:
1.29 njoly 48: #define USES_DIRS \
49: if (FSTYPE_SYSVBFS(tc)) \
50: atf_tc_skip("directories not supported by file system")
1.1 pooka 51:
1.7 pooka 52: #define USES_SYMLINKS \
53: if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc)) \
1.9 njoly 54: atf_tc_skip("symlinks not supported by file system")
1.7 pooka 55:
1.2 pooka 56: static char *
57: md(char *buf, const char *base, const char *tail)
58: {
59:
60: sprintf(buf, "%s/%s", base, tail);
61: return buf;
62: }
63:
1.1 pooka 64: static void
65: lookup_simple(const atf_tc_t *tc, const char *mountpath)
66: {
67: char pb[MAXPATHLEN], final[MAXPATHLEN];
68: struct stat sb1, sb2;
69:
70: strcpy(final, mountpath);
71: sprintf(pb, "%s/../%s", mountpath, basename(final));
72: if (rump_sys_stat(pb, &sb1) == -1)
73: atf_tc_fail_errno("stat 1");
74:
75: sprintf(pb, "%s/./../%s", mountpath, basename(final));
76: if (rump_sys_stat(pb, &sb2) == -1)
77: atf_tc_fail_errno("stat 2");
78:
79: ATF_REQUIRE(memcmp(&sb1, &sb2, sizeof(sb1)) == 0);
80: }
81:
82: static void
83: lookup_complex(const atf_tc_t *tc, const char *mountpath)
84: {
85: char pb[MAXPATHLEN];
86: struct stat sb1, sb2;
87:
88: USES_DIRS;
89:
1.41 gson 90: if (FSTYPE_UDF(tc))
91: atf_tc_expect_fail("PR kern/49033");
92:
1.1 pooka 93: sprintf(pb, "%s/dir", mountpath);
94: if (rump_sys_mkdir(pb, 0777) == -1)
95: atf_tc_fail_errno("mkdir");
96: if (rump_sys_stat(pb, &sb1) == -1)
97: atf_tc_fail_errno("stat 1");
98:
99: sprintf(pb, "%s/./dir/../././dir/.", mountpath);
100: if (rump_sys_stat(pb, &sb2) == -1)
101: atf_tc_fail_errno("stat 2");
102:
1.40 martin 103: if (memcmp(&sb1, &sb2, sizeof(sb1)) != 0) {
104: printf("what\tsb1\t\tsb2\n");
105:
106: #define FIELD(FN) \
107: printf(#FN "\t%lld\t%lld\n", \
108: (long long)sb1.FN, (long long)sb2.FN)
109: #define TIME(FN) \
110: printf(#FN "\t%lld.%ld\t%lld.%ld\n", \
111: (long long)sb1.FN.tv_sec, sb1.FN.tv_nsec, \
112: (long long)sb2.FN.tv_sec, sb2.FN.tv_nsec)
113:
114: FIELD(st_dev);
115: FIELD(st_mode);
116: FIELD(st_ino);
117: FIELD(st_nlink);
118: FIELD(st_uid);
119: FIELD(st_gid);
120: FIELD(st_rdev);
1.45 riastrad 121: TIME(st_atimespec);
122: TIME(st_mtimespec);
123: TIME(st_ctimespec);
124: TIME(st_birthtimespec);
1.40 martin 125: FIELD(st_size);
126: FIELD(st_blocks);
127: FIELD(st_flags);
128: FIELD(st_gen);
129:
130: #undef FIELD
131: #undef TIME
132:
133: atf_tc_fail("stat results differ, see ouput for more details");
134: }
1.41 gson 135: if (FSTYPE_UDF(tc))
136: atf_tc_fail("random failure of PR kern/49033 "
137: "did not happen this time");
1.1 pooka 138: }
139:
140: static void
141: dir_simple(const atf_tc_t *tc, const char *mountpath)
142: {
143: char pb[MAXPATHLEN];
144: struct stat sb;
145:
146: USES_DIRS;
147:
148: /* check we can create directories */
149: sprintf(pb, "%s/dir", mountpath);
150: if (rump_sys_mkdir(pb, 0777) == -1)
151: atf_tc_fail_errno("mkdir");
152: if (rump_sys_stat(pb, &sb) == -1)
153: atf_tc_fail_errno("stat new directory");
154:
155: /* check we can remove then and that it makes them unreachable */
156: if (rump_sys_rmdir(pb) == -1)
157: atf_tc_fail_errno("rmdir");
158: if (rump_sys_stat(pb, &sb) != -1 || errno != ENOENT)
159: atf_tc_fail("ENOENT expected from stat");
160: }
161:
162: static void
163: dir_notempty(const atf_tc_t *tc, const char *mountpath)
164: {
165: char pb[MAXPATHLEN], pb2[MAXPATHLEN];
166: int fd, rv;
167:
168: USES_DIRS;
169:
170: /* check we can create directories */
171: sprintf(pb, "%s/dir", mountpath);
172: if (rump_sys_mkdir(pb, 0777) == -1)
173: atf_tc_fail_errno("mkdir");
174:
175: sprintf(pb2, "%s/dir/file", mountpath);
176: fd = rump_sys_open(pb2, O_RDWR | O_CREAT, 0777);
177: if (fd == -1)
178: atf_tc_fail_errno("create file");
179: rump_sys_close(fd);
180:
181: rv = rump_sys_rmdir(pb);
182: if (rv != -1 || errno != ENOTEMPTY)
183: atf_tc_fail("non-empty directory removed succesfully");
184:
185: if (rump_sys_unlink(pb2) == -1)
186: atf_tc_fail_errno("cannot remove dir/file");
187:
188: if (rump_sys_rmdir(pb) == -1)
189: atf_tc_fail_errno("remove directory");
190: }
191:
1.2 pooka 192: static void
1.18 pooka 193: dir_rmdirdotdot(const atf_tc_t *tc, const char *mp)
194: {
195: char pb[MAXPATHLEN];
196: int xerrno;
197:
198: USES_DIRS;
199:
200: FSTEST_ENTER();
201: RL(rump_sys_mkdir("test", 0777));
202: RL(rump_sys_chdir("test"));
203:
204: RL(rump_sys_mkdir("subtest", 0777));
205: RL(rump_sys_chdir("subtest"));
206:
207: md(pb, mp, "test/subtest");
208: RL(rump_sys_rmdir(pb));
209: md(pb, mp, "test");
210: RL(rump_sys_rmdir(pb));
211:
212: if (FSTYPE_NFS(tc))
213: xerrno = ESTALE;
214: else
215: xerrno = ENOENT;
216: ATF_REQUIRE_ERRNO(xerrno, rump_sys_chdir("..") == -1);
217: FSTEST_EXIT();
218: }
219:
220: static void
1.2 pooka 221: checkfile(const char *path, struct stat *refp)
222: {
223: char buf[MAXPATHLEN];
224: struct stat sb;
225: static int n = 1;
226:
227: md(buf, path, "file");
228: if (rump_sys_stat(buf, &sb) == -1)
229: atf_tc_fail_errno("cannot stat file %d (%s)", n, buf);
230: if (memcmp(&sb, refp, sizeof(sb)) != 0)
231: atf_tc_fail("stat mismatch %d", n);
232: n++;
233: }
234:
235: static void
236: rename_dir(const atf_tc_t *tc, const char *mp)
237: {
238: char pb1[MAXPATHLEN], pb2[MAXPATHLEN], pb3[MAXPATHLEN];
1.16 pooka 239: struct stat ref, sb;
1.2 pooka 240:
1.10 pooka 241: if (FSTYPE_RUMPFS(tc))
1.29 njoly 242: atf_tc_skip("rename not supported by file system");
1.10 pooka 243:
1.2 pooka 244: USES_DIRS;
245:
246: md(pb1, mp, "dir1");
247: if (rump_sys_mkdir(pb1, 0777) == -1)
248: atf_tc_fail_errno("mkdir 1");
249:
250: md(pb2, mp, "dir2");
251: if (rump_sys_mkdir(pb2, 0777) == -1)
252: atf_tc_fail_errno("mkdir 2");
253: md(pb2, mp, "dir2/subdir");
254: if (rump_sys_mkdir(pb2, 0777) == -1)
255: atf_tc_fail_errno("mkdir 3");
256:
257: md(pb3, mp, "dir1/file");
258: if (rump_sys_mknod(pb3, S_IFREG | 0777, -1) == -1)
259: atf_tc_fail_errno("create file");
260: if (rump_sys_stat(pb3, &ref) == -1)
261: atf_tc_fail_errno("stat of file");
262:
263: /*
264: * First try ops which should succeed.
265: */
266:
267: /* rename within directory */
268: md(pb3, mp, "dir3");
269: if (rump_sys_rename(pb1, pb3) == -1)
270: atf_tc_fail_errno("rename 1");
271: checkfile(pb3, &ref);
272:
273: /* rename directory onto itself (two ways, should fail) */
274: md(pb1, mp, "dir3/.");
275: if (rump_sys_rename(pb1, pb3) != -1 || errno != EINVAL)
276: atf_tc_fail_errno("rename 2");
277: if (rump_sys_rename(pb3, pb1) != -1 || errno != EISDIR)
278: atf_tc_fail_errno("rename 3");
279:
280: checkfile(pb3, &ref);
281:
282: /* rename father of directory into directory */
283: md(pb1, mp, "dir2/dir");
284: md(pb2, mp, "dir2");
285: if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
286: atf_tc_fail_errno("rename 4");
287:
288: /* same for grandfather */
289: md(pb1, mp, "dir2/subdir/dir2");
290: if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
291: atf_tc_fail("rename 5");
292:
293: checkfile(pb3, &ref);
294:
295: /* rename directory over a non-empty directory */
296: if (rump_sys_rename(pb2, pb3) != -1 || errno != ENOTEMPTY)
297: atf_tc_fail("rename 6");
298:
299: /* cross-directory rename */
300: md(pb1, mp, "dir3");
301: md(pb2, mp, "dir2/somedir");
302: if (rump_sys_rename(pb1, pb2) == -1)
303: atf_tc_fail_errno("rename 7");
304: checkfile(pb2, &ref);
305:
306: /* move to parent directory */
307: md(pb1, mp, "dir2/somedir/../../dir3");
308: if (rump_sys_rename(pb2, pb1) == -1)
309: atf_tc_fail_errno("rename 8");
310: md(pb1, mp, "dir2/../dir3");
311: checkfile(pb1, &ref);
312:
1.16 pooka 313: /* atomic cross-directory rename */
1.2 pooka 314: md(pb3, mp, "dir2/subdir");
315: if (rump_sys_rename(pb1, pb3) == -1)
316: atf_tc_fail_errno("rename 9");
317: checkfile(pb3, &ref);
1.16 pooka 318:
319: /* rename directory over an empty directory */
320: md(pb1, mp, "parent");
321: md(pb2, mp, "parent/dir1");
322: md(pb3, mp, "parent/dir2");
323: RL(rump_sys_mkdir(pb1, 0777));
324: RL(rump_sys_mkdir(pb2, 0777));
325: RL(rump_sys_mkdir(pb3, 0777));
326: RL(rump_sys_rename(pb2, pb3));
327:
328: RL(rump_sys_stat(pb1, &sb));
1.22 hannken 329: if (! FSTYPE_MSDOS(tc))
330: ATF_CHECK_EQ(sb.st_nlink, 3);
1.16 pooka 331: RL(rump_sys_rmdir(pb3));
332: RL(rump_sys_rmdir(pb1));
1.2 pooka 333: }
334:
335: static void
336: rename_dotdot(const atf_tc_t *tc, const char *mp)
337: {
338:
1.10 pooka 339: if (FSTYPE_RUMPFS(tc))
1.29 njoly 340: atf_tc_skip("rename not supported by file system");
1.10 pooka 341:
1.2 pooka 342: USES_DIRS;
343:
344: if (rump_sys_chdir(mp) == -1)
345: atf_tc_fail_errno("chdir mountpoint");
346:
347: if (rump_sys_mkdir("dir1", 0777) == -1)
348: atf_tc_fail_errno("mkdir 1");
349: if (rump_sys_mkdir("dir2", 0777) == -1)
350: atf_tc_fail_errno("mkdir 2");
351:
352: if (rump_sys_rename("dir1", "dir1/..") != -1 || errno != EINVAL)
353: atf_tc_fail_errno("self-dotdot to");
354:
355: if (rump_sys_rename("dir1/..", "sometarget") != -1 || errno != EINVAL)
356: atf_tc_fail_errno("self-dotdot from");
357:
358: if (rump_sys_rename("dir1", "dir2/..") != -1 || errno != EINVAL)
359: atf_tc_fail("other-dotdot");
360:
361: rump_sys_chdir("/");
362: }
363:
364: static void
365: rename_reg_nodir(const atf_tc_t *tc, const char *mp)
366: {
367: bool haslinks;
368: struct stat sb;
1.38 christos 369: ino_t f1ino;
1.2 pooka 370:
1.10 pooka 371: if (FSTYPE_RUMPFS(tc))
1.29 njoly 372: atf_tc_skip("rename not supported by file system");
1.10 pooka 373:
1.2 pooka 374: if (rump_sys_chdir(mp) == -1)
375: atf_tc_fail_errno("chdir mountpoint");
376:
377: if (FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))
378: haslinks = false;
379: else
380: haslinks = true;
381:
382: if (rump_sys_mknod("file1", S_IFREG | 0777, -1) == -1)
383: atf_tc_fail_errno("create file");
384: if (rump_sys_mknod("file2", S_IFREG | 0777, -1) == -1)
385: atf_tc_fail_errno("create file");
386:
387: if (rump_sys_stat("file1", &sb) == -1)
388: atf_tc_fail_errno("stat");
389: f1ino = sb.st_ino;
390:
391: if (haslinks) {
392: if (rump_sys_link("file1", "file_link") == -1)
393: atf_tc_fail_errno("link");
394: if (rump_sys_stat("file_link", &sb) == -1)
395: atf_tc_fail_errno("stat");
396: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
397: ATF_REQUIRE_EQ(sb.st_nlink, 2);
398: }
399:
400: if (rump_sys_stat("file2", &sb) == -1)
401: atf_tc_fail_errno("stat");
402:
403: if (rump_sys_rename("file1", "file3") == -1)
404: atf_tc_fail_errno("rename 1");
405: if (rump_sys_stat("file3", &sb) == -1)
406: atf_tc_fail_errno("stat 1");
407: if (haslinks) {
408: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
409: }
410: if (rump_sys_stat("file1", &sb) != -1 || errno != ENOENT)
411: atf_tc_fail_errno("source 1");
412:
413: if (rump_sys_rename("file3", "file2") == -1)
414: atf_tc_fail_errno("rename 2");
415: if (rump_sys_stat("file2", &sb) == -1)
416: atf_tc_fail_errno("stat 2");
417: if (haslinks) {
418: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
419: }
420:
421: if (rump_sys_stat("file3", &sb) != -1 || errno != ENOENT)
422: atf_tc_fail_errno("source 2");
423:
424: if (haslinks) {
425: if (rump_sys_rename("file2", "file_link") == -1)
426: atf_tc_fail_errno("rename hardlink");
427: if (rump_sys_stat("file2", &sb) != -1 || errno != ENOENT)
428: atf_tc_fail_errno("source 3");
429: if (rump_sys_stat("file_link", &sb) == -1)
430: atf_tc_fail_errno("stat 2");
431: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
432: ATF_REQUIRE_EQ(sb.st_nlink, 1);
433: }
434:
1.37 njoly 435: ATF_CHECK_ERRNO(EFAULT, rump_sys_rename("file2", NULL) == -1);
436: ATF_CHECK_ERRNO(EFAULT, rump_sys_rename(NULL, "file2") == -1);
437:
1.2 pooka 438: rump_sys_chdir("/");
439: }
440:
1.5 njoly 441: static void
442: create_nametoolong(const atf_tc_t *tc, const char *mp)
443: {
444: char *name;
445: int fd;
446: long val;
447: size_t len;
448:
449: if (rump_sys_chdir(mp) == -1)
450: atf_tc_fail_errno("chdir mountpoint");
451:
452: val = rump_sys_pathconf(".", _PC_NAME_MAX);
453: if (val == -1)
454: atf_tc_fail_errno("pathconf");
455:
456: len = val + 1;
457: name = malloc(len+1);
458: if (name == NULL)
459: atf_tc_fail_errno("malloc");
460:
461: memset(name, 'a', len);
462: *(name+len) = '\0';
463:
464: val = rump_sys_pathconf(".", _PC_NO_TRUNC);
465: if (val == -1)
466: atf_tc_fail_errno("pathconf");
467:
468: fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666);
469: if (val != 0 && (fd != -1 || errno != ENAMETOOLONG))
470: atf_tc_fail_errno("open");
471:
472: if (val == 0 && rump_sys_close(fd) == -1)
473: atf_tc_fail_errno("close");
474: if (val == 0 && rump_sys_unlink(name) == -1)
475: atf_tc_fail_errno("unlink");
476:
477: free(name);
478:
479: rump_sys_chdir("/");
480: }
481:
482: static void
1.14 yamt 483: create_exist(const atf_tc_t *tc, const char *mp)
484: {
485: const char *name = "hoge";
486: int fd;
487:
488: RL(rump_sys_chdir(mp));
489: RL(fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666));
490: RL(rump_sys_close(fd));
491: RL(rump_sys_unlink(name));
492: RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
493: RL(rump_sys_close(fd));
494: RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
495: RL(rump_sys_close(fd));
496: ATF_REQUIRE_ERRNO(EEXIST,
497: (fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666)));
498: RL(rump_sys_unlink(name));
499: RL(rump_sys_chdir("/"));
500: }
501:
502: static void
1.5 njoly 503: rename_nametoolong(const atf_tc_t *tc, const char *mp)
504: {
505: char *name;
506: int res, fd;
507: long val;
508: size_t len;
509:
1.10 pooka 510: if (FSTYPE_RUMPFS(tc))
1.29 njoly 511: atf_tc_skip("rename not supported by file system");
1.10 pooka 512:
1.5 njoly 513: if (rump_sys_chdir(mp) == -1)
514: atf_tc_fail_errno("chdir mountpoint");
515:
516: val = rump_sys_pathconf(".", _PC_NAME_MAX);
517: if (val == -1)
518: atf_tc_fail_errno("pathconf");
519:
520: len = val + 1;
521: name = malloc(len+1);
522: if (name == NULL)
523: atf_tc_fail_errno("malloc");
524:
525: memset(name, 'a', len);
526: *(name+len) = '\0';
527:
528: fd = rump_sys_open("dummy", O_RDWR|O_CREAT, 0666);
529: if (fd == -1)
530: atf_tc_fail_errno("open");
531: if (rump_sys_close(fd) == -1)
532: atf_tc_fail_errno("close");
533:
534: val = rump_sys_pathconf(".", _PC_NO_TRUNC);
535: if (val == -1)
536: atf_tc_fail_errno("pathconf");
537:
538: res = rump_sys_rename("dummy", name);
539: if (val != 0 && (res != -1 || errno != ENAMETOOLONG))
540: atf_tc_fail_errno("rename");
541:
542: if (val == 0 && rump_sys_unlink(name) == -1)
543: atf_tc_fail_errno("unlink");
544:
545: free(name);
546:
547: rump_sys_chdir("/");
548: }
549:
1.42 gson 550: /*
551: * Test creating a symlink whose length is "len" bytes, not including
552: * the terminating NUL.
553: */
1.7 pooka 554: static void
1.42 gson 555: symlink_len(const atf_tc_t *tc, const char *mp, size_t len)
1.7 pooka 556: {
1.42 gson 557: char *buf;
558: int r;
1.7 pooka 559:
560: USES_SYMLINKS;
561:
562: RL(rump_sys_chdir(mp));
1.8 pooka 563:
1.42 gson 564: buf = malloc(len + 1);
565: ATF_REQUIRE(buf);
566: memset(buf, 'a', len);
567: buf[len] = '\0';
568: r = rump_sys_symlink(buf, "afile");
569: if (r == -1) {
570: ATF_REQUIRE_ERRNO(ENAMETOOLONG, r);
571: } else {
572: RL(rump_sys_unlink("afile"));
573: }
574: free(buf);
575:
1.7 pooka 576: RL(rump_sys_chdir("/"));
577: }
578:
1.11 pooka 579: static void
1.42 gson 580: symlink_zerolen(const atf_tc_t *tc, const char *mp)
581: {
582: symlink_len(tc, mp, 0);
583: }
584:
585: static void
586: symlink_long(const atf_tc_t *tc, const char *mp)
587: {
588: /*
589: * Test lengths close to powers of two, as those are likely
590: * to be edge cases.
591: */
592: size_t len;
593: int fuzz;
594: for (len = 2; len <= 65536; len *= 2) {
595: for (fuzz = -1; fuzz <= 1; fuzz++) {
596: symlink_len(tc, mp, len + fuzz);
597: }
598: }
599: }
600:
601: static void
1.28 riastrad 602: symlink_root(const atf_tc_t *tc, const char *mp)
603: {
604:
605: USES_SYMLINKS;
606:
607: RL(rump_sys_chdir(mp));
608: RL(rump_sys_symlink("/", "foo"));
609: RL(rump_sys_chdir("foo"));
610: }
611:
612: static void
1.11 pooka 613: attrs(const atf_tc_t *tc, const char *mp)
614: {
615: struct stat sb, sb2;
616: struct timeval tv[2];
617: int fd;
618:
619: FSTEST_ENTER();
620: RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
621: RL(rump_sys_close(fd));
622: RL(rump_sys_stat(TESTFILE, &sb));
623: if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
624: RL(rump_sys_chown(TESTFILE, 1, 2));
625: sb.st_uid = 1;
626: sb.st_gid = 2;
627: RL(rump_sys_chmod(TESTFILE, 0123));
628: sb.st_mode = (sb.st_mode & ~ACCESSPERMS) | 0123;
629: }
630:
631: tv[0].tv_sec = 1000000000; /* need something >1980 for msdosfs */
632: tv[0].tv_usec = 1;
633: tv[1].tv_sec = 1000000002; /* need even seconds for msdosfs */
634: tv[1].tv_usec = 3;
635: RL(rump_sys_utimes(TESTFILE, tv));
636: RL(rump_sys_utimes(TESTFILE, tv)); /* XXX: utimes & birthtime */
637: sb.st_atimespec.tv_sec = 1000000000;
638: sb.st_atimespec.tv_nsec = 1000;
639: sb.st_mtimespec.tv_sec = 1000000002;
640: sb.st_mtimespec.tv_nsec = 3000;
641:
642: RL(rump_sys_stat(TESTFILE, &sb2));
643: #define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a)
644: if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
645: CHECK(st_uid);
646: CHECK(st_gid);
647: CHECK(st_mode);
648: }
649: if (!FSTYPE_MSDOS(tc)) {
650: /* msdosfs has only access date, not time */
651: CHECK(st_atimespec.tv_sec);
652: }
653: CHECK(st_mtimespec.tv_sec);
1.27 uch 654: if (!(FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc) ||
655: FSTYPE_SYSVBFS(tc) || FSTYPE_V7FS(tc))) {
1.11 pooka 656: CHECK(st_atimespec.tv_nsec);
657: CHECK(st_mtimespec.tv_nsec);
658: }
659: #undef CHECK
660:
661: FSTEST_EXIT();
662: }
663:
1.12 kefren 664: static void
665: fcntl_lock(const atf_tc_t *tc, const char *mp)
666: {
667: int fd, fd2;
668: struct flock l;
669: struct lwp *lwp1, *lwp2;
670:
671: FSTEST_ENTER();
672: l.l_pid = 0;
673: l.l_start = l.l_len = 1024;
674: l.l_type = F_RDLCK | F_WRLCK;
675: l.l_whence = SEEK_END;
676:
677: lwp1 = rump_pub_lwproc_curlwp();
678: RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
679: RL(rump_sys_ftruncate(fd, 8192));
680:
681: RL(rump_sys_fcntl(fd, F_SETLK, &l));
682:
683: /* Next, we fork and try to lock the same area */
684: RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
685: lwp2 = rump_pub_lwproc_curlwp();
686: RL(fd2 = rump_sys_open(TESTFILE, O_RDWR, 0));
687: ATF_REQUIRE_ERRNO(EAGAIN, rump_sys_fcntl(fd2, F_SETLK, &l));
688:
689: /* Switch back and unlock... */
690: rump_pub_lwproc_switch(lwp1);
691: l.l_type = F_UNLCK;
692: RL(rump_sys_fcntl(fd, F_SETLK, &l));
693:
694: /* ... and try to lock again */
695: rump_pub_lwproc_switch(lwp2);
696: l.l_type = F_RDLCK | F_WRLCK;
697: RL(rump_sys_fcntl(fd2, F_SETLK, &l));
698:
699: RL(rump_sys_close(fd2));
700: rump_pub_lwproc_releaselwp();
701:
702: RL(rump_sys_close(fd));
703:
704: FSTEST_EXIT();
705: }
706:
1.13 pooka 707: static int
708: flock_compare(const void *p, const void *q)
709: {
710: int a = ((const struct flock *)p)->l_start;
711: int b = ((const struct flock *)q)->l_start;
712: return a < b ? -1 : (a > b ? 1 : 0);
713: }
714:
1.26 alnsn 715: /*
716: * Find all locks set by fcntl_getlock_pids test
717: * using GETLK for a range [start, start+end], and,
718: * if there is a blocking lock, recursively find
719: * all locks to the left (toward the beginning of
720: * a file) and to the right of the lock.
721: * The function also understands "until end of file"
722: * convention when len==0.
723: */
724: static unsigned int
725: fcntl_getlocks(int fildes, off_t start, off_t len,
726: struct flock *lock, struct flock *end)
727: {
728: unsigned int rv = 0;
729: const struct flock l = { start, len, 0, F_RDLCK, SEEK_SET };
730:
731: if (lock == end)
732: return rv;
733:
734: RL(rump_sys_fcntl(fildes, F_GETLK, &l));
735:
736: if (l.l_type == F_UNLCK)
737: return rv;
738:
739: *lock++ = l;
740: rv += 1;
741:
742: ATF_REQUIRE(l.l_whence == SEEK_SET);
743:
744: if (l.l_start > start) {
745: unsigned int n =
746: fcntl_getlocks(fildes, start, l.l_start - start, lock, end);
747: rv += n;
748: lock += n;
749: if (lock == end)
750: return rv;
751: }
752:
753: if (l.l_len == 0) /* does l spans until the end? */
754: return rv;
755:
756: if (len == 0) /* are we looking for locks until the end? */ {
757: rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end);
758: } else if (l.l_start + l.l_len < start + len) {
759: len -= l.l_start + l.l_len - start;
760: rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end);
761: }
762:
763: return rv;
764: }
765:
1.13 pooka 766: static void
767: fcntl_getlock_pids(const atf_tc_t *tc, const char *mp)
768: {
769: /* test non-overlaping ranges */
770: struct flock expect[4];
771: const struct flock lock[4] = {
772: { 0, 2, 0, F_WRLCK, SEEK_SET },
773: { 2, 1, 0, F_WRLCK, SEEK_SET },
774: { 7, 5, 0, F_WRLCK, SEEK_SET },
775: { 4, 3, 0, F_WRLCK, SEEK_SET },
776: };
777:
1.26 alnsn 778: /* Add extra element to make sure recursion does't stop at array end */
779: struct flock result[5];
780:
781: /* Add 5th process */
782: int fd[5];
783: pid_t pid[5];
784: struct lwp *lwp[5];
1.13 pooka 785:
786: unsigned int i, j;
787: const off_t sz = 8192;
788: int omode = 0755;
789: int oflags = O_RDWR | O_CREAT;
790:
791: memcpy(expect, lock, sizeof(lock));
792:
793: FSTEST_ENTER();
794:
795: /*
796: * First, we create 4 processes and let each lock a range of the
797: * file. Note that the third and fourth processes lock in
798: * "reverse" order, i.e. the greater pid locks a range before
799: * the lesser pid.
1.26 alnsn 800: * Then, we create 5th process which doesn't lock anything.
1.13 pooka 801: */
1.26 alnsn 802: for (i = 0; i < __arraycount(lwp); i++) {
1.13 pooka 803: RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
804:
805: lwp[i] = rump_pub_lwproc_curlwp();
1.26 alnsn 806: pid[i] = rump_sys_getpid();
1.13 pooka 807:
808: RL(fd[i] = rump_sys_open(TESTFILE, oflags, omode));
809: oflags = O_RDWR;
810: omode = 0;
811:
812: RL(rump_sys_ftruncate(fd[i], sz));
1.26 alnsn 813:
814: if (i < __arraycount(lock)) {
815: RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i]));
816: expect[i].l_pid = pid[i];
817: }
1.13 pooka 818: }
819:
1.26 alnsn 820: qsort(expect, __arraycount(expect), sizeof(expect[0]), &flock_compare);
821:
1.13 pooka 822: /*
1.26 alnsn 823: * In the context of each process, recursively find all locks
824: * that would block the current process. Processes 1-4 don't
825: * see their own lock, we insert it to simplify checks.
826: * Process 5 sees all 4 locks.
1.13 pooka 827: */
1.26 alnsn 828: for (i = 0; i < __arraycount(lwp); i++) {
829: unsigned int nlocks;
830:
1.13 pooka 831: rump_pub_lwproc_switch(lwp[i]);
832:
1.26 alnsn 833: memset(result, 0, sizeof(result));
834: nlocks = fcntl_getlocks(fd[i], 0, sz,
835: result, result + __arraycount(result));
836:
837: if (i < __arraycount(lock)) {
838: ATF_REQUIRE(nlocks < __arraycount(result));
839: result[nlocks] = lock[i];
840: result[nlocks].l_pid = pid[i];
841: nlocks++;
842: }
843:
844: ATF_CHECK_EQ(nlocks, __arraycount(expect));
845:
846: qsort(result, nlocks, sizeof(result[0]), &flock_compare);
847:
848: for (j = 0; j < nlocks; j++) {
849: ATF_CHECK_EQ(result[j].l_start, expect[j].l_start );
850: ATF_CHECK_EQ(result[j].l_len, expect[j].l_len );
851: ATF_CHECK_EQ(result[j].l_pid, expect[j].l_pid );
852: ATF_CHECK_EQ(result[j].l_type, expect[j].l_type );
853: ATF_CHECK_EQ(result[j].l_whence, expect[j].l_whence);
1.13 pooka 854: }
855: }
856:
857: /*
858: * Release processes. This also releases the fds and locks
859: * making fs unmount possible
860: */
1.26 alnsn 861: for (i = 0; i < __arraycount(lwp); i++) {
1.13 pooka 862: rump_pub_lwproc_switch(lwp[i]);
863: rump_pub_lwproc_releaselwp();
864: }
865:
866: FSTEST_EXIT();
867: }
868:
1.15 pooka 869: static void
870: access_simple(const atf_tc_t *tc, const char *mp)
871: {
872: int fd;
873: int tmode;
874:
875: FSTEST_ENTER();
876: RL(fd = rump_sys_open("tfile", O_CREAT | O_RDWR, 0777));
877: RL(rump_sys_close(fd));
878:
879: #define ALLACC (F_OK | X_OK | W_OK | R_OK)
880: if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc))
881: tmode = F_OK;
882: else
883: tmode = ALLACC;
884:
885: RL(rump_sys_access("tfile", tmode));
886:
887: /* PR kern/44648 */
888: ATF_REQUIRE_ERRNO(EINVAL, rump_sys_access("tfile", ALLACC+1) == -1);
889: #undef ALLACC
890: FSTEST_EXIT();
891: }
892:
1.30 njoly 893: static void
894: read_directory(const atf_tc_t *tc, const char *mp)
895: {
896: char buf[1024];
897: int fd, res;
898: ssize_t size;
899:
900: FSTEST_ENTER();
901: fd = rump_sys_open(".", O_DIRECTORY | O_RDONLY, 0777);
902: ATF_REQUIRE(fd != -1);
903:
904: size = rump_sys_pread(fd, buf, sizeof(buf), 0);
905: ATF_CHECK(size != -1 || errno == EISDIR);
906: size = rump_sys_read(fd, buf, sizeof(buf));
907: ATF_CHECK(size != -1 || errno == EISDIR);
908:
909: res = rump_sys_close(fd);
910: ATF_REQUIRE(res != -1);
911: FSTEST_EXIT();
912: }
913:
1.39 njoly 914: static void
915: lstat_symlink(const atf_tc_t *tc, const char *mp)
916: {
917: const char *src, *dst;
918: int res;
919: struct stat st;
920:
921: USES_SYMLINKS;
1.43 gson 922:
1.39 njoly 923: FSTEST_ENTER();
924:
925: src = "source";
926: dst = "destination";
927:
928: res = rump_sys_symlink(src, dst);
929: ATF_REQUIRE(res != -1);
930: res = rump_sys_lstat(dst, &st);
931: ATF_REQUIRE(res != -1);
932:
933: ATF_CHECK(S_ISLNK(st.st_mode) != 0);
934: ATF_CHECK(st.st_size == (off_t)strlen(src));
935:
936: FSTEST_EXIT();
937: }
938:
1.1 pooka 939: ATF_TC_FSAPPLY(lookup_simple, "simple lookup (./.. on root)");
940: ATF_TC_FSAPPLY(lookup_complex, "lookup of non-dot entries");
941: ATF_TC_FSAPPLY(dir_simple, "mkdir/rmdir");
942: ATF_TC_FSAPPLY(dir_notempty, "non-empty directories cannot be removed");
1.31 christos 943: ATF_TC_FSAPPLY(dir_rmdirdotdot, "remove .. and try to cd out (PR kern/44657)");
944: ATF_TC_FSAPPLY(rename_dir, "exercise various directory renaming ops "
945: "(PR kern/44288)");
946: ATF_TC_FSAPPLY(rename_dotdot, "rename dir .. (PR kern/43617)");
1.2 pooka 947: ATF_TC_FSAPPLY(rename_reg_nodir, "rename regular files, no subdirectories");
1.5 njoly 948: ATF_TC_FSAPPLY(create_nametoolong, "create file with name too long");
1.14 yamt 949: ATF_TC_FSAPPLY(create_exist, "create with O_EXCL");
1.5 njoly 950: ATF_TC_FSAPPLY(rename_nametoolong, "rename to file with name too long");
1.42 gson 951: ATF_TC_FSAPPLY(symlink_zerolen, "symlink with target of length 0");
952: ATF_TC_FSAPPLY(symlink_long, "symlink with target of length > 0");
1.28 riastrad 953: ATF_TC_FSAPPLY(symlink_root, "symlink to root directory");
1.11 pooka 954: ATF_TC_FSAPPLY(attrs, "check setting attributes works");
1.12 kefren 955: ATF_TC_FSAPPLY(fcntl_lock, "check fcntl F_SETLK");
1.13 pooka 956: ATF_TC_FSAPPLY(fcntl_getlock_pids,"fcntl F_GETLK w/ many procs, PR kern/44494");
1.15 pooka 957: ATF_TC_FSAPPLY(access_simple, "access(2)");
1.30 njoly 958: ATF_TC_FSAPPLY(read_directory, "read(2) on directories");
1.39 njoly 959: ATF_TC_FSAPPLY(lstat_symlink, "lstat(2) values for symbolic links");
1.1 pooka 960:
961: ATF_TP_ADD_TCS(tp)
962: {
963:
964: ATF_TP_FSAPPLY(lookup_simple);
965: ATF_TP_FSAPPLY(lookup_complex);
966: ATF_TP_FSAPPLY(dir_simple);
967: ATF_TP_FSAPPLY(dir_notempty);
1.18 pooka 968: ATF_TP_FSAPPLY(dir_rmdirdotdot);
1.2 pooka 969: ATF_TP_FSAPPLY(rename_dir);
970: ATF_TP_FSAPPLY(rename_dotdot);
971: ATF_TP_FSAPPLY(rename_reg_nodir);
1.5 njoly 972: ATF_TP_FSAPPLY(create_nametoolong);
1.14 yamt 973: ATF_TP_FSAPPLY(create_exist);
1.5 njoly 974: ATF_TP_FSAPPLY(rename_nametoolong);
1.7 pooka 975: ATF_TP_FSAPPLY(symlink_zerolen);
1.42 gson 976: ATF_TP_FSAPPLY(symlink_long);
1.28 riastrad 977: ATF_TP_FSAPPLY(symlink_root);
1.11 pooka 978: ATF_TP_FSAPPLY(attrs);
1.12 kefren 979: ATF_TP_FSAPPLY(fcntl_lock);
1.13 pooka 980: ATF_TP_FSAPPLY(fcntl_getlock_pids);
1.15 pooka 981: ATF_TP_FSAPPLY(access_simple);
1.30 njoly 982: ATF_TP_FSAPPLY(read_directory);
1.39 njoly 983: ATF_TP_FSAPPLY(lstat_symlink);
1.1 pooka 984:
985: return atf_no_error();
986: }
CVSweb <webmaster@jp.NetBSD.org>