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