1 /* $NetBSD: t_vnops.c,v 1.49 2015/04/09 19:47:05 riastradh Exp $ */
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
30 #include <sys/statvfs.h>
40 #include <rump/rump_syscalls.h>
41 #include <rump/rump.h>
43 #include "../common/h_fsmacros.h"
44 #include "../../h_macros.h"
46 #define TESTFILE "afile"
49 if (FSTYPE_SYSVBFS(tc)) \
50 atf_tc_skip("directories not supported by file system")
52 #define USES_SYMLINKS \
53 if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc)) \
54 atf_tc_skip("symlinks not supported by file system")
57 md(char *buf
, const char *base
, const char *tail
)
60 sprintf(buf
, "%s/%s", base
, tail
);
65 lookup_simple(const atf_tc_t
*tc
, const char *mountpath
)
67 char pb
[MAXPATHLEN
], final
[MAXPATHLEN
];
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");
75 sprintf(pb
, "%s/./../%s", mountpath
, basename(final
));
76 if (rump_sys_stat(pb
, &sb2
) == -1)
77 atf_tc_fail_errno("stat 2");
79 ATF_REQUIRE(memcmp(&sb1
, &sb2
, sizeof(sb1
)) == 0);
83 lookup_complex(const atf_tc_t
*tc
, const char *mountpath
)
91 atf_tc_expect_fail("PR kern/49033");
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");
99 sprintf(pb
, "%s/./dir/../././dir/.", mountpath
);
100 if (rump_sys_stat(pb
, &sb2
) == -1)
101 atf_tc_fail_errno("stat 2");
103 if (memcmp(&sb1
, &sb2
, sizeof(sb1
)) != 0) {
104 printf("what\tsb1\t\tsb2\n");
107 printf(#FN "\t%lld\t%lld\n", \
108 (long long)sb1.FN, (long long)sb2.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)
124 TIME(st_birthtimespec
);
133 atf_tc_fail("stat results differ, see ouput for more details");
136 atf_tc_fail("random failure of PR kern/49033 "
137 "did not happen this time");
141 dir_simple(const atf_tc_t
*tc
, const char *mountpath
)
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");
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");
163 dir_notempty(const atf_tc_t
*tc
, const char *mountpath
)
165 char pb
[MAXPATHLEN
], pb2
[MAXPATHLEN
];
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");
175 sprintf(pb2
, "%s/dir/file", mountpath
);
176 fd
= rump_sys_open(pb2
, O_RDWR
| O_CREAT
, 0777);
178 atf_tc_fail_errno("create file");
181 rv
= rump_sys_rmdir(pb
);
182 if (rv
!= -1 || errno
!= ENOTEMPTY
)
183 atf_tc_fail("non-empty directory removed succesfully");
185 if (rump_sys_unlink(pb2
) == -1)
186 atf_tc_fail_errno("cannot remove dir/file");
188 if (rump_sys_rmdir(pb
) == -1)
189 atf_tc_fail_errno("remove directory");
193 dir_rmdirdotdot(const atf_tc_t
*tc
, const char *mp
)
201 RL(rump_sys_mkdir("test", 0777));
202 RL(rump_sys_chdir("test"));
204 RL(rump_sys_mkdir("subtest", 0777));
205 RL(rump_sys_chdir("subtest"));
207 md(pb
, mp
, "test/subtest");
208 RL(rump_sys_rmdir(pb
));
210 RL(rump_sys_rmdir(pb
));
216 ATF_REQUIRE_ERRNO(xerrno
, rump_sys_chdir("..") == -1);
221 checkfile(const char *path
, struct stat
*refp
)
223 char buf
[MAXPATHLEN
];
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
);
236 rename_dir(const atf_tc_t
*tc
, const char *mp
)
238 char pb1
[MAXPATHLEN
], pb2
[MAXPATHLEN
], pb3
[MAXPATHLEN
];
241 if (FSTYPE_RUMPFS(tc
))
242 atf_tc_skip("rename not supported by file system");
247 if (rump_sys_mkdir(pb1
, 0777) == -1)
248 atf_tc_fail_errno("mkdir 1");
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");
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");
264 * First try ops which should succeed.
267 /* rename within directory */
269 if (rump_sys_rename(pb1
, pb3
) == -1)
270 atf_tc_fail_errno("rename 1");
271 checkfile(pb3
, &ref
);
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");
280 checkfile(pb3
, &ref
);
282 /* rename father of directory into directory */
283 md(pb1
, mp
, "dir2/dir");
285 if (rump_sys_rename(pb2
, pb1
) != -1 || errno
!= EINVAL
)
286 atf_tc_fail_errno("rename 4");
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");
293 checkfile(pb3
, &ref
);
295 /* rename directory over a non-empty directory */
296 if (rump_sys_rename(pb2
, pb3
) != -1 || errno
!= ENOTEMPTY
)
297 atf_tc_fail("rename 6");
299 /* cross-directory rename */
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
);
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
);
313 /* atomic cross-directory rename */
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
);
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
));
328 RL(rump_sys_stat(pb1
, &sb
));
329 if (! FSTYPE_MSDOS(tc
))
330 ATF_CHECK_EQ(sb
.st_nlink
, 3);
331 RL(rump_sys_rmdir(pb3
));
332 RL(rump_sys_rmdir(pb1
));
336 rename_dotdot(const atf_tc_t
*tc
, const char *mp
)
339 if (FSTYPE_RUMPFS(tc
))
340 atf_tc_skip("rename not supported by file system");
344 if (rump_sys_chdir(mp
) == -1)
345 atf_tc_fail_errno("chdir mountpoint");
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");
352 if (rump_sys_rename("dir1", "dir1/..") != -1 || errno
!= EINVAL
)
353 atf_tc_fail_errno("self-dotdot to");
355 if (rump_sys_rename("dir1/..", "sometarget") != -1 || errno
!= EINVAL
)
356 atf_tc_fail_errno("self-dotdot from");
358 if (rump_sys_rename("dir1", "dir2/..") != -1 || errno
!= EINVAL
)
359 atf_tc_fail("other-dotdot");
365 rename_reg_nodir(const atf_tc_t
*tc
, const char *mp
)
371 if (FSTYPE_RUMPFS(tc
))
372 atf_tc_skip("rename not supported by file system");
374 if (rump_sys_chdir(mp
) == -1)
375 atf_tc_fail_errno("chdir mountpoint");
377 if (FSTYPE_MSDOS(tc
) || FSTYPE_SYSVBFS(tc
))
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");
387 if (rump_sys_stat("file1", &sb
) == -1)
388 atf_tc_fail_errno("stat");
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);
400 if (rump_sys_stat("file2", &sb
) == -1)
401 atf_tc_fail_errno("stat");
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");
408 ATF_REQUIRE_EQ(sb
.st_ino
, f1ino
);
410 if (rump_sys_stat("file1", &sb
) != -1 || errno
!= ENOENT
)
411 atf_tc_fail_errno("source 1");
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");
418 ATF_REQUIRE_EQ(sb
.st_ino
, f1ino
);
421 if (rump_sys_stat("file3", &sb
) != -1 || errno
!= ENOENT
)
422 atf_tc_fail_errno("source 2");
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);
435 ATF_CHECK_ERRNO(EFAULT
, rump_sys_rename("file2", NULL
) == -1);
436 ATF_CHECK_ERRNO(EFAULT
, rump_sys_rename(NULL
, "file2") == -1);
442 create_nametoolong(const atf_tc_t
*tc
, const char *mp
)
449 if (rump_sys_chdir(mp
) == -1)
450 atf_tc_fail_errno("chdir mountpoint");
452 val
= rump_sys_pathconf(".", _PC_NAME_MAX
);
454 atf_tc_fail_errno("pathconf");
457 name
= malloc(len
+1);
459 atf_tc_fail_errno("malloc");
461 memset(name
, 'a', len
);
464 val
= rump_sys_pathconf(".", _PC_NO_TRUNC
);
466 atf_tc_fail_errno("pathconf");
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");
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");
483 create_exist(const atf_tc_t
*tc
, const char *mp
)
485 const char *name
= "hoge";
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("/"));
503 rename_nametoolong(const atf_tc_t
*tc
, const char *mp
)
510 if (FSTYPE_RUMPFS(tc
))
511 atf_tc_skip("rename not supported by file system");
513 if (rump_sys_chdir(mp
) == -1)
514 atf_tc_fail_errno("chdir mountpoint");
516 val
= rump_sys_pathconf(".", _PC_NAME_MAX
);
518 atf_tc_fail_errno("pathconf");
521 name
= malloc(len
+1);
523 atf_tc_fail_errno("malloc");
525 memset(name
, 'a', len
);
528 fd
= rump_sys_open("dummy", O_RDWR
|O_CREAT
, 0666);
530 atf_tc_fail_errno("open");
531 if (rump_sys_close(fd
) == -1)
532 atf_tc_fail_errno("close");
534 val
= rump_sys_pathconf(".", _PC_NO_TRUNC
);
536 atf_tc_fail_errno("pathconf");
538 res
= rump_sys_rename("dummy", name
);
539 if (val
!= 0 && (res
!= -1 || errno
!= ENAMETOOLONG
))
540 atf_tc_fail_errno("rename");
542 if (val
== 0 && rump_sys_unlink(name
) == -1)
543 atf_tc_fail_errno("unlink");
551 * Test creating a symlink whose length is "len" bytes, not including
552 * the terminating NUL.
555 symlink_len(const atf_tc_t
*tc
, const char *mp
, size_t len
)
562 RL(rump_sys_chdir(mp
));
564 buf
= malloc(len
+ 1);
566 memset(buf
, 'a', len
);
568 r
= rump_sys_symlink(buf
, "afile");
570 ATF_REQUIRE_ERRNO(ENAMETOOLONG
, r
);
572 RL(rump_sys_unlink("afile"));
576 RL(rump_sys_chdir("/"));
580 symlink_zerolen(const atf_tc_t
*tc
, const char *mp
)
582 symlink_len(tc
, mp
, 0);
586 symlink_long(const atf_tc_t
*tc
, const char *mp
)
589 * Test lengths close to powers of two, as those are likely
594 for (len
= 2; len
<= 65536; len
*= 2) {
595 for (fuzz
= -1; fuzz
<= 1; fuzz
++) {
596 symlink_len(tc
, mp
, len
+ fuzz
);
602 symlink_root(const atf_tc_t
*tc
, const char *mp
)
607 RL(rump_sys_chdir(mp
));
608 RL(rump_sys_symlink("/", "foo"));
609 RL(rump_sys_chdir("foo"));
613 attrs(const atf_tc_t
*tc
, const char *mp
)
616 struct timeval tv
[2];
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));
627 RL(rump_sys_chmod(TESTFILE
, 0123));
628 sb
.st_mode
= (sb
.st_mode
& ~ACCESSPERMS
) | 0123;
631 tv
[0].tv_sec
= 1000000000; /* need something >1980 for msdosfs */
633 tv
[1].tv_sec
= 1000000002; /* need even seconds for msdosfs */
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;
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
))) {
649 if (!FSTYPE_MSDOS(tc
)) {
650 /* msdosfs has only access date, not time */
651 CHECK(st_atimespec
.tv_sec
);
653 CHECK(st_mtimespec
.tv_sec
);
654 if (!(FSTYPE_EXT2FS(tc
) || FSTYPE_MSDOS(tc
) ||
655 FSTYPE_SYSVBFS(tc
) || FSTYPE_V7FS(tc
))) {
656 CHECK(st_atimespec
.tv_nsec
);
657 CHECK(st_mtimespec
.tv_nsec
);
665 fcntl_lock(const atf_tc_t
*tc
, const char *mp
)
669 struct lwp
*lwp1
, *lwp2
;
673 l
.l_start
= l
.l_len
= 1024;
674 l
.l_type
= F_RDLCK
| F_WRLCK
;
675 l
.l_whence
= SEEK_END
;
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));
681 RL(rump_sys_fcntl(fd
, F_SETLK
, &l
));
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
));
689 /* Switch back and unlock... */
690 rump_pub_lwproc_switch(lwp1
);
692 RL(rump_sys_fcntl(fd
, F_SETLK
, &l
));
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
));
699 RL(rump_sys_close(fd2
));
700 rump_pub_lwproc_releaselwp();
702 RL(rump_sys_close(fd
));
708 flock_compare(const void *p
, const void *q
)
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);
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.
725 fcntl_getlocks(int fildes
, off_t start
, off_t len
,
726 struct flock
*lock
, struct flock
*end
)
729 const struct flock l
= { start
, len
, 0, F_RDLCK
, SEEK_SET
};
734 RL(rump_sys_fcntl(fildes
, F_GETLK
, &l
));
736 if (l
.l_type
== F_UNLCK
)
742 ATF_REQUIRE(l
.l_whence
== SEEK_SET
);
744 if (l
.l_start
> start
) {
746 fcntl_getlocks(fildes
, start
, l
.l_start
- start
, lock
, end
);
753 if (l
.l_len
== 0) /* does l spans until the end? */
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
);
767 fcntl_getlock_pids(const atf_tc_t
*tc
, const char *mp
)
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
},
778 /* Add extra element to make sure recursion does't stop at array end */
779 struct flock result
[5];
781 /* Add 5th process */
787 const off_t sz
= 8192;
789 int oflags
= O_RDWR
| O_CREAT
;
791 memcpy(expect
, lock
, sizeof(lock
));
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
800 * Then, we create 5th process which doesn't lock anything.
802 for (i
= 0; i
< __arraycount(lwp
); i
++) {
803 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG
));
805 lwp
[i
] = rump_pub_lwproc_curlwp();
806 pid
[i
] = rump_sys_getpid();
808 RL(fd
[i
] = rump_sys_open(TESTFILE
, oflags
, omode
));
812 RL(rump_sys_ftruncate(fd
[i
], sz
));
814 if (i
< __arraycount(lock
)) {
815 RL(rump_sys_fcntl(fd
[i
], F_SETLK
, &lock
[i
]));
816 expect
[i
].l_pid
= pid
[i
];
820 qsort(expect
, __arraycount(expect
), sizeof(expect
[0]), &flock_compare
);
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.
828 for (i
= 0; i
< __arraycount(lwp
); i
++) {
831 rump_pub_lwproc_switch(lwp
[i
]);
833 memset(result
, 0, sizeof(result
));
834 nlocks
= fcntl_getlocks(fd
[i
], 0, sz
,
835 result
, result
+ __arraycount(result
));
837 if (i
< __arraycount(lock
)) {
838 ATF_REQUIRE(nlocks
< __arraycount(result
));
839 result
[nlocks
] = lock
[i
];
840 result
[nlocks
].l_pid
= pid
[i
];
844 ATF_CHECK_EQ(nlocks
, __arraycount(expect
));
846 qsort(result
, nlocks
, sizeof(result
[0]), &flock_compare
);
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
);
858 * Release processes. This also releases the fds and locks
859 * making fs unmount possible
861 for (i
= 0; i
< __arraycount(lwp
); i
++) {
862 rump_pub_lwproc_switch(lwp
[i
]);
863 rump_pub_lwproc_releaselwp();
870 access_simple(const atf_tc_t
*tc
, const char *mp
)
876 RL(fd
= rump_sys_open("tfile", O_CREAT
| O_RDWR
, 0777));
877 RL(rump_sys_close(fd
));
879 #define ALLACC (F_OK | X_OK | W_OK | R_OK)
880 if (FSTYPE_SYSVBFS(tc
) || FSTYPE_MSDOS(tc
))
885 RL(rump_sys_access("tfile", tmode
));
888 ATF_REQUIRE_ERRNO(EINVAL
, rump_sys_access("tfile", ALLACC
+1) == -1);
894 read_directory(const atf_tc_t
*tc
, const char *mp
)
901 fd
= rump_sys_open(".", O_DIRECTORY
| O_RDONLY
, 0777);
902 ATF_REQUIRE(fd
!= -1);
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
);
909 res
= rump_sys_close(fd
);
910 ATF_REQUIRE(res
!= -1);
915 lstat_symlink(const atf_tc_t
*tc
, const char *mp
)
917 const char *src
, *dst
;
928 res
= rump_sys_symlink(src
, dst
);
929 ATF_REQUIRE(res
!= -1);
930 res
= rump_sys_lstat(dst
, &st
);
931 ATF_REQUIRE(res
!= -1);
933 ATF_CHECK(S_ISLNK(st
.st_mode
) != 0);
934 ATF_CHECK(st
.st_size
== (off_t
)strlen(src
));
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");
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 "
946 ATF_TC_FSAPPLY(rename_dotdot
, "rename dir .. (PR kern/43617)");
947 ATF_TC_FSAPPLY(rename_reg_nodir
, "rename regular files, no subdirectories");
948 ATF_TC_FSAPPLY(create_nametoolong
, "create file with name too long");
949 ATF_TC_FSAPPLY(create_exist
, "create with O_EXCL");
950 ATF_TC_FSAPPLY(rename_nametoolong
, "rename to file with name too long");
951 ATF_TC_FSAPPLY(symlink_zerolen
, "symlink with target of length 0");
952 ATF_TC_FSAPPLY(symlink_long
, "symlink with target of length > 0");
953 ATF_TC_FSAPPLY(symlink_root
, "symlink to root directory");
954 ATF_TC_FSAPPLY(attrs
, "check setting attributes works");
955 ATF_TC_FSAPPLY(fcntl_lock
, "check fcntl F_SETLK");
956 ATF_TC_FSAPPLY(fcntl_getlock_pids
,"fcntl F_GETLK w/ many procs, PR kern/44494");
957 ATF_TC_FSAPPLY(access_simple
, "access(2)");
958 ATF_TC_FSAPPLY(read_directory
, "read(2) on directories");
959 ATF_TC_FSAPPLY(lstat_symlink
, "lstat(2) values for symbolic links");
964 ATF_TP_FSAPPLY(lookup_simple
);
965 ATF_TP_FSAPPLY(lookup_complex
);
966 ATF_TP_FSAPPLY(dir_simple
);
967 ATF_TP_FSAPPLY(dir_notempty
);
968 ATF_TP_FSAPPLY(dir_rmdirdotdot
);
969 ATF_TP_FSAPPLY(rename_dir
);
970 ATF_TP_FSAPPLY(rename_dotdot
);
971 ATF_TP_FSAPPLY(rename_reg_nodir
);
972 ATF_TP_FSAPPLY(create_nametoolong
);
973 ATF_TP_FSAPPLY(create_exist
);
974 ATF_TP_FSAPPLY(rename_nametoolong
);
975 ATF_TP_FSAPPLY(symlink_zerolen
);
976 ATF_TP_FSAPPLY(symlink_long
);
977 ATF_TP_FSAPPLY(symlink_root
);
978 ATF_TP_FSAPPLY(attrs
);
979 ATF_TP_FSAPPLY(fcntl_lock
);
980 ATF_TP_FSAPPLY(fcntl_getlock_pids
);
981 ATF_TP_FSAPPLY(access_simple
);
982 ATF_TP_FSAPPLY(read_directory
);
983 ATF_TP_FSAPPLY(lstat_symlink
);
985 return atf_no_error();