xref: /netbsd-src/tests/fs/vfs/t_vnops.c (revision e171cef674c69200bbfc54629573bfbcba313f30)
1*e171cef6Sandvar /*	$NetBSD: t_vnops.c,v 1.63 2023/05/08 19:23:45 andvar Exp $	*/
22a5fd96fSpooka 
32a5fd96fSpooka /*-
42a5fd96fSpooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
52a5fd96fSpooka  * All rights reserved.
62a5fd96fSpooka  *
72a5fd96fSpooka  * Redistribution and use in source and binary forms, with or without
82a5fd96fSpooka  * modification, are permitted provided that the following conditions
92a5fd96fSpooka  * are met:
102a5fd96fSpooka  * 1. Redistributions of source code must retain the above copyright
112a5fd96fSpooka  *    notice, this list of conditions and the following disclaimer.
122a5fd96fSpooka  * 2. Redistributions in binary form must reproduce the above copyright
132a5fd96fSpooka  *    notice, this list of conditions and the following disclaimer in the
142a5fd96fSpooka  *    documentation and/or other materials provided with the distribution.
152a5fd96fSpooka  *
162a5fd96fSpooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
172a5fd96fSpooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
182a5fd96fSpooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
192a5fd96fSpooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
202a5fd96fSpooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
212a5fd96fSpooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
222a5fd96fSpooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
232a5fd96fSpooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
242a5fd96fSpooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
252a5fd96fSpooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
262a5fd96fSpooka  * POSSIBILITY OF SUCH DAMAGE.
272a5fd96fSpooka  */
282a5fd96fSpooka 
292a5fd96fSpooka #include <sys/stat.h>
302a5fd96fSpooka #include <sys/statvfs.h>
317760e6f9Skre #include <sys/time.h>
322a5fd96fSpooka 
33e8bcfa54Spooka #include <assert.h>
342a5fd96fSpooka #include <atf-c.h>
3579350377Sgson #include <ctype.h>
362a5fd96fSpooka #include <fcntl.h>
372a5fd96fSpooka #include <libgen.h>
38dccf0d48Snjoly #include <stdlib.h>
39e8bcfa54Spooka #include <string.h>
402a5fd96fSpooka #include <unistd.h>
412a5fd96fSpooka 
422a5fd96fSpooka #include <rump/rump_syscalls.h>
432a5fd96fSpooka #include <rump/rump.h>
442a5fd96fSpooka 
452a5fd96fSpooka #include "../common/h_fsmacros.h"
46c54cb811Schristos #include "h_macros.h"
472a5fd96fSpooka 
4845bfa2deSpooka #define TESTFILE "afile"
4945bfa2deSpooka 
502a5fd96fSpooka #define USES_DIRS					\
517557af29Snjoly     if (FSTYPE_SYSVBFS(tc))				\
527557af29Snjoly 	atf_tc_skip("directories not supported by file system")
532a5fd96fSpooka 
54b28267edSpooka #define USES_SYMLINKS					\
55b28267edSpooka     if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc))		\
567601b30dSnjoly 	atf_tc_skip("symlinks not supported by file system")
57b28267edSpooka 
58ae0b9cceSpooka static char *
md(char * buf,size_t buflen,const char * base,const char * tail)590ca6f6b2Schristos md(char *buf, size_t buflen, const char *base, const char *tail)
60ae0b9cceSpooka {
61ae0b9cceSpooka 
620ca6f6b2Schristos 	snprintf(buf, buflen, "%s/%s", base, tail);
63ae0b9cceSpooka 	return buf;
64ae0b9cceSpooka }
65ae0b9cceSpooka 
662a5fd96fSpooka static void
lookup_simple(const atf_tc_t * tc,const char * mountpath)672a5fd96fSpooka lookup_simple(const atf_tc_t *tc, const char *mountpath)
682a5fd96fSpooka {
692a5fd96fSpooka 	char pb[MAXPATHLEN], final[MAXPATHLEN];
702a5fd96fSpooka 	struct stat sb1, sb2;
712a5fd96fSpooka 
722a5fd96fSpooka 	strcpy(final, mountpath);
730ca6f6b2Schristos 	snprintf(pb, sizeof(pb), "%s/../%s", mountpath, basename(final));
742a5fd96fSpooka 	if (rump_sys_stat(pb, &sb1) == -1)
752a5fd96fSpooka 		atf_tc_fail_errno("stat 1");
762a5fd96fSpooka 
770ca6f6b2Schristos 	snprintf(pb, sizeof(pb), "%s/./../%s", mountpath, basename(final));
782a5fd96fSpooka 	if (rump_sys_stat(pb, &sb2) == -1)
792a5fd96fSpooka 		atf_tc_fail_errno("stat 2");
802a5fd96fSpooka 
812a5fd96fSpooka 	ATF_REQUIRE(memcmp(&sb1, &sb2, sizeof(sb1)) == 0);
822a5fd96fSpooka }
832a5fd96fSpooka 
842a5fd96fSpooka static void
lookup_complex(const atf_tc_t * tc,const char * mountpath)852a5fd96fSpooka lookup_complex(const atf_tc_t *tc, const char *mountpath)
862a5fd96fSpooka {
872a5fd96fSpooka 	char pb[MAXPATHLEN];
882a5fd96fSpooka 	struct stat sb1, sb2;
897760e6f9Skre 	struct timespec atplus1, onesec;
902a5fd96fSpooka 
912a5fd96fSpooka 	USES_DIRS;
922a5fd96fSpooka 
930ca6f6b2Schristos 	snprintf(pb, sizeof(pb), "%s/dir", mountpath);
942a5fd96fSpooka 	if (rump_sys_mkdir(pb, 0777) == -1)
952a5fd96fSpooka 		atf_tc_fail_errno("mkdir");
962a5fd96fSpooka 	if (rump_sys_stat(pb, &sb1) == -1)
972a5fd96fSpooka 		atf_tc_fail_errno("stat 1");
982a5fd96fSpooka 
990ca6f6b2Schristos 	snprintf(pb, sizeof(pb), "%s/./dir/../././dir/.", mountpath);
1002a5fd96fSpooka 	if (rump_sys_stat(pb, &sb2) == -1)
1012a5fd96fSpooka 		atf_tc_fail_errno("stat 2");
1022a5fd96fSpooka 
1037760e6f9Skre 	/*
1047760e6f9Skre 	 * The lookup is permitted to modify the access time of
1057760e6f9Skre 	 * any directories searched - such a directory is the
1067760e6f9Skre 	 * subject of this test.   Any difference should cause
107*e171cef6Sandvar 	 * the 2nd lookup atime to be >= the first, if it is ==, all is
1087760e6f9Skre 	 * OK (atime is not required to be modified by the search, or
109*e171cef6Sandvar 	 * both references may happen within the same clock tick), if the
1107760e6f9Skre 	 * 2nd lookup atime is > the first, but not "too much" greater,
1117760e6f9Skre 	 * just set it back, so the memcmp just below succeeds
1127760e6f9Skre 	 * (assuming all else is OK).
1137760e6f9Skre 	 */
1147760e6f9Skre 	onesec.tv_sec = 1;
1157760e6f9Skre 	onesec.tv_nsec = 0;
1167760e6f9Skre 	timespecadd(&sb1.st_atimespec, &onesec, &atplus1);
1177760e6f9Skre 	if (timespeccmp(&sb2.st_atimespec, &sb1.st_atimespec, >) &&
1187760e6f9Skre 	    timespeccmp(&sb2.st_atimespec, &atplus1, <))
1197760e6f9Skre 		sb2.st_atimespec = sb1.st_atimespec;
1207760e6f9Skre 
121dbd2e87eSmartin 	if (memcmp(&sb1, &sb2, sizeof(sb1)) != 0) {
122dbd2e87eSmartin 		printf("what\tsb1\t\tsb2\n");
123dbd2e87eSmartin 
124dbd2e87eSmartin #define FIELD(FN)	\
125dbd2e87eSmartin 		printf(#FN "\t%lld\t%lld\n", \
126dbd2e87eSmartin 		(long long)sb1.FN, (long long)sb2.FN)
127dbd2e87eSmartin #define TIME(FN)	\
128dbd2e87eSmartin 		printf(#FN "\t%lld.%ld\t%lld.%ld\n", \
129dbd2e87eSmartin 		(long long)sb1.FN.tv_sec, sb1.FN.tv_nsec, \
130dbd2e87eSmartin 		(long long)sb2.FN.tv_sec, sb2.FN.tv_nsec)
131dbd2e87eSmartin 
132dbd2e87eSmartin 		FIELD(st_dev);
133dbd2e87eSmartin 		FIELD(st_mode);
134dbd2e87eSmartin 		FIELD(st_ino);
135dbd2e87eSmartin 		FIELD(st_nlink);
136dbd2e87eSmartin 		FIELD(st_uid);
137dbd2e87eSmartin 		FIELD(st_gid);
138dbd2e87eSmartin 		FIELD(st_rdev);
1398c0065dbSriastradh 		TIME(st_atimespec);
1408c0065dbSriastradh 		TIME(st_mtimespec);
1418c0065dbSriastradh 		TIME(st_ctimespec);
1428c0065dbSriastradh 		TIME(st_birthtimespec);
143dbd2e87eSmartin 		FIELD(st_size);
144dbd2e87eSmartin 		FIELD(st_blocks);
145dbd2e87eSmartin 		FIELD(st_flags);
146dbd2e87eSmartin 		FIELD(st_gen);
147dbd2e87eSmartin 
148dbd2e87eSmartin #undef FIELD
149dbd2e87eSmartin #undef TIME
150dbd2e87eSmartin 
15160f3bf6aSandvar 		atf_tc_fail("stat results differ, see output for more details");
152dbd2e87eSmartin 	}
1532a5fd96fSpooka }
1542a5fd96fSpooka 
1552a5fd96fSpooka static void
dir_simple(const atf_tc_t * tc,const char * mountpath)1562a5fd96fSpooka dir_simple(const atf_tc_t *tc, const char *mountpath)
1572a5fd96fSpooka {
1582a5fd96fSpooka 	char pb[MAXPATHLEN];
1592a5fd96fSpooka 	struct stat sb;
1602a5fd96fSpooka 
1612a5fd96fSpooka 	USES_DIRS;
1622a5fd96fSpooka 
1632a5fd96fSpooka 	/* check we can create directories */
1640ca6f6b2Schristos 	snprintf(pb, sizeof(pb), "%s/dir", mountpath);
1652a5fd96fSpooka 	if (rump_sys_mkdir(pb, 0777) == -1)
1662a5fd96fSpooka 		atf_tc_fail_errno("mkdir");
1672a5fd96fSpooka 	if (rump_sys_stat(pb, &sb) == -1)
1682a5fd96fSpooka 		atf_tc_fail_errno("stat new directory");
1692a5fd96fSpooka 
170*e171cef6Sandvar 	/* check we can remove them and that it makes them unreachable */
1712a5fd96fSpooka 	if (rump_sys_rmdir(pb) == -1)
1722a5fd96fSpooka 		atf_tc_fail_errno("rmdir");
1732a5fd96fSpooka 	if (rump_sys_stat(pb, &sb) != -1 || errno != ENOENT)
1742a5fd96fSpooka 		atf_tc_fail("ENOENT expected from stat");
1752a5fd96fSpooka }
1762a5fd96fSpooka 
1772a5fd96fSpooka static void
do_dir_slash(const atf_tc_t * tc,const char * mountpath,const char * addend)1780df09db4Smartin do_dir_slash(const atf_tc_t *tc, const char *mountpath, const char *addend)
1790df09db4Smartin {
1800df09db4Smartin 	char plain[MAXPATHLEN], with_slash[MAXPATHLEN];
1810df09db4Smartin 	struct stat sb;
1820df09db4Smartin 
1830df09db4Smartin 	USES_DIRS;
1840df09db4Smartin 
1850df09db4Smartin 	/* check we can create directories with one or more / appended */
1860df09db4Smartin 	snprintf(plain, sizeof(plain), "%s/dir%s", mountpath, addend);
1870df09db4Smartin 	snprintf(with_slash, sizeof(with_slash), "%s/dir/", mountpath);
1880df09db4Smartin 	if (rump_sys_mkdir(with_slash, 0777) == -1)
1890df09db4Smartin 		atf_tc_fail_errno("mkdir");
1900df09db4Smartin 	if (rump_sys_stat(plain, &sb) == -1)
1910df09db4Smartin 		atf_tc_fail_errno("stat new directory");
1920df09db4Smartin 	if (rump_sys_rmdir(plain) == -1)
1930df09db4Smartin 		atf_tc_fail_errno("rmdir");
1940df09db4Smartin 	if (rump_sys_stat(with_slash, &sb) != -1 || errno != ENOENT)
1950df09db4Smartin 		atf_tc_fail("ENOENT expected from stat");
1960df09db4Smartin }
1970df09db4Smartin 
1980df09db4Smartin static void
dir_slash(const atf_tc_t * tc,const char * mountpath)1990df09db4Smartin dir_slash(const atf_tc_t *tc, const char *mountpath)
2000df09db4Smartin {
2010df09db4Smartin 	do_dir_slash(tc, mountpath, "/");
2020df09db4Smartin }
2030df09db4Smartin 
2040df09db4Smartin static void
dir_2slash(const atf_tc_t * tc,const char * mountpath)2050df09db4Smartin dir_2slash(const atf_tc_t *tc, const char *mountpath)
2060df09db4Smartin {
2070df09db4Smartin 	do_dir_slash(tc, mountpath, "//");
2080df09db4Smartin }
2090df09db4Smartin 
2100df09db4Smartin static void
dir_3slash(const atf_tc_t * tc,const char * mountpath)2110df09db4Smartin dir_3slash(const atf_tc_t *tc, const char *mountpath)
2120df09db4Smartin {
2130df09db4Smartin 	do_dir_slash(tc, mountpath, "///");
2140df09db4Smartin }
2150df09db4Smartin 
2160df09db4Smartin static void
dir_notempty(const atf_tc_t * tc,const char * mountpath)2172a5fd96fSpooka dir_notempty(const atf_tc_t *tc, const char *mountpath)
2182a5fd96fSpooka {
2192a5fd96fSpooka 	char pb[MAXPATHLEN], pb2[MAXPATHLEN];
2202a5fd96fSpooka 	int fd, rv;
2212a5fd96fSpooka 
2222a5fd96fSpooka 	USES_DIRS;
2232a5fd96fSpooka 
2242a5fd96fSpooka 	/* check we can create directories */
2250ca6f6b2Schristos 	snprintf(pb, sizeof(pb), "%s/dir", mountpath);
2262a5fd96fSpooka 	if (rump_sys_mkdir(pb, 0777) == -1)
2272a5fd96fSpooka 		atf_tc_fail_errno("mkdir");
2282a5fd96fSpooka 
2290ca6f6b2Schristos 	snprintf(pb2, sizeof(pb2), "%s/dir/file", mountpath);
2302a5fd96fSpooka 	fd = rump_sys_open(pb2, O_RDWR | O_CREAT, 0777);
2312a5fd96fSpooka 	if (fd == -1)
2322a5fd96fSpooka 		atf_tc_fail_errno("create file");
2332a5fd96fSpooka 	rump_sys_close(fd);
2342a5fd96fSpooka 
2352a5fd96fSpooka 	rv = rump_sys_rmdir(pb);
2362a5fd96fSpooka 	if (rv != -1 || errno != ENOTEMPTY)
23772e44f84Sandvar 		atf_tc_fail("non-empty directory removed successfully");
2382a5fd96fSpooka 
2392a5fd96fSpooka 	if (rump_sys_unlink(pb2) == -1)
2402a5fd96fSpooka 		atf_tc_fail_errno("cannot remove dir/file");
2412a5fd96fSpooka 
2422a5fd96fSpooka 	if (rump_sys_rmdir(pb) == -1)
2432a5fd96fSpooka 		atf_tc_fail_errno("remove directory");
2442a5fd96fSpooka }
2452a5fd96fSpooka 
246ae0b9cceSpooka static void
dir_rmdirdotdot(const atf_tc_t * tc,const char * mp)247878d41e6Spooka dir_rmdirdotdot(const atf_tc_t *tc, const char *mp)
248878d41e6Spooka {
249878d41e6Spooka 	char pb[MAXPATHLEN];
250878d41e6Spooka 	int xerrno;
251878d41e6Spooka 
252878d41e6Spooka 	USES_DIRS;
253878d41e6Spooka 
254878d41e6Spooka 	FSTEST_ENTER();
255878d41e6Spooka 	RL(rump_sys_mkdir("test", 0777));
256878d41e6Spooka 	RL(rump_sys_chdir("test"));
257878d41e6Spooka 
258878d41e6Spooka 	RL(rump_sys_mkdir("subtest", 0777));
259878d41e6Spooka 	RL(rump_sys_chdir("subtest"));
260878d41e6Spooka 
2610ca6f6b2Schristos 	md(pb, sizeof(pb), mp, "test/subtest");
262878d41e6Spooka 	RL(rump_sys_rmdir(pb));
2630ca6f6b2Schristos 	md(pb, sizeof(pb), mp, "test");
264878d41e6Spooka 	RL(rump_sys_rmdir(pb));
265878d41e6Spooka 
266878d41e6Spooka 	if (FSTYPE_NFS(tc))
267878d41e6Spooka 		xerrno = ESTALE;
268878d41e6Spooka 	else
269878d41e6Spooka 		xerrno = ENOENT;
270878d41e6Spooka 	ATF_REQUIRE_ERRNO(xerrno, rump_sys_chdir("..") == -1);
271878d41e6Spooka 	FSTEST_EXIT();
272878d41e6Spooka }
273878d41e6Spooka 
274878d41e6Spooka static void
checkfile(const char * path,struct stat * refp)275ae0b9cceSpooka checkfile(const char *path, struct stat *refp)
276ae0b9cceSpooka {
277ae0b9cceSpooka 	char buf[MAXPATHLEN];
278ae0b9cceSpooka 	struct stat sb;
279ae0b9cceSpooka 	static int n = 1;
280ae0b9cceSpooka 
2810ca6f6b2Schristos 	md(buf, sizeof(buf), path, "file");
282ae0b9cceSpooka 	if (rump_sys_stat(buf, &sb) == -1)
283ae0b9cceSpooka 		atf_tc_fail_errno("cannot stat file %d (%s)", n, buf);
284ae0b9cceSpooka 	if (memcmp(&sb, refp, sizeof(sb)) != 0)
285ae0b9cceSpooka 		atf_tc_fail("stat mismatch %d", n);
286ae0b9cceSpooka 	n++;
287ae0b9cceSpooka }
288ae0b9cceSpooka 
289ae0b9cceSpooka static void
rename_dir(const atf_tc_t * tc,const char * mp)290ae0b9cceSpooka rename_dir(const atf_tc_t *tc, const char *mp)
291ae0b9cceSpooka {
292ae0b9cceSpooka 	char pb1[MAXPATHLEN], pb2[MAXPATHLEN], pb3[MAXPATHLEN];
2931157445bSpooka 	struct stat ref, sb;
294ae0b9cceSpooka 
29588b6bdf1Spooka 	if (FSTYPE_RUMPFS(tc))
2967557af29Snjoly 		atf_tc_skip("rename not supported by file system");
29788b6bdf1Spooka 
298ae0b9cceSpooka 	USES_DIRS;
299ae0b9cceSpooka 
3000ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "dir1");
301ae0b9cceSpooka 	if (rump_sys_mkdir(pb1, 0777) == -1)
302ae0b9cceSpooka 		atf_tc_fail_errno("mkdir 1");
303ae0b9cceSpooka 
3040ca6f6b2Schristos 	md(pb2, sizeof(pb2), mp, "dir2");
305ae0b9cceSpooka 	if (rump_sys_mkdir(pb2, 0777) == -1)
306ae0b9cceSpooka 		atf_tc_fail_errno("mkdir 2");
3070ca6f6b2Schristos 	md(pb2, sizeof(pb2), mp, "dir2/subdir");
308ae0b9cceSpooka 	if (rump_sys_mkdir(pb2, 0777) == -1)
309ae0b9cceSpooka 		atf_tc_fail_errno("mkdir 3");
310ae0b9cceSpooka 
3110ca6f6b2Schristos 	md(pb3, sizeof(pb3), mp, "dir1/file");
312ae0b9cceSpooka 	if (rump_sys_mknod(pb3, S_IFREG | 0777, -1) == -1)
313ae0b9cceSpooka 		atf_tc_fail_errno("create file");
314ae0b9cceSpooka 	if (rump_sys_stat(pb3, &ref) == -1)
315ae0b9cceSpooka 		atf_tc_fail_errno("stat of file");
316ae0b9cceSpooka 
317ae0b9cceSpooka 	/*
318ae0b9cceSpooka 	 * First try ops which should succeed.
319ae0b9cceSpooka 	 */
320ae0b9cceSpooka 
321ae0b9cceSpooka 	/* rename within directory */
3220ca6f6b2Schristos 	md(pb3, sizeof(pb3), mp, "dir3");
323ae0b9cceSpooka 	if (rump_sys_rename(pb1, pb3) == -1)
324ae0b9cceSpooka 		atf_tc_fail_errno("rename 1");
325ae0b9cceSpooka 	checkfile(pb3, &ref);
326ae0b9cceSpooka 
327ae0b9cceSpooka 	/* rename directory onto itself (two ways, should fail) */
3280ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "dir3/.");
329ae0b9cceSpooka 	if (rump_sys_rename(pb1, pb3) != -1 || errno != EINVAL)
330ae0b9cceSpooka 		atf_tc_fail_errno("rename 2");
331ae0b9cceSpooka 	if (rump_sys_rename(pb3, pb1) != -1 || errno != EISDIR)
332ae0b9cceSpooka 		atf_tc_fail_errno("rename 3");
333ae0b9cceSpooka 
334ae0b9cceSpooka 	checkfile(pb3, &ref);
335ae0b9cceSpooka 
336ae0b9cceSpooka 	/* rename father of directory into directory */
3370ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "dir2/dir");
3380ca6f6b2Schristos 	md(pb2, sizeof(pb2), mp, "dir2");
339ae0b9cceSpooka 	if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
340ae0b9cceSpooka 		atf_tc_fail_errno("rename 4");
341ae0b9cceSpooka 
342ae0b9cceSpooka 	/* same for grandfather */
3430ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "dir2/subdir/dir2");
344ae0b9cceSpooka 	if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
345ae0b9cceSpooka 		atf_tc_fail("rename 5");
346ae0b9cceSpooka 
347ae0b9cceSpooka 	checkfile(pb3, &ref);
348ae0b9cceSpooka 
349ae0b9cceSpooka 	/* rename directory over a non-empty directory */
350ae0b9cceSpooka 	if (rump_sys_rename(pb2, pb3) != -1 || errno != ENOTEMPTY)
351ae0b9cceSpooka 		atf_tc_fail("rename 6");
352ae0b9cceSpooka 
353ae0b9cceSpooka 	/* cross-directory rename */
3540ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "dir3");
3550ca6f6b2Schristos 	md(pb2, sizeof(pb2), mp, "dir2/somedir");
356ae0b9cceSpooka 	if (rump_sys_rename(pb1, pb2) == -1)
357ae0b9cceSpooka 		atf_tc_fail_errno("rename 7");
358ae0b9cceSpooka 	checkfile(pb2, &ref);
359ae0b9cceSpooka 
360ae0b9cceSpooka 	/* move to parent directory */
3610ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "dir2/somedir/../../dir3");
362ae0b9cceSpooka 	if (rump_sys_rename(pb2, pb1) == -1)
363ae0b9cceSpooka 		atf_tc_fail_errno("rename 8");
3640ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "dir2/../dir3");
365ae0b9cceSpooka 	checkfile(pb1, &ref);
366ae0b9cceSpooka 
3671157445bSpooka 	/* atomic cross-directory rename */
3680ca6f6b2Schristos 	md(pb3, sizeof(pb3), mp, "dir2/subdir");
369ae0b9cceSpooka 	if (rump_sys_rename(pb1, pb3) == -1)
370ae0b9cceSpooka 		atf_tc_fail_errno("rename 9");
371ae0b9cceSpooka 	checkfile(pb3, &ref);
3721157445bSpooka 
3731157445bSpooka 	/* rename directory over an empty directory */
3740ca6f6b2Schristos 	md(pb1, sizeof(pb1), mp, "parent");
3750ca6f6b2Schristos 	md(pb2, sizeof(pb2), mp, "parent/dir1");
3760ca6f6b2Schristos 	md(pb3, sizeof(pb3), mp, "parent/dir2");
3771157445bSpooka 	RL(rump_sys_mkdir(pb1, 0777));
3781157445bSpooka 	RL(rump_sys_mkdir(pb2, 0777));
3791157445bSpooka 	RL(rump_sys_mkdir(pb3, 0777));
3801157445bSpooka 	RL(rump_sys_rename(pb2, pb3));
3811157445bSpooka 
3821157445bSpooka 	RL(rump_sys_stat(pb1, &sb));
383d8c44cecShannken 	if (! FSTYPE_MSDOS(tc))
3841157445bSpooka 		ATF_CHECK_EQ(sb.st_nlink, 3);
3851157445bSpooka 	RL(rump_sys_rmdir(pb3));
3861157445bSpooka 	RL(rump_sys_rmdir(pb1));
387ae0b9cceSpooka }
388ae0b9cceSpooka 
389ae0b9cceSpooka static void
rename_dotdot(const atf_tc_t * tc,const char * mp)390ae0b9cceSpooka rename_dotdot(const atf_tc_t *tc, const char *mp)
391ae0b9cceSpooka {
392ae0b9cceSpooka 
39388b6bdf1Spooka 	if (FSTYPE_RUMPFS(tc))
3947557af29Snjoly 		atf_tc_skip("rename not supported by file system");
39588b6bdf1Spooka 
396ae0b9cceSpooka 	USES_DIRS;
397ae0b9cceSpooka 
398ae0b9cceSpooka 	if (rump_sys_chdir(mp) == -1)
399ae0b9cceSpooka 		atf_tc_fail_errno("chdir mountpoint");
400ae0b9cceSpooka 
401ae0b9cceSpooka 	if (rump_sys_mkdir("dir1", 0777) == -1)
402ae0b9cceSpooka 		atf_tc_fail_errno("mkdir 1");
403ae0b9cceSpooka 	if (rump_sys_mkdir("dir2", 0777) == -1)
404ae0b9cceSpooka 		atf_tc_fail_errno("mkdir 2");
405ae0b9cceSpooka 
406ae0b9cceSpooka 	if (rump_sys_rename("dir1", "dir1/..") != -1 || errno != EINVAL)
407ae0b9cceSpooka 		atf_tc_fail_errno("self-dotdot to");
408ae0b9cceSpooka 
409ae0b9cceSpooka 	if (rump_sys_rename("dir1/..", "sometarget") != -1 || errno != EINVAL)
410ae0b9cceSpooka 		atf_tc_fail_errno("self-dotdot from");
411ae0b9cceSpooka 
412ae0b9cceSpooka 	if (rump_sys_rename("dir1", "dir2/..") != -1 || errno != EINVAL)
413ae0b9cceSpooka 		atf_tc_fail("other-dotdot");
414ae0b9cceSpooka 
415ae0b9cceSpooka 	rump_sys_chdir("/");
416ae0b9cceSpooka }
417ae0b9cceSpooka 
418ae0b9cceSpooka static void
rename_reg_nodir(const atf_tc_t * tc,const char * mp)419ae0b9cceSpooka rename_reg_nodir(const atf_tc_t *tc, const char *mp)
420ae0b9cceSpooka {
421ae0b9cceSpooka 	bool haslinks;
422ae0b9cceSpooka 	struct stat sb;
423d56fcfc9Schristos 	ino_t f1ino;
424ae0b9cceSpooka 
42588b6bdf1Spooka 	if (FSTYPE_RUMPFS(tc))
4267557af29Snjoly 		atf_tc_skip("rename not supported by file system");
42788b6bdf1Spooka 
428ae0b9cceSpooka 	if (rump_sys_chdir(mp) == -1)
429ae0b9cceSpooka 		atf_tc_fail_errno("chdir mountpoint");
430ae0b9cceSpooka 
431ae0b9cceSpooka 	if (FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))
432ae0b9cceSpooka 		haslinks = false;
433ae0b9cceSpooka 	else
434ae0b9cceSpooka 		haslinks = true;
435ae0b9cceSpooka 
436ae0b9cceSpooka 	if (rump_sys_mknod("file1", S_IFREG | 0777, -1) == -1)
437ae0b9cceSpooka 		atf_tc_fail_errno("create file");
438ae0b9cceSpooka 	if (rump_sys_mknod("file2", S_IFREG | 0777, -1) == -1)
439ae0b9cceSpooka 		atf_tc_fail_errno("create file");
440ae0b9cceSpooka 
441ae0b9cceSpooka 	if (rump_sys_stat("file1", &sb) == -1)
442ae0b9cceSpooka 		atf_tc_fail_errno("stat");
443ae0b9cceSpooka 	f1ino = sb.st_ino;
444ae0b9cceSpooka 
445ae0b9cceSpooka 	if (haslinks) {
446ae0b9cceSpooka 		if (rump_sys_link("file1", "file_link") == -1)
447ae0b9cceSpooka 			atf_tc_fail_errno("link");
448ae0b9cceSpooka 		if (rump_sys_stat("file_link", &sb) == -1)
449ae0b9cceSpooka 			atf_tc_fail_errno("stat");
450ae0b9cceSpooka 		ATF_REQUIRE_EQ(sb.st_ino, f1ino);
451ae0b9cceSpooka 		ATF_REQUIRE_EQ(sb.st_nlink, 2);
452ae0b9cceSpooka 	}
453ae0b9cceSpooka 
454ae0b9cceSpooka 	if (rump_sys_stat("file2", &sb) == -1)
455ae0b9cceSpooka 		atf_tc_fail_errno("stat");
456ae0b9cceSpooka 
457ae0b9cceSpooka 	if (rump_sys_rename("file1", "file3") == -1)
458ae0b9cceSpooka 		atf_tc_fail_errno("rename 1");
459ae0b9cceSpooka 	if (rump_sys_stat("file3", &sb) == -1)
460ae0b9cceSpooka 		atf_tc_fail_errno("stat 1");
461ae0b9cceSpooka 	if (haslinks) {
462ae0b9cceSpooka 		ATF_REQUIRE_EQ(sb.st_ino, f1ino);
463ae0b9cceSpooka 	}
464ae0b9cceSpooka 	if (rump_sys_stat("file1", &sb) != -1 || errno != ENOENT)
465ae0b9cceSpooka 		atf_tc_fail_errno("source 1");
466ae0b9cceSpooka 
467ae0b9cceSpooka 	if (rump_sys_rename("file3", "file2") == -1)
468ae0b9cceSpooka 		atf_tc_fail_errno("rename 2");
469ae0b9cceSpooka 	if (rump_sys_stat("file2", &sb) == -1)
470ae0b9cceSpooka 		atf_tc_fail_errno("stat 2");
471ae0b9cceSpooka 	if (haslinks) {
472ae0b9cceSpooka 		ATF_REQUIRE_EQ(sb.st_ino, f1ino);
473ae0b9cceSpooka 	}
474ae0b9cceSpooka 
475ae0b9cceSpooka 	if (rump_sys_stat("file3", &sb) != -1 || errno != ENOENT)
476ae0b9cceSpooka 		atf_tc_fail_errno("source 2");
477ae0b9cceSpooka 
478ae0b9cceSpooka 	if (haslinks) {
479ae0b9cceSpooka 		if (rump_sys_rename("file2", "file_link") == -1)
480ae0b9cceSpooka 			atf_tc_fail_errno("rename hardlink");
481ae0b9cceSpooka 		if (rump_sys_stat("file2", &sb) != -1 || errno != ENOENT)
482ae0b9cceSpooka 			atf_tc_fail_errno("source 3");
483ae0b9cceSpooka 		if (rump_sys_stat("file_link", &sb) == -1)
484ae0b9cceSpooka 			atf_tc_fail_errno("stat 2");
485ae0b9cceSpooka 		ATF_REQUIRE_EQ(sb.st_ino, f1ino);
486ae0b9cceSpooka 		ATF_REQUIRE_EQ(sb.st_nlink, 1);
487ae0b9cceSpooka 	}
488ae0b9cceSpooka 
4891fe37e8eSnjoly 	ATF_CHECK_ERRNO(EFAULT, rump_sys_rename("file2", NULL) == -1);
4901fe37e8eSnjoly 	ATF_CHECK_ERRNO(EFAULT, rump_sys_rename(NULL, "file2") == -1);
4911fe37e8eSnjoly 
492ae0b9cceSpooka 	rump_sys_chdir("/");
493ae0b9cceSpooka }
494ae0b9cceSpooka 
4958b742e7aSpooka /* PR kern/50607 */
496dccf0d48Snjoly static void
create_many(const atf_tc_t * tc,const char * mp)497596d7c22Spooka create_many(const atf_tc_t *tc, const char *mp)
498596d7c22Spooka {
499596d7c22Spooka 	char buf[64];
500596d7c22Spooka 	int nfiles = 2324; /* #Nancy */
501596d7c22Spooka 	int i;
502596d7c22Spooka 
503596d7c22Spooka 	/* takes forever with many files */
504596d7c22Spooka 	if (FSTYPE_MSDOS(tc))
505596d7c22Spooka 		nfiles /= 4;
506596d7c22Spooka 
507596d7c22Spooka 	RL(rump_sys_chdir(mp));
508596d7c22Spooka 
509419929efSpooka 	if (FSTYPE_SYSVBFS(tc)) {
510419929efSpooka 		/* fs doesn't support many files or subdirectories */
511419929efSpooka 		nfiles = 5;
512419929efSpooka 	} else {
513596d7c22Spooka 		/* msdosfs doesn't like many entries in the root directory */
514596d7c22Spooka 		RL(rump_sys_mkdir("subdir", 0777));
515596d7c22Spooka 		RL(rump_sys_chdir("subdir"));
516419929efSpooka 	}
517596d7c22Spooka 
518596d7c22Spooka 	/* create them */
51910c4a4e0Spooka #define TESTFN "testfile"
520596d7c22Spooka 	for (i = 0; i < nfiles; i++) {
521596d7c22Spooka 		int fd;
522596d7c22Spooka 
5230ca6f6b2Schristos 		snprintf(buf, sizeof(buf), TESTFN "%d", i);
524596d7c22Spooka 		RL(fd = rump_sys_open(buf, O_RDWR|O_CREAT|O_EXCL, 0666));
525596d7c22Spooka 		RL(rump_sys_close(fd));
526596d7c22Spooka 	}
527596d7c22Spooka 
528596d7c22Spooka 	/* wipe them out */
529596d7c22Spooka 	for (i = 0; i < nfiles; i++) {
5300ca6f6b2Schristos 		snprintf(buf, sizeof(buf), TESTFN "%d", i);
5310ca6f6b2Schristos 		RLF(rump_sys_unlink(buf), "%s", buf);
532596d7c22Spooka 	}
533596d7c22Spooka #undef TESTFN
534596d7c22Spooka 
535596d7c22Spooka 	rump_sys_chdir("/");
536596d7c22Spooka }
537596d7c22Spooka 
53879350377Sgson /*
53979350377Sgson  * Test creating files with one-character names using all possible
54079350377Sgson  * character values.  Failures to create the file are ignored as the
54179350377Sgson  * characters allowed in file names vary by file system, but at least
54279350377Sgson  * we can check that the fs does not crash, and if the file is
54379350377Sgson  * successfully created, unlinking it should also succeed.
54479350377Sgson  */
54579350377Sgson static void
create_nonalphanum(const atf_tc_t * tc,const char * mp)54679350377Sgson create_nonalphanum(const atf_tc_t *tc, const char *mp)
54779350377Sgson {
54879350377Sgson 	char buf[64];
54979350377Sgson 	int i;
55079350377Sgson 
55179350377Sgson 	RL(rump_sys_chdir(mp));
55279350377Sgson 
55379350377Sgson 	for (i = 0; i < 256; i++) {
55479350377Sgson 		int fd;
5550ca6f6b2Schristos 		snprintf(buf, sizeof(buf), "%c", i);
55679350377Sgson 		fd = rump_sys_open(buf, O_RDWR|O_CREAT|O_EXCL, 0666);
55779350377Sgson 		if (fd == -1)
55879350377Sgson 			continue;
5590ca6f6b2Schristos 		RLF(rump_sys_close(fd), "%d", fd);
5600ca6f6b2Schristos 		RLF(rump_sys_unlink(buf), "%s", buf);
56179350377Sgson 	}
56279350377Sgson 	printf("\n");
56379350377Sgson 
56479350377Sgson 	rump_sys_chdir("/");
56579350377Sgson }
56679350377Sgson 
567596d7c22Spooka static void
create_nametoolong(const atf_tc_t * tc,const char * mp)568dccf0d48Snjoly create_nametoolong(const atf_tc_t *tc, const char *mp)
569dccf0d48Snjoly {
570dccf0d48Snjoly 	char *name;
571dccf0d48Snjoly 	int fd;
572dccf0d48Snjoly 	long val;
573dccf0d48Snjoly 	size_t len;
574dccf0d48Snjoly 
575dccf0d48Snjoly 	if (rump_sys_chdir(mp) == -1)
576dccf0d48Snjoly 		atf_tc_fail_errno("chdir mountpoint");
577dccf0d48Snjoly 
578dccf0d48Snjoly 	val = rump_sys_pathconf(".", _PC_NAME_MAX);
579dccf0d48Snjoly 	if (val == -1)
580dccf0d48Snjoly 		atf_tc_fail_errno("pathconf");
581dccf0d48Snjoly 
582dccf0d48Snjoly 	len = val + 1;
583dccf0d48Snjoly 	name = malloc(len+1);
584dccf0d48Snjoly 	if (name == NULL)
585dccf0d48Snjoly 		atf_tc_fail_errno("malloc");
586dccf0d48Snjoly 
587dccf0d48Snjoly 	memset(name, 'a', len);
588dccf0d48Snjoly 	*(name+len) = '\0';
589dccf0d48Snjoly 
590dccf0d48Snjoly 	val = rump_sys_pathconf(".", _PC_NO_TRUNC);
591dccf0d48Snjoly 	if (val == -1)
592dccf0d48Snjoly 		atf_tc_fail_errno("pathconf");
593dccf0d48Snjoly 
594dccf0d48Snjoly 	fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666);
595dccf0d48Snjoly 	if (val != 0 && (fd != -1 || errno != ENAMETOOLONG))
596dccf0d48Snjoly 		atf_tc_fail_errno("open");
597dccf0d48Snjoly 
598dccf0d48Snjoly 	if (val == 0 && rump_sys_close(fd) == -1)
599dccf0d48Snjoly 		atf_tc_fail_errno("close");
600dccf0d48Snjoly 	if (val == 0 && rump_sys_unlink(name) == -1)
601dccf0d48Snjoly 		atf_tc_fail_errno("unlink");
602dccf0d48Snjoly 
603dccf0d48Snjoly 	free(name);
604dccf0d48Snjoly 
605dccf0d48Snjoly 	rump_sys_chdir("/");
606dccf0d48Snjoly }
607dccf0d48Snjoly 
608dccf0d48Snjoly static void
create_exist(const atf_tc_t * tc,const char * mp)6090aabb924Syamt create_exist(const atf_tc_t *tc, const char *mp)
6100aabb924Syamt {
6110aabb924Syamt 	const char *name = "hoge";
6120aabb924Syamt 	int fd;
6130aabb924Syamt 
6140aabb924Syamt 	RL(rump_sys_chdir(mp));
6150aabb924Syamt 	RL(fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666));
6160aabb924Syamt 	RL(rump_sys_close(fd));
6170aabb924Syamt 	RL(rump_sys_unlink(name));
6180aabb924Syamt 	RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
6190aabb924Syamt 	RL(rump_sys_close(fd));
6200aabb924Syamt 	RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
6210aabb924Syamt 	RL(rump_sys_close(fd));
6220aabb924Syamt 	ATF_REQUIRE_ERRNO(EEXIST,
6230aabb924Syamt 	    (fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666)));
6240aabb924Syamt 	RL(rump_sys_unlink(name));
6250aabb924Syamt 	RL(rump_sys_chdir("/"));
6260aabb924Syamt }
6270aabb924Syamt 
6280aabb924Syamt static void
rename_nametoolong(const atf_tc_t * tc,const char * mp)629dccf0d48Snjoly rename_nametoolong(const atf_tc_t *tc, const char *mp)
630dccf0d48Snjoly {
631dccf0d48Snjoly 	char *name;
632dccf0d48Snjoly 	int res, fd;
633dccf0d48Snjoly 	long val;
634dccf0d48Snjoly 	size_t len;
635dccf0d48Snjoly 
63688b6bdf1Spooka 	if (FSTYPE_RUMPFS(tc))
6377557af29Snjoly 		atf_tc_skip("rename not supported by file system");
63888b6bdf1Spooka 
639dccf0d48Snjoly 	if (rump_sys_chdir(mp) == -1)
640dccf0d48Snjoly 		atf_tc_fail_errno("chdir mountpoint");
641dccf0d48Snjoly 
642dccf0d48Snjoly 	val = rump_sys_pathconf(".", _PC_NAME_MAX);
643dccf0d48Snjoly 	if (val == -1)
644dccf0d48Snjoly 		atf_tc_fail_errno("pathconf");
645dccf0d48Snjoly 
646dccf0d48Snjoly 	len = val + 1;
647dccf0d48Snjoly 	name = malloc(len+1);
648dccf0d48Snjoly 	if (name == NULL)
649dccf0d48Snjoly 		atf_tc_fail_errno("malloc");
650dccf0d48Snjoly 
651dccf0d48Snjoly 	memset(name, 'a', len);
652dccf0d48Snjoly 	*(name+len) = '\0';
653dccf0d48Snjoly 
654dccf0d48Snjoly 	fd = rump_sys_open("dummy", O_RDWR|O_CREAT, 0666);
655dccf0d48Snjoly 	if (fd == -1)
656dccf0d48Snjoly 		atf_tc_fail_errno("open");
657dccf0d48Snjoly 	if (rump_sys_close(fd) == -1)
658dccf0d48Snjoly 		atf_tc_fail_errno("close");
659dccf0d48Snjoly 
660dccf0d48Snjoly 	val = rump_sys_pathconf(".", _PC_NO_TRUNC);
661dccf0d48Snjoly 	if (val == -1)
662dccf0d48Snjoly 		atf_tc_fail_errno("pathconf");
663dccf0d48Snjoly 
664dccf0d48Snjoly 	res = rump_sys_rename("dummy", name);
665dccf0d48Snjoly 	if (val != 0 && (res != -1 || errno != ENAMETOOLONG))
666dccf0d48Snjoly 		atf_tc_fail_errno("rename");
667dccf0d48Snjoly 
668dccf0d48Snjoly 	if (val == 0 && rump_sys_unlink(name) == -1)
669dccf0d48Snjoly 		atf_tc_fail_errno("unlink");
670dccf0d48Snjoly 
671dccf0d48Snjoly 	free(name);
672dccf0d48Snjoly 
673dccf0d48Snjoly 	rump_sys_chdir("/");
674dccf0d48Snjoly }
675dccf0d48Snjoly 
676dec58decSgson /*
677dec58decSgson  * Test creating a symlink whose length is "len" bytes, not including
678dec58decSgson  * the terminating NUL.
679dec58decSgson  */
680b28267edSpooka static void
symlink_len(const atf_tc_t * tc,const char * mp,size_t len)681dec58decSgson symlink_len(const atf_tc_t *tc, const char *mp, size_t len)
682b28267edSpooka {
683dec58decSgson 	char *buf;
684dec58decSgson 	int r;
685b28267edSpooka 
686b28267edSpooka 	USES_SYMLINKS;
687b28267edSpooka 
68803f6cc70Schristos 	RLF(rump_sys_chdir(mp), "%s", mp);
689192b53ecSpooka 
690dec58decSgson 	buf = malloc(len + 1);
691dec58decSgson 	ATF_REQUIRE(buf);
692dec58decSgson 	memset(buf, 'a', len);
693dec58decSgson 	buf[len] = '\0';
694dec58decSgson 	r = rump_sys_symlink(buf, "afile");
695dec58decSgson 	if (r == -1) {
696dec58decSgson 		ATF_REQUIRE_ERRNO(ENAMETOOLONG, r);
697dec58decSgson 	} else {
698dec58decSgson 		RL(rump_sys_unlink("afile"));
699dec58decSgson 	}
700dec58decSgson 	free(buf);
701dec58decSgson 
702b28267edSpooka 	RL(rump_sys_chdir("/"));
703b28267edSpooka }
704b28267edSpooka 
70545bfa2deSpooka static void
symlink_zerolen(const atf_tc_t * tc,const char * mp)706dec58decSgson symlink_zerolen(const atf_tc_t *tc, const char *mp)
707dec58decSgson {
708dec58decSgson 	symlink_len(tc, mp, 0);
709dec58decSgson }
710dec58decSgson 
711dec58decSgson static void
symlink_long(const atf_tc_t * tc,const char * mp)712dec58decSgson symlink_long(const atf_tc_t *tc, const char *mp)
713dec58decSgson {
714dec58decSgson 	/*
715dec58decSgson 	 * Test lengths close to powers of two, as those are likely
716dec58decSgson 	 * to be edge cases.
717dec58decSgson 	 */
718dec58decSgson 	size_t len;
719dec58decSgson 	int fuzz;
720dec58decSgson 	for (len = 2; len <= 65536; len *= 2) {
721dec58decSgson 		for (fuzz = -1; fuzz <= 1; fuzz++) {
722dec58decSgson 			symlink_len(tc, mp, len + fuzz);
723dec58decSgson 		}
724dec58decSgson 	}
725dec58decSgson }
726dec58decSgson 
727dec58decSgson static void
symlink_root(const atf_tc_t * tc,const char * mp)7280ed1cdc7Sriastradh symlink_root(const atf_tc_t *tc, const char *mp)
7290ed1cdc7Sriastradh {
7300ed1cdc7Sriastradh 
7310ed1cdc7Sriastradh 	USES_SYMLINKS;
7320ed1cdc7Sriastradh 
7330ed1cdc7Sriastradh 	RL(rump_sys_chdir(mp));
7340ed1cdc7Sriastradh 	RL(rump_sys_symlink("/", "foo"));
7350ed1cdc7Sriastradh 	RL(rump_sys_chdir("foo"));
7360ed1cdc7Sriastradh }
7370ed1cdc7Sriastradh 
7380ed1cdc7Sriastradh static void
attrs(const atf_tc_t * tc,const char * mp)73945bfa2deSpooka attrs(const atf_tc_t *tc, const char *mp)
74045bfa2deSpooka {
74145bfa2deSpooka 	struct stat sb, sb2;
74245bfa2deSpooka 	struct timeval tv[2];
74345bfa2deSpooka 	int fd;
74445bfa2deSpooka 
74545bfa2deSpooka 	FSTEST_ENTER();
74645bfa2deSpooka 	RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
74745bfa2deSpooka 	RL(rump_sys_close(fd));
74845bfa2deSpooka 	RL(rump_sys_stat(TESTFILE, &sb));
74945bfa2deSpooka 	if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
75045bfa2deSpooka 		RL(rump_sys_chown(TESTFILE, 1, 2));
75145bfa2deSpooka 		sb.st_uid = 1;
75245bfa2deSpooka 		sb.st_gid = 2;
75345bfa2deSpooka 		RL(rump_sys_chmod(TESTFILE, 0123));
75445bfa2deSpooka 		sb.st_mode = (sb.st_mode & ~ACCESSPERMS) | 0123;
75545bfa2deSpooka 	}
75645bfa2deSpooka 
75745bfa2deSpooka 	tv[0].tv_sec = 1000000000; /* need something >1980 for msdosfs */
75845bfa2deSpooka 	tv[0].tv_usec = 1;
75945bfa2deSpooka 	tv[1].tv_sec = 1000000002; /* need even seconds for msdosfs */
76045bfa2deSpooka 	tv[1].tv_usec = 3;
76145bfa2deSpooka 	RL(rump_sys_utimes(TESTFILE, tv));
76245bfa2deSpooka 	RL(rump_sys_utimes(TESTFILE, tv)); /* XXX: utimes & birthtime */
76345bfa2deSpooka 	sb.st_atimespec.tv_sec = 1000000000;
76445bfa2deSpooka 	sb.st_atimespec.tv_nsec = 1000;
76545bfa2deSpooka 	sb.st_mtimespec.tv_sec = 1000000002;
76645bfa2deSpooka 	sb.st_mtimespec.tv_nsec = 3000;
76745bfa2deSpooka 
76845bfa2deSpooka 	RL(rump_sys_stat(TESTFILE, &sb2));
76945bfa2deSpooka #define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a)
77045bfa2deSpooka 	if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
77145bfa2deSpooka 		CHECK(st_uid);
77245bfa2deSpooka 		CHECK(st_gid);
77345bfa2deSpooka 		CHECK(st_mode);
77445bfa2deSpooka 	}
77545bfa2deSpooka 	if (!FSTYPE_MSDOS(tc)) {
77645bfa2deSpooka 		/* msdosfs has only access date, not time */
77745bfa2deSpooka 		CHECK(st_atimespec.tv_sec);
77845bfa2deSpooka 	}
77945bfa2deSpooka 	CHECK(st_mtimespec.tv_sec);
780154297fdSuch 	if (!(FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc) ||
781154297fdSuch 	      FSTYPE_SYSVBFS(tc) || FSTYPE_V7FS(tc))) {
78245bfa2deSpooka 		CHECK(st_atimespec.tv_nsec);
78345bfa2deSpooka 		CHECK(st_mtimespec.tv_nsec);
78445bfa2deSpooka 	}
78545bfa2deSpooka #undef  CHECK
78645bfa2deSpooka 
78745bfa2deSpooka 	FSTEST_EXIT();
78845bfa2deSpooka }
78945bfa2deSpooka 
790eea5c398Skefren static void
fcntl_lock(const atf_tc_t * tc,const char * mp)791eea5c398Skefren fcntl_lock(const atf_tc_t *tc, const char *mp)
792eea5c398Skefren {
793eea5c398Skefren 	int fd, fd2;
794eea5c398Skefren 	struct flock l;
795eea5c398Skefren 	struct lwp *lwp1, *lwp2;
796eea5c398Skefren 
797eea5c398Skefren 	FSTEST_ENTER();
798eea5c398Skefren 	l.l_pid = 0;
799eea5c398Skefren 	l.l_start = l.l_len = 1024;
800eea5c398Skefren 	l.l_type = F_RDLCK | F_WRLCK;
801eea5c398Skefren 	l.l_whence = SEEK_END;
802eea5c398Skefren 
803eea5c398Skefren 	lwp1 = rump_pub_lwproc_curlwp();
804eea5c398Skefren 	RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
805eea5c398Skefren 	RL(rump_sys_ftruncate(fd, 8192));
806eea5c398Skefren 
807eea5c398Skefren 	RL(rump_sys_fcntl(fd, F_SETLK, &l));
808eea5c398Skefren 
809eea5c398Skefren 	/* Next, we fork and try to lock the same area */
810eea5c398Skefren 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
811eea5c398Skefren 	lwp2 = rump_pub_lwproc_curlwp();
812eea5c398Skefren 	RL(fd2 = rump_sys_open(TESTFILE, O_RDWR, 0));
813eea5c398Skefren 	ATF_REQUIRE_ERRNO(EAGAIN, rump_sys_fcntl(fd2, F_SETLK, &l));
814eea5c398Skefren 
815eea5c398Skefren 	/* Switch back and unlock... */
816eea5c398Skefren 	rump_pub_lwproc_switch(lwp1);
817eea5c398Skefren 	l.l_type = F_UNLCK;
818eea5c398Skefren 	RL(rump_sys_fcntl(fd, F_SETLK, &l));
819eea5c398Skefren 
820eea5c398Skefren 	/* ... and try to lock again */
821eea5c398Skefren 	rump_pub_lwproc_switch(lwp2);
822eea5c398Skefren 	l.l_type = F_RDLCK | F_WRLCK;
823eea5c398Skefren 	RL(rump_sys_fcntl(fd2, F_SETLK, &l));
824eea5c398Skefren 
825eea5c398Skefren 	RL(rump_sys_close(fd2));
826eea5c398Skefren 	rump_pub_lwproc_releaselwp();
827eea5c398Skefren 
828eea5c398Skefren 	RL(rump_sys_close(fd));
829eea5c398Skefren 
830eea5c398Skefren 	FSTEST_EXIT();
831eea5c398Skefren }
832eea5c398Skefren 
833e8bcfa54Spooka static int
flock_compare(const void * p,const void * q)834e8bcfa54Spooka flock_compare(const void *p, const void *q)
835e8bcfa54Spooka {
836e8bcfa54Spooka 	int a = ((const struct flock *)p)->l_start;
837e8bcfa54Spooka 	int b = ((const struct flock *)q)->l_start;
838e8bcfa54Spooka 	return a < b ? -1 : (a > b ? 1 : 0);
839e8bcfa54Spooka }
840e8bcfa54Spooka 
841f60611afSalnsn /*
842f60611afSalnsn  * Find all locks set by fcntl_getlock_pids test
843f60611afSalnsn  * using GETLK for a range [start, start+end], and,
844f60611afSalnsn  * if there is a blocking lock, recursively find
845f60611afSalnsn  * all locks to the left (toward the beginning of
846f60611afSalnsn  * a file) and to the right of the lock.
847f60611afSalnsn  * The function also understands "until end of file"
848f60611afSalnsn  * convention when len==0.
849f60611afSalnsn  */
850f60611afSalnsn static unsigned int
fcntl_getlocks(int fildes,off_t start,off_t len,struct flock * lock,struct flock * end)851f60611afSalnsn fcntl_getlocks(int fildes, off_t start, off_t len,
852f60611afSalnsn     struct flock *lock, struct flock *end)
853f60611afSalnsn {
854f60611afSalnsn 	unsigned int rv = 0;
855f60611afSalnsn 	const struct flock l = { start, len, 0, F_RDLCK, SEEK_SET };
856f60611afSalnsn 
857f60611afSalnsn 	if (lock == end)
858f60611afSalnsn 		return rv;
859f60611afSalnsn 
860f60611afSalnsn 	RL(rump_sys_fcntl(fildes, F_GETLK, &l));
861f60611afSalnsn 
862f60611afSalnsn 	if (l.l_type == F_UNLCK)
863f60611afSalnsn 		return rv;
864f60611afSalnsn 
865f60611afSalnsn 	*lock++ = l;
866f60611afSalnsn 	rv += 1;
867f60611afSalnsn 
868f60611afSalnsn 	ATF_REQUIRE(l.l_whence == SEEK_SET);
869f60611afSalnsn 
870f60611afSalnsn 	if (l.l_start > start) {
871f60611afSalnsn 		unsigned int n =
872f60611afSalnsn 		    fcntl_getlocks(fildes, start, l.l_start - start, lock, end);
873f60611afSalnsn 		rv += n;
874f60611afSalnsn 		lock += n;
875f60611afSalnsn 		if (lock == end)
876f60611afSalnsn 			return rv;
877f60611afSalnsn 	}
878f60611afSalnsn 
879f60611afSalnsn 	if (l.l_len == 0) /* does l spans until the end? */
880f60611afSalnsn 		return rv;
881f60611afSalnsn 
882f60611afSalnsn 	if (len == 0) /* are we looking for locks until the end? */ {
883f60611afSalnsn 		rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end);
884f60611afSalnsn 	} else if (l.l_start + l.l_len < start + len) {
885f60611afSalnsn 		len -= l.l_start + l.l_len - start;
886f60611afSalnsn 		rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end);
887f60611afSalnsn 	}
888f60611afSalnsn 
889f60611afSalnsn 	return rv;
890f60611afSalnsn }
891f60611afSalnsn 
892e8bcfa54Spooka static void
fcntl_getlock_pids(const atf_tc_t * tc,const char * mp)893e8bcfa54Spooka fcntl_getlock_pids(const atf_tc_t *tc, const char *mp)
894e8bcfa54Spooka {
895e8bcfa54Spooka 	/* test non-overlaping ranges */
896e8bcfa54Spooka 	struct flock expect[4];
897e8bcfa54Spooka 	const struct flock lock[4] = {
898e8bcfa54Spooka 		{ 0, 2, 0, F_WRLCK, SEEK_SET },
899e8bcfa54Spooka 		{ 2, 1, 0, F_WRLCK, SEEK_SET },
900e8bcfa54Spooka 		{ 7, 5, 0, F_WRLCK, SEEK_SET },
901e8bcfa54Spooka 		{ 4, 3, 0, F_WRLCK, SEEK_SET },
902e8bcfa54Spooka 	};
903e8bcfa54Spooka 
904f60611afSalnsn     /* Add extra element to make sure recursion does't stop at array end */
905f60611afSalnsn 	struct flock result[5];
906f60611afSalnsn 
907f60611afSalnsn 	/* Add 5th process */
908f60611afSalnsn 	int fd[5];
909f60611afSalnsn 	pid_t pid[5];
910f60611afSalnsn 	struct lwp *lwp[5];
911e8bcfa54Spooka 
912e8bcfa54Spooka 	unsigned int i, j;
913e8bcfa54Spooka 	const off_t sz = 8192;
914e8bcfa54Spooka 	int omode  = 0755;
915e8bcfa54Spooka 	int oflags = O_RDWR | O_CREAT;
916e8bcfa54Spooka 
917e8bcfa54Spooka 	memcpy(expect, lock, sizeof(lock));
918e8bcfa54Spooka 
919e8bcfa54Spooka 	FSTEST_ENTER();
920e8bcfa54Spooka 
921e8bcfa54Spooka 	/*
922e8bcfa54Spooka 	 * First, we create 4 processes and let each lock a range of the
923e8bcfa54Spooka 	 * file.  Note that the third and fourth processes lock in
924e8bcfa54Spooka 	 * "reverse" order, i.e. the greater pid locks a range before
925e8bcfa54Spooka 	 * the lesser pid.
926f60611afSalnsn 	 * Then, we create 5th process which doesn't lock anything.
927e8bcfa54Spooka 	 */
928e8bcfa54Spooka 	for (i = 0; i < __arraycount(lwp); i++) {
929e8bcfa54Spooka 		RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
930e8bcfa54Spooka 
931e8bcfa54Spooka 		lwp[i] = rump_pub_lwproc_curlwp();
932f60611afSalnsn 		pid[i] = rump_sys_getpid();
933e8bcfa54Spooka 
934e8bcfa54Spooka 		RL(fd[i] = rump_sys_open(TESTFILE, oflags, omode));
935e8bcfa54Spooka 		oflags = O_RDWR;
936e8bcfa54Spooka 		omode  = 0;
937e8bcfa54Spooka 
938e8bcfa54Spooka 		RL(rump_sys_ftruncate(fd[i], sz));
939f60611afSalnsn 
940f60611afSalnsn 		if (i < __arraycount(lock)) {
941e8bcfa54Spooka 			RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i]));
942f60611afSalnsn 			expect[i].l_pid = pid[i];
943f60611afSalnsn 		}
944e8bcfa54Spooka 	}
945e8bcfa54Spooka 
946f60611afSalnsn 	qsort(expect, __arraycount(expect), sizeof(expect[0]), &flock_compare);
947f60611afSalnsn 
948e8bcfa54Spooka 	/*
949f60611afSalnsn 	 * In the context of each process, recursively find all locks
950f60611afSalnsn 	 * that would block the current process. Processes 1-4 don't
951f60611afSalnsn 	 * see their own lock, we insert it to simplify checks.
952f60611afSalnsn 	 * Process 5 sees all 4 locks.
953e8bcfa54Spooka 	 */
954e8bcfa54Spooka 	for (i = 0; i < __arraycount(lwp); i++) {
955f60611afSalnsn 		unsigned int nlocks;
956f60611afSalnsn 
957e8bcfa54Spooka 		rump_pub_lwproc_switch(lwp[i]);
958e8bcfa54Spooka 
959f60611afSalnsn 		memset(result, 0, sizeof(result));
960f60611afSalnsn 		nlocks = fcntl_getlocks(fd[i], 0, sz,
961f60611afSalnsn 		    result, result + __arraycount(result));
962e8bcfa54Spooka 
963f60611afSalnsn 		if (i < __arraycount(lock)) {
964f60611afSalnsn 			ATF_REQUIRE(nlocks < __arraycount(result));
965f60611afSalnsn 			result[nlocks] = lock[i];
966f60611afSalnsn 			result[nlocks].l_pid = pid[i];
967f60611afSalnsn 			nlocks++;
968e8bcfa54Spooka 		}
969f60611afSalnsn 
970f60611afSalnsn 		ATF_CHECK_EQ(nlocks, __arraycount(expect));
971f60611afSalnsn 
972f60611afSalnsn 		qsort(result, nlocks, sizeof(result[0]), &flock_compare);
973f60611afSalnsn 
974f60611afSalnsn 		for (j = 0; j < nlocks; j++) {
975f60611afSalnsn 			ATF_CHECK_EQ(result[j].l_start,  expect[j].l_start );
976f60611afSalnsn 			ATF_CHECK_EQ(result[j].l_len,    expect[j].l_len   );
977f60611afSalnsn 			ATF_CHECK_EQ(result[j].l_pid,    expect[j].l_pid   );
978f60611afSalnsn 			ATF_CHECK_EQ(result[j].l_type,   expect[j].l_type  );
979f60611afSalnsn 			ATF_CHECK_EQ(result[j].l_whence, expect[j].l_whence);
980e8bcfa54Spooka 		}
981e8bcfa54Spooka 	}
982e8bcfa54Spooka 
983e8bcfa54Spooka 	/*
984e8bcfa54Spooka 	 * Release processes.  This also releases the fds and locks
985e8bcfa54Spooka 	 * making fs unmount possible
986e8bcfa54Spooka 	 */
987e8bcfa54Spooka 	for (i = 0; i < __arraycount(lwp); i++) {
988e8bcfa54Spooka 		rump_pub_lwproc_switch(lwp[i]);
989e8bcfa54Spooka 		rump_pub_lwproc_releaselwp();
990e8bcfa54Spooka 	}
991e8bcfa54Spooka 
992e8bcfa54Spooka 	FSTEST_EXIT();
993e8bcfa54Spooka }
994e8bcfa54Spooka 
9956ae16092Spooka static void
access_simple(const atf_tc_t * tc,const char * mp)9966ae16092Spooka access_simple(const atf_tc_t *tc, const char *mp)
9976ae16092Spooka {
9986ae16092Spooka 	int fd;
9996ae16092Spooka 	int tmode;
10006ae16092Spooka 
10016ae16092Spooka 	FSTEST_ENTER();
10026ae16092Spooka 	RL(fd = rump_sys_open("tfile", O_CREAT | O_RDWR, 0777));
10036ae16092Spooka 	RL(rump_sys_close(fd));
10046ae16092Spooka 
10056ae16092Spooka #define ALLACC (F_OK | X_OK | W_OK | R_OK)
10066ae16092Spooka 	if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc))
10076ae16092Spooka 		tmode = F_OK;
10086ae16092Spooka 	else
10096ae16092Spooka 		tmode = ALLACC;
10106ae16092Spooka 
10116ae16092Spooka 	RL(rump_sys_access("tfile", tmode));
10126ae16092Spooka 
10136ae16092Spooka 	/* PR kern/44648 */
10146ae16092Spooka 	ATF_REQUIRE_ERRNO(EINVAL, rump_sys_access("tfile", ALLACC+1) == -1);
10156ae16092Spooka #undef ALLACC
10166ae16092Spooka 	FSTEST_EXIT();
10176ae16092Spooka }
10186ae16092Spooka 
1019973e4855Snjoly static void
read_directory(const atf_tc_t * tc,const char * mp)1020973e4855Snjoly read_directory(const atf_tc_t *tc, const char *mp)
1021973e4855Snjoly {
1022973e4855Snjoly 	char buf[1024];
1023973e4855Snjoly 	int fd, res;
1024973e4855Snjoly 	ssize_t size;
1025973e4855Snjoly 
1026973e4855Snjoly 	FSTEST_ENTER();
1027973e4855Snjoly 	fd = rump_sys_open(".", O_DIRECTORY | O_RDONLY, 0777);
1028973e4855Snjoly 	ATF_REQUIRE(fd != -1);
1029973e4855Snjoly 
1030973e4855Snjoly 	size = rump_sys_pread(fd, buf, sizeof(buf), 0);
1031973e4855Snjoly 	ATF_CHECK(size != -1 || errno == EISDIR);
1032973e4855Snjoly 	size = rump_sys_read(fd, buf, sizeof(buf));
1033973e4855Snjoly 	ATF_CHECK(size != -1 || errno == EISDIR);
1034973e4855Snjoly 
1035973e4855Snjoly 	res = rump_sys_close(fd);
1036973e4855Snjoly 	ATF_REQUIRE(res != -1);
1037973e4855Snjoly 	FSTEST_EXIT();
1038973e4855Snjoly }
1039973e4855Snjoly 
1040954ca525Snjoly static void
lstat_symlink(const atf_tc_t * tc,const char * mp)1041954ca525Snjoly lstat_symlink(const atf_tc_t *tc, const char *mp)
1042954ca525Snjoly {
1043954ca525Snjoly 	const char *src, *dst;
1044954ca525Snjoly 	int res;
1045954ca525Snjoly 	struct stat st;
1046954ca525Snjoly 
1047954ca525Snjoly 	USES_SYMLINKS;
104876c3358aSgson 
1049954ca525Snjoly 	FSTEST_ENTER();
1050954ca525Snjoly 
1051954ca525Snjoly 	src = "source";
1052954ca525Snjoly 	dst = "destination";
1053954ca525Snjoly 
1054954ca525Snjoly 	res = rump_sys_symlink(src, dst);
1055954ca525Snjoly 	ATF_REQUIRE(res != -1);
1056954ca525Snjoly 	res = rump_sys_lstat(dst, &st);
1057954ca525Snjoly 	ATF_REQUIRE(res != -1);
1058954ca525Snjoly 
1059954ca525Snjoly 	ATF_CHECK(S_ISLNK(st.st_mode) != 0);
1060954ca525Snjoly 	ATF_CHECK(st.st_size == (off_t)strlen(src));
1061954ca525Snjoly 
1062954ca525Snjoly 	FSTEST_EXIT();
1063954ca525Snjoly }
1064954ca525Snjoly 
10652a5fd96fSpooka ATF_TC_FSAPPLY(lookup_simple, "simple lookup (./.. on root)");
10662a5fd96fSpooka ATF_TC_FSAPPLY(lookup_complex, "lookup of non-dot entries");
10672a5fd96fSpooka ATF_TC_FSAPPLY(dir_simple, "mkdir/rmdir");
10680df09db4Smartin ATF_TC_FSAPPLY(dir_slash, "mkdir with appended slash");
10690df09db4Smartin ATF_TC_FSAPPLY(dir_2slash, "mkdir with two slashes appended");
10700df09db4Smartin ATF_TC_FSAPPLY(dir_3slash, "mkdir with three slashes appended");
10712a5fd96fSpooka ATF_TC_FSAPPLY(dir_notempty, "non-empty directories cannot be removed");
107259c51f5cSchristos ATF_TC_FSAPPLY(dir_rmdirdotdot, "remove .. and try to cd out (PR kern/44657)");
107359c51f5cSchristos ATF_TC_FSAPPLY(rename_dir, "exercise various directory renaming ops "
107459c51f5cSchristos "(PR kern/44288)");
107559c51f5cSchristos ATF_TC_FSAPPLY(rename_dotdot, "rename dir .. (PR kern/43617)");
1076ae0b9cceSpooka ATF_TC_FSAPPLY(rename_reg_nodir, "rename regular files, no subdirectories");
1077dccf0d48Snjoly ATF_TC_FSAPPLY(create_nametoolong, "create file with name too long");
10780aabb924Syamt ATF_TC_FSAPPLY(create_exist, "create with O_EXCL");
1079dccf0d48Snjoly ATF_TC_FSAPPLY(rename_nametoolong, "rename to file with name too long");
1080dec58decSgson ATF_TC_FSAPPLY(symlink_zerolen, "symlink with target of length 0");
1081dec58decSgson ATF_TC_FSAPPLY(symlink_long, "symlink with target of length > 0");
10820ed1cdc7Sriastradh ATF_TC_FSAPPLY(symlink_root, "symlink to root directory");
108345bfa2deSpooka ATF_TC_FSAPPLY(attrs, "check setting attributes works");
1084eea5c398Skefren ATF_TC_FSAPPLY(fcntl_lock, "check fcntl F_SETLK");
1085e8bcfa54Spooka ATF_TC_FSAPPLY(fcntl_getlock_pids,"fcntl F_GETLK w/ many procs, PR kern/44494");
10866ae16092Spooka ATF_TC_FSAPPLY(access_simple, "access(2)");
1087973e4855Snjoly ATF_TC_FSAPPLY(read_directory, "read(2) on directories");
1088954ca525Snjoly ATF_TC_FSAPPLY(lstat_symlink, "lstat(2) values for symbolic links");
10892a5fd96fSpooka 
1090596d7c22Spooka #undef FSTEST_IMGSIZE
1091596d7c22Spooka #define FSTEST_IMGSIZE (1024*1024*64)
1092596d7c22Spooka ATF_TC_FSAPPLY(create_many, "create many directory entries");
109379350377Sgson ATF_TC_FSAPPLY(create_nonalphanum, "non-alphanumeric filenames");
1094596d7c22Spooka 
ATF_TP_ADD_TCS(tp)10952a5fd96fSpooka ATF_TP_ADD_TCS(tp)
10962a5fd96fSpooka {
10972a5fd96fSpooka 
10982a5fd96fSpooka 	ATF_TP_FSAPPLY(lookup_simple);
10992a5fd96fSpooka 	ATF_TP_FSAPPLY(lookup_complex);
11002a5fd96fSpooka 	ATF_TP_FSAPPLY(dir_simple);
11012a5fd96fSpooka 	ATF_TP_FSAPPLY(dir_notempty);
1102878d41e6Spooka 	ATF_TP_FSAPPLY(dir_rmdirdotdot);
11030df09db4Smartin 	ATF_TP_FSAPPLY(dir_slash);
11040df09db4Smartin 	ATF_TP_FSAPPLY(dir_2slash);
11050df09db4Smartin 	ATF_TP_FSAPPLY(dir_3slash);
1106ae0b9cceSpooka 	ATF_TP_FSAPPLY(rename_dir);
1107ae0b9cceSpooka 	ATF_TP_FSAPPLY(rename_dotdot);
1108ae0b9cceSpooka 	ATF_TP_FSAPPLY(rename_reg_nodir);
1109596d7c22Spooka 	ATF_TP_FSAPPLY(create_many);
111079350377Sgson 	ATF_TP_FSAPPLY(create_nonalphanum);
1111dccf0d48Snjoly 	ATF_TP_FSAPPLY(create_nametoolong);
11120aabb924Syamt 	ATF_TP_FSAPPLY(create_exist);
1113dccf0d48Snjoly 	ATF_TP_FSAPPLY(rename_nametoolong);
1114b28267edSpooka 	ATF_TP_FSAPPLY(symlink_zerolen);
1115dec58decSgson 	ATF_TP_FSAPPLY(symlink_long);
11160ed1cdc7Sriastradh 	ATF_TP_FSAPPLY(symlink_root);
111745bfa2deSpooka 	ATF_TP_FSAPPLY(attrs);
1118eea5c398Skefren 	ATF_TP_FSAPPLY(fcntl_lock);
1119e8bcfa54Spooka 	ATF_TP_FSAPPLY(fcntl_getlock_pids);
11206ae16092Spooka 	ATF_TP_FSAPPLY(access_simple);
1121973e4855Snjoly 	ATF_TP_FSAPPLY(read_directory);
1122954ca525Snjoly 	ATF_TP_FSAPPLY(lstat_symlink);
11232a5fd96fSpooka 
11242a5fd96fSpooka 	return atf_no_error();
11252a5fd96fSpooka }
1126