Annotation of src/tests/fs/vfs/t_vnops.c, Revision 1.20
1.20 ! pooka 1: /* $NetBSD: t_vnops.c,v 1.19 2011/03/01 15:33:35 pooka 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.1 pooka 48: #define USES_DIRS \
49: if (FSTYPE_SYSVBFS(tc)) atf_tc_skip("dirs not supported by file system")
50:
1.7 pooka 51: #define USES_SYMLINKS \
52: if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc)) \
1.9 njoly 53: atf_tc_skip("symlinks not supported by file system")
1.7 pooka 54:
1.2 pooka 55: static char *
56: md(char *buf, const char *base, const char *tail)
57: {
58:
59: sprintf(buf, "%s/%s", base, tail);
60: return buf;
61: }
62:
1.1 pooka 63: static void
64: lookup_simple(const atf_tc_t *tc, const char *mountpath)
65: {
66: char pb[MAXPATHLEN], final[MAXPATHLEN];
67: struct stat sb1, sb2;
68:
69: strcpy(final, mountpath);
70: sprintf(pb, "%s/../%s", mountpath, basename(final));
71: if (rump_sys_stat(pb, &sb1) == -1)
72: atf_tc_fail_errno("stat 1");
73:
74: sprintf(pb, "%s/./../%s", mountpath, basename(final));
75: if (rump_sys_stat(pb, &sb2) == -1)
76: atf_tc_fail_errno("stat 2");
77:
78: ATF_REQUIRE(memcmp(&sb1, &sb2, sizeof(sb1)) == 0);
79: }
80:
81: static void
82: lookup_complex(const atf_tc_t *tc, const char *mountpath)
83: {
84: char pb[MAXPATHLEN];
85: struct stat sb1, sb2;
86:
87: USES_DIRS;
88:
89: sprintf(pb, "%s/dir", mountpath);
90: if (rump_sys_mkdir(pb, 0777) == -1)
91: atf_tc_fail_errno("mkdir");
92: if (rump_sys_stat(pb, &sb1) == -1)
93: atf_tc_fail_errno("stat 1");
94:
95: sprintf(pb, "%s/./dir/../././dir/.", mountpath);
96: if (rump_sys_stat(pb, &sb2) == -1)
97: atf_tc_fail_errno("stat 2");
98:
99: ATF_REQUIRE(memcmp(&sb1, &sb2, sizeof(sb1)) == 0);
100: }
101:
102: static void
103: dir_simple(const atf_tc_t *tc, const char *mountpath)
104: {
105: char pb[MAXPATHLEN];
106: struct stat sb;
107:
108: USES_DIRS;
109:
110: /* check we can create directories */
111: sprintf(pb, "%s/dir", mountpath);
112: if (rump_sys_mkdir(pb, 0777) == -1)
113: atf_tc_fail_errno("mkdir");
114: if (rump_sys_stat(pb, &sb) == -1)
115: atf_tc_fail_errno("stat new directory");
116:
117: /* check we can remove then and that it makes them unreachable */
118: if (rump_sys_rmdir(pb) == -1)
119: atf_tc_fail_errno("rmdir");
120: if (rump_sys_stat(pb, &sb) != -1 || errno != ENOENT)
121: atf_tc_fail("ENOENT expected from stat");
122: }
123:
124: static void
125: dir_notempty(const atf_tc_t *tc, const char *mountpath)
126: {
127: char pb[MAXPATHLEN], pb2[MAXPATHLEN];
128: int fd, rv;
129:
130: USES_DIRS;
131:
132: /* check we can create directories */
133: sprintf(pb, "%s/dir", mountpath);
134: if (rump_sys_mkdir(pb, 0777) == -1)
135: atf_tc_fail_errno("mkdir");
136:
137: sprintf(pb2, "%s/dir/file", mountpath);
138: fd = rump_sys_open(pb2, O_RDWR | O_CREAT, 0777);
139: if (fd == -1)
140: atf_tc_fail_errno("create file");
141: rump_sys_close(fd);
142:
143: rv = rump_sys_rmdir(pb);
144: if (rv != -1 || errno != ENOTEMPTY)
145: atf_tc_fail("non-empty directory removed succesfully");
146:
147: if (rump_sys_unlink(pb2) == -1)
148: atf_tc_fail_errno("cannot remove dir/file");
149:
150: if (rump_sys_rmdir(pb) == -1)
151: atf_tc_fail_errno("remove directory");
152: }
153:
1.2 pooka 154: static void
1.18 pooka 155: dir_rmdirdotdot(const atf_tc_t *tc, const char *mp)
156: {
157: char pb[MAXPATHLEN];
158: int xerrno;
159:
160: USES_DIRS;
161:
162: FSTEST_ENTER();
163: RL(rump_sys_mkdir("test", 0777));
164: RL(rump_sys_chdir("test"));
165:
166: RL(rump_sys_mkdir("subtest", 0777));
167: RL(rump_sys_chdir("subtest"));
168:
169: md(pb, mp, "test/subtest");
170: RL(rump_sys_rmdir(pb));
171: md(pb, mp, "test");
172: RL(rump_sys_rmdir(pb));
173:
174: if (FSTYPE_NFS(tc))
175: xerrno = ESTALE;
176: else
177: xerrno = ENOENT;
1.19 pooka 178: if (FSTYPE_TMPFS(tc))
179: atf_tc_expect_signal(-1, "PR kern/44657");
1.18 pooka 180: ATF_REQUIRE_ERRNO(xerrno, rump_sys_chdir("..") == -1);
181: FSTEST_EXIT();
182: }
183:
184: static void
1.2 pooka 185: checkfile(const char *path, struct stat *refp)
186: {
187: char buf[MAXPATHLEN];
188: struct stat sb;
189: static int n = 1;
190:
191: md(buf, path, "file");
192: if (rump_sys_stat(buf, &sb) == -1)
193: atf_tc_fail_errno("cannot stat file %d (%s)", n, buf);
194: if (memcmp(&sb, refp, sizeof(sb)) != 0)
195: atf_tc_fail("stat mismatch %d", n);
196: n++;
197: }
198:
199: static void
200: rename_dir(const atf_tc_t *tc, const char *mp)
201: {
202: char pb1[MAXPATHLEN], pb2[MAXPATHLEN], pb3[MAXPATHLEN];
1.16 pooka 203: struct stat ref, sb;
1.2 pooka 204:
1.17 pooka 205: //if (FSTYPE_MSDOS(tc))
206: //atf_tc_skip("test fails in some setups, reason unknown");
1.3 pooka 207:
1.10 pooka 208: if (FSTYPE_RUMPFS(tc))
209: atf_tc_skip("rename not supported by fs");
210:
1.2 pooka 211: USES_DIRS;
212:
213: md(pb1, mp, "dir1");
214: if (rump_sys_mkdir(pb1, 0777) == -1)
215: atf_tc_fail_errno("mkdir 1");
216:
217: md(pb2, mp, "dir2");
218: if (rump_sys_mkdir(pb2, 0777) == -1)
219: atf_tc_fail_errno("mkdir 2");
220: md(pb2, mp, "dir2/subdir");
221: if (rump_sys_mkdir(pb2, 0777) == -1)
222: atf_tc_fail_errno("mkdir 3");
223:
224: md(pb3, mp, "dir1/file");
225: if (rump_sys_mknod(pb3, S_IFREG | 0777, -1) == -1)
226: atf_tc_fail_errno("create file");
227: if (rump_sys_stat(pb3, &ref) == -1)
228: atf_tc_fail_errno("stat of file");
229:
230: /*
231: * First try ops which should succeed.
232: */
233:
234: /* rename within directory */
235: md(pb3, mp, "dir3");
236: if (rump_sys_rename(pb1, pb3) == -1)
237: atf_tc_fail_errno("rename 1");
238: checkfile(pb3, &ref);
239:
240: /* rename directory onto itself (two ways, should fail) */
241: md(pb1, mp, "dir3/.");
242: if (rump_sys_rename(pb1, pb3) != -1 || errno != EINVAL)
243: atf_tc_fail_errno("rename 2");
244: if (rump_sys_rename(pb3, pb1) != -1 || errno != EISDIR)
245: atf_tc_fail_errno("rename 3");
246:
247: checkfile(pb3, &ref);
248:
249: /* rename father of directory into directory */
250: md(pb1, mp, "dir2/dir");
251: md(pb2, mp, "dir2");
252: if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
253: atf_tc_fail_errno("rename 4");
254:
255: /* same for grandfather */
256: md(pb1, mp, "dir2/subdir/dir2");
257: if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
258: atf_tc_fail("rename 5");
259:
260: checkfile(pb3, &ref);
261:
262: /* rename directory over a non-empty directory */
263: if (rump_sys_rename(pb2, pb3) != -1 || errno != ENOTEMPTY)
264: atf_tc_fail("rename 6");
265:
266: /* cross-directory rename */
267: md(pb1, mp, "dir3");
268: md(pb2, mp, "dir2/somedir");
269: if (rump_sys_rename(pb1, pb2) == -1)
270: atf_tc_fail_errno("rename 7");
271: checkfile(pb2, &ref);
272:
273: /* move to parent directory */
274: md(pb1, mp, "dir2/somedir/../../dir3");
275: if (rump_sys_rename(pb2, pb1) == -1)
276: atf_tc_fail_errno("rename 8");
277: md(pb1, mp, "dir2/../dir3");
278: checkfile(pb1, &ref);
279:
1.16 pooka 280: /* atomic cross-directory rename */
1.2 pooka 281: md(pb3, mp, "dir2/subdir");
282: if (rump_sys_rename(pb1, pb3) == -1)
283: atf_tc_fail_errno("rename 9");
284: checkfile(pb3, &ref);
1.16 pooka 285:
286: /* rename directory over an empty directory */
287: md(pb1, mp, "parent");
288: md(pb2, mp, "parent/dir1");
289: md(pb3, mp, "parent/dir2");
290: RL(rump_sys_mkdir(pb1, 0777));
291: RL(rump_sys_mkdir(pb2, 0777));
292: RL(rump_sys_mkdir(pb3, 0777));
293: RL(rump_sys_rename(pb2, pb3));
294:
295: RL(rump_sys_stat(pb1, &sb));
296: ATF_CHECK_EQ(sb.st_nlink, 3);
297: RL(rump_sys_rmdir(pb3));
298: if (FSTYPE_TMPFS(tc))
299: atf_tc_expect_signal(-1, "PR kern/44288");
300: RL(rump_sys_rmdir(pb1));
1.20 ! pooka 301:
! 302: if (FSTYPE_MSDOS(tc))
! 303: atf_tc_expect_fail("PR kern/44661");
1.2 pooka 304: }
305:
306: static void
307: rename_dotdot(const atf_tc_t *tc, const char *mp)
308: {
309:
1.10 pooka 310: if (FSTYPE_RUMPFS(tc))
311: atf_tc_skip("rename not supported by fs");
312:
1.2 pooka 313: USES_DIRS;
314:
315: if (rump_sys_chdir(mp) == -1)
316: atf_tc_fail_errno("chdir mountpoint");
317:
318: if (rump_sys_mkdir("dir1", 0777) == -1)
319: atf_tc_fail_errno("mkdir 1");
320: if (rump_sys_mkdir("dir2", 0777) == -1)
321: atf_tc_fail_errno("mkdir 2");
322:
323: if (rump_sys_rename("dir1", "dir1/..") != -1 || errno != EINVAL)
324: atf_tc_fail_errno("self-dotdot to");
325:
326: if (rump_sys_rename("dir1/..", "sometarget") != -1 || errno != EINVAL)
327: atf_tc_fail_errno("self-dotdot from");
328: atf_tc_expect_pass();
329:
330: if (FSTYPE_TMPFS(tc)) {
331: atf_tc_expect_fail("PR kern/43617");
332: }
333: if (rump_sys_rename("dir1", "dir2/..") != -1 || errno != EINVAL)
334: atf_tc_fail("other-dotdot");
335:
336: rump_sys_chdir("/");
337: }
338:
339: static void
340: rename_reg_nodir(const atf_tc_t *tc, const char *mp)
341: {
342: bool haslinks;
343: struct stat sb;
344: ino_t f1ino, f2ino;
345:
1.10 pooka 346: if (FSTYPE_RUMPFS(tc))
347: atf_tc_skip("rename not supported by fs");
348:
1.3 pooka 349: if (FSTYPE_MSDOS(tc))
350: atf_tc_skip("test fails in some setups, reason unknown");
351:
1.2 pooka 352: if (rump_sys_chdir(mp) == -1)
353: atf_tc_fail_errno("chdir mountpoint");
354:
355: if (FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))
356: haslinks = false;
357: else
358: haslinks = true;
359:
360: if (rump_sys_mknod("file1", S_IFREG | 0777, -1) == -1)
361: atf_tc_fail_errno("create file");
362: if (rump_sys_mknod("file2", S_IFREG | 0777, -1) == -1)
363: atf_tc_fail_errno("create file");
364:
365: if (rump_sys_stat("file1", &sb) == -1)
366: atf_tc_fail_errno("stat");
367: f1ino = sb.st_ino;
368:
369: if (haslinks) {
370: if (rump_sys_link("file1", "file_link") == -1)
371: atf_tc_fail_errno("link");
372: if (rump_sys_stat("file_link", &sb) == -1)
373: atf_tc_fail_errno("stat");
374: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
375: ATF_REQUIRE_EQ(sb.st_nlink, 2);
376: }
377:
378: if (rump_sys_stat("file2", &sb) == -1)
379: atf_tc_fail_errno("stat");
380: f2ino = sb.st_ino;
381:
382: if (rump_sys_rename("file1", "file3") == -1)
383: atf_tc_fail_errno("rename 1");
384: if (rump_sys_stat("file3", &sb) == -1)
385: atf_tc_fail_errno("stat 1");
386: if (haslinks) {
387: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
388: }
389: if (rump_sys_stat("file1", &sb) != -1 || errno != ENOENT)
390: atf_tc_fail_errno("source 1");
391:
392: if (rump_sys_rename("file3", "file2") == -1)
393: atf_tc_fail_errno("rename 2");
394: if (rump_sys_stat("file2", &sb) == -1)
395: atf_tc_fail_errno("stat 2");
396: if (haslinks) {
397: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
398: }
399:
400: if (rump_sys_stat("file3", &sb) != -1 || errno != ENOENT)
401: atf_tc_fail_errno("source 2");
402:
403: if (haslinks) {
404: if (rump_sys_rename("file2", "file_link") == -1)
405: atf_tc_fail_errno("rename hardlink");
406: if (rump_sys_stat("file2", &sb) != -1 || errno != ENOENT)
407: atf_tc_fail_errno("source 3");
408: if (rump_sys_stat("file_link", &sb) == -1)
409: atf_tc_fail_errno("stat 2");
410: ATF_REQUIRE_EQ(sb.st_ino, f1ino);
411: ATF_REQUIRE_EQ(sb.st_nlink, 1);
412: }
413:
414: rump_sys_chdir("/");
415: }
416:
1.5 njoly 417: static void
418: create_nametoolong(const atf_tc_t *tc, const char *mp)
419: {
420: char *name;
421: int fd;
422: long val;
423: size_t len;
424:
425: if (rump_sys_chdir(mp) == -1)
426: atf_tc_fail_errno("chdir mountpoint");
427:
428: val = rump_sys_pathconf(".", _PC_NAME_MAX);
429: if (val == -1)
430: atf_tc_fail_errno("pathconf");
431:
432: len = val + 1;
433: name = malloc(len+1);
434: if (name == NULL)
435: atf_tc_fail_errno("malloc");
436:
437: memset(name, 'a', len);
438: *(name+len) = '\0';
439:
440: val = rump_sys_pathconf(".", _PC_NO_TRUNC);
441: if (val == -1)
442: atf_tc_fail_errno("pathconf");
443:
444: if (FSTYPE_MSDOS(tc))
445: atf_tc_expect_fail("PR kern/43670");
446: fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666);
447: if (val != 0 && (fd != -1 || errno != ENAMETOOLONG))
448: atf_tc_fail_errno("open");
449:
450: if (val == 0 && rump_sys_close(fd) == -1)
451: atf_tc_fail_errno("close");
452: if (val == 0 && rump_sys_unlink(name) == -1)
453: atf_tc_fail_errno("unlink");
454:
455: free(name);
456:
457: rump_sys_chdir("/");
458: }
459:
460: static void
1.14 yamt 461: create_exist(const atf_tc_t *tc, const char *mp)
462: {
463: const char *name = "hoge";
464: int fd;
465:
466: RL(rump_sys_chdir(mp));
467: RL(fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666));
468: RL(rump_sys_close(fd));
469: RL(rump_sys_unlink(name));
470: RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
471: RL(rump_sys_close(fd));
472: RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
473: RL(rump_sys_close(fd));
474: ATF_REQUIRE_ERRNO(EEXIST,
475: (fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666)));
476: RL(rump_sys_unlink(name));
477: RL(rump_sys_chdir("/"));
478: }
479:
480: static void
1.5 njoly 481: rename_nametoolong(const atf_tc_t *tc, const char *mp)
482: {
483: char *name;
484: int res, fd;
485: long val;
486: size_t len;
487:
1.10 pooka 488: if (FSTYPE_RUMPFS(tc))
489: atf_tc_skip("rename not supported by fs");
490:
1.5 njoly 491: if (rump_sys_chdir(mp) == -1)
492: atf_tc_fail_errno("chdir mountpoint");
493:
494: val = rump_sys_pathconf(".", _PC_NAME_MAX);
495: if (val == -1)
496: atf_tc_fail_errno("pathconf");
497:
498: len = val + 1;
499: name = malloc(len+1);
500: if (name == NULL)
501: atf_tc_fail_errno("malloc");
502:
503: memset(name, 'a', len);
504: *(name+len) = '\0';
505:
506: fd = rump_sys_open("dummy", O_RDWR|O_CREAT, 0666);
507: if (fd == -1)
508: atf_tc_fail_errno("open");
509: if (rump_sys_close(fd) == -1)
510: atf_tc_fail_errno("close");
511:
512: val = rump_sys_pathconf(".", _PC_NO_TRUNC);
513: if (val == -1)
514: atf_tc_fail_errno("pathconf");
515:
516: if (FSTYPE_MSDOS(tc))
517: atf_tc_expect_fail("PR kern/43670");
518: res = rump_sys_rename("dummy", name);
519: if (val != 0 && (res != -1 || errno != ENAMETOOLONG))
520: atf_tc_fail_errno("rename");
521:
522: if (val == 0 && rump_sys_unlink(name) == -1)
523: atf_tc_fail_errno("unlink");
524:
525: free(name);
526:
527: rump_sys_chdir("/");
528: }
529:
1.7 pooka 530: static void
531: symlink_zerolen(const atf_tc_t *tc, const char *mp)
532: {
533:
534: USES_SYMLINKS;
535:
536: RL(rump_sys_chdir(mp));
1.8 pooka 537:
538: if (FSTYPE_TMPFS(tc)) {
539: atf_tc_expect_signal(SIGABRT, "PR kern/43843");
540: }
541:
1.7 pooka 542: RL(rump_sys_symlink("", "afile"));
543: RL(rump_sys_chdir("/"));
544: }
545:
1.11 pooka 546: static void
547: attrs(const atf_tc_t *tc, const char *mp)
548: {
549: struct stat sb, sb2;
550: struct timeval tv[2];
551: int fd;
552:
553: FSTEST_ENTER();
554: RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
555: RL(rump_sys_close(fd));
556: RL(rump_sys_stat(TESTFILE, &sb));
557: if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
558: RL(rump_sys_chown(TESTFILE, 1, 2));
559: sb.st_uid = 1;
560: sb.st_gid = 2;
561: RL(rump_sys_chmod(TESTFILE, 0123));
562: sb.st_mode = (sb.st_mode & ~ACCESSPERMS) | 0123;
563: }
564:
565: tv[0].tv_sec = 1000000000; /* need something >1980 for msdosfs */
566: tv[0].tv_usec = 1;
567: tv[1].tv_sec = 1000000002; /* need even seconds for msdosfs */
568: tv[1].tv_usec = 3;
569: RL(rump_sys_utimes(TESTFILE, tv));
570: RL(rump_sys_utimes(TESTFILE, tv)); /* XXX: utimes & birthtime */
571: sb.st_atimespec.tv_sec = 1000000000;
572: sb.st_atimespec.tv_nsec = 1000;
573: sb.st_mtimespec.tv_sec = 1000000002;
574: sb.st_mtimespec.tv_nsec = 3000;
575:
576: RL(rump_sys_stat(TESTFILE, &sb2));
577: #define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a)
578: if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
579: CHECK(st_uid);
580: CHECK(st_gid);
581: CHECK(st_mode);
582: }
583: if (!FSTYPE_MSDOS(tc)) {
584: /* msdosfs has only access date, not time */
585: CHECK(st_atimespec.tv_sec);
586: }
587: CHECK(st_mtimespec.tv_sec);
588: if (!(FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
589: CHECK(st_atimespec.tv_nsec);
590: CHECK(st_mtimespec.tv_nsec);
591: }
592: #undef CHECK
593:
594: FSTEST_EXIT();
595: }
596:
1.12 kefren 597: static void
598: fcntl_lock(const atf_tc_t *tc, const char *mp)
599: {
600: int fd, fd2;
601: struct flock l;
602: struct lwp *lwp1, *lwp2;
603:
604: FSTEST_ENTER();
605: l.l_pid = 0;
606: l.l_start = l.l_len = 1024;
607: l.l_type = F_RDLCK | F_WRLCK;
608: l.l_whence = SEEK_END;
609:
610: lwp1 = rump_pub_lwproc_curlwp();
611: RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
612: RL(rump_sys_ftruncate(fd, 8192));
613:
614: /* PR kern/43321 */
615: RL(rump_sys_fcntl(fd, F_SETLK, &l));
616:
617: /* Next, we fork and try to lock the same area */
618: RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
619: lwp2 = rump_pub_lwproc_curlwp();
620: RL(fd2 = rump_sys_open(TESTFILE, O_RDWR, 0));
621: ATF_REQUIRE_ERRNO(EAGAIN, rump_sys_fcntl(fd2, F_SETLK, &l));
622:
623: /* Switch back and unlock... */
624: rump_pub_lwproc_switch(lwp1);
625: l.l_type = F_UNLCK;
626: RL(rump_sys_fcntl(fd, F_SETLK, &l));
627:
628: /* ... and try to lock again */
629: rump_pub_lwproc_switch(lwp2);
630: l.l_type = F_RDLCK | F_WRLCK;
631: RL(rump_sys_fcntl(fd2, F_SETLK, &l));
632:
633: RL(rump_sys_close(fd2));
634: rump_pub_lwproc_releaselwp();
635:
636: RL(rump_sys_close(fd));
637:
638: FSTEST_EXIT();
639: }
640:
1.13 pooka 641: static int
642: flock_compare(const void *p, const void *q)
643: {
644: int a = ((const struct flock *)p)->l_start;
645: int b = ((const struct flock *)q)->l_start;
646: return a < b ? -1 : (a > b ? 1 : 0);
647: }
648:
649: static void
650: fcntl_getlock_pids(const atf_tc_t *tc, const char *mp)
651: {
652: /* test non-overlaping ranges */
653: struct flock expect[4];
654: const struct flock lock[4] = {
655: { 0, 2, 0, F_WRLCK, SEEK_SET },
656: { 2, 1, 0, F_WRLCK, SEEK_SET },
657: { 7, 5, 0, F_WRLCK, SEEK_SET },
658: { 4, 3, 0, F_WRLCK, SEEK_SET },
659: };
660:
661: int fd[4];
662: struct lwp *lwp[4];
663: pid_t prevpid = 0;
664:
665: unsigned int i, j;
666: const off_t sz = 8192;
667: int omode = 0755;
668: int oflags = O_RDWR | O_CREAT;
669:
670: memcpy(expect, lock, sizeof(lock));
671: qsort(expect, __arraycount(expect), sizeof(expect[0]), &flock_compare);
672:
673: FSTEST_ENTER();
674:
675: /*
676: * First, we create 4 processes and let each lock a range of the
677: * file. Note that the third and fourth processes lock in
678: * "reverse" order, i.e. the greater pid locks a range before
679: * the lesser pid.
680: */
681: for(i = 0; i < __arraycount(lwp); i++) {
682: RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
683:
684: lwp[i] = rump_pub_lwproc_curlwp();
685: assert(rump_sys_getpid() > prevpid);
686: prevpid = rump_sys_getpid();
687:
688: RL(fd[i] = rump_sys_open(TESTFILE, oflags, omode));
689: oflags = O_RDWR;
690: omode = 0;
691:
692: RL(rump_sys_ftruncate(fd[i], sz));
693: RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i]));
694: }
695:
696: atf_tc_expect_fail("PR kern/44494");
697: /*
698: * In the context of each pid , do GETLK for a readlock from
699: * i = [0,__arraycount(locks)]. If we try to lock from the same
700: * start offset as the lock our current process holds, check
701: * that we fail on the offset of the next lock ("else if" branch).
702: * Otherwise, expect to get a lock for the current offset
703: * ("if" branch). The "else" branch is purely for the last
704: * process where we expect no blocking locks.
705: */
706: for(i = 0; i < __arraycount(lwp); i++) {
707: rump_pub_lwproc_switch(lwp[i]);
708:
709: for(j = 0; j < __arraycount(lwp); j++) {
710: struct flock l;
711: l = expect[j];
712: l.l_len = sz;
713: l.l_type = F_RDLCK;
714:
715: RL(rump_sys_fcntl(fd[i], F_GETLK, &l));
716:
717: if(expect[j].l_start != lock[i].l_start) {
718: /*
719: * lock set by another process
720: */
721: ATF_CHECK(l.l_type != F_UNLCK);
722: ATF_CHECK_EQ(l.l_start, expect[j].l_start);
723: ATF_CHECK_EQ(l.l_len, expect[j].l_len);
724: } else if (j != __arraycount(lwp) - 1) {
725: /*
726: * lock set by the current process
727: */
728: ATF_CHECK(l.l_type != F_UNLCK);
729: ATF_CHECK_EQ(l.l_start, expect[j+1].l_start);
730: ATF_CHECK_EQ(l.l_len, expect[j+1].l_len);
731: } else {
732: /*
733: * there are no other locks after the
734: * current process lock
735: */
736: ATF_CHECK_EQ(l.l_type, F_UNLCK);
737: ATF_CHECK_EQ(l.l_start, expect[j].l_start);
738: ATF_CHECK_EQ(l.l_len, sz);
739: ATF_CHECK_EQ(l.l_pid, expect[j].l_pid);
740: ATF_CHECK_EQ(l.l_whence, expect[j].l_whence);
741: }
742: }
743: }
744:
745: /*
746: * Release processes. This also releases the fds and locks
747: * making fs unmount possible
748: */
749: for(i = 0; i < __arraycount(lwp); i++) {
750: rump_pub_lwproc_switch(lwp[i]);
751: rump_pub_lwproc_releaselwp();
752: }
753:
754: FSTEST_EXIT();
755: }
756:
1.15 pooka 757: static void
758: access_simple(const atf_tc_t *tc, const char *mp)
759: {
760: int fd;
761: int tmode;
762:
763: FSTEST_ENTER();
764: RL(fd = rump_sys_open("tfile", O_CREAT | O_RDWR, 0777));
765: RL(rump_sys_close(fd));
766:
767: #define ALLACC (F_OK | X_OK | W_OK | R_OK)
768: if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc))
769: tmode = F_OK;
770: else
771: tmode = ALLACC;
772:
773: RL(rump_sys_access("tfile", tmode));
774:
775: /* PR kern/44648 */
776: ATF_REQUIRE_ERRNO(EINVAL, rump_sys_access("tfile", ALLACC+1) == -1);
777: #undef ALLACC
778: FSTEST_EXIT();
779: }
780:
1.1 pooka 781: ATF_TC_FSAPPLY(lookup_simple, "simple lookup (./.. on root)");
782: ATF_TC_FSAPPLY(lookup_complex, "lookup of non-dot entries");
783: ATF_TC_FSAPPLY(dir_simple, "mkdir/rmdir");
784: ATF_TC_FSAPPLY(dir_notempty, "non-empty directories cannot be removed");
1.18 pooka 785: ATF_TC_FSAPPLY(dir_rmdirdotdot, "remove .. and try to cd out");
1.2 pooka 786: ATF_TC_FSAPPLY(rename_dir, "exercise various directory renaming ops");
787: ATF_TC_FSAPPLY(rename_dotdot, "rename dir ..");
788: ATF_TC_FSAPPLY(rename_reg_nodir, "rename regular files, no subdirectories");
1.5 njoly 789: ATF_TC_FSAPPLY(create_nametoolong, "create file with name too long");
1.14 yamt 790: ATF_TC_FSAPPLY(create_exist, "create with O_EXCL");
1.5 njoly 791: ATF_TC_FSAPPLY(rename_nametoolong, "rename to file with name too long");
1.7 pooka 792: ATF_TC_FSAPPLY(symlink_zerolen, "symlink with 0-len target");
1.11 pooka 793: ATF_TC_FSAPPLY(attrs, "check setting attributes works");
1.12 kefren 794: ATF_TC_FSAPPLY(fcntl_lock, "check fcntl F_SETLK");
1.13 pooka 795: ATF_TC_FSAPPLY(fcntl_getlock_pids,"fcntl F_GETLK w/ many procs, PR kern/44494");
1.15 pooka 796: ATF_TC_FSAPPLY(access_simple, "access(2)");
1.1 pooka 797:
798: ATF_TP_ADD_TCS(tp)
799: {
800:
801: ATF_TP_FSAPPLY(lookup_simple);
802: ATF_TP_FSAPPLY(lookup_complex);
803: ATF_TP_FSAPPLY(dir_simple);
804: ATF_TP_FSAPPLY(dir_notempty);
1.18 pooka 805: ATF_TP_FSAPPLY(dir_rmdirdotdot);
1.2 pooka 806: ATF_TP_FSAPPLY(rename_dir);
807: ATF_TP_FSAPPLY(rename_dotdot);
808: ATF_TP_FSAPPLY(rename_reg_nodir);
1.5 njoly 809: ATF_TP_FSAPPLY(create_nametoolong);
1.14 yamt 810: ATF_TP_FSAPPLY(create_exist);
1.5 njoly 811: ATF_TP_FSAPPLY(rename_nametoolong);
1.7 pooka 812: ATF_TP_FSAPPLY(symlink_zerolen);
1.11 pooka 813: ATF_TP_FSAPPLY(attrs);
1.12 kefren 814: ATF_TP_FSAPPLY(fcntl_lock);
1.13 pooka 815: ATF_TP_FSAPPLY(fcntl_getlock_pids);
1.15 pooka 816: ATF_TP_FSAPPLY(access_simple);
1.1 pooka 817:
818: return atf_no_error();
819: }
CVSweb <webmaster@jp.NetBSD.org>