summaryrefslogtreecommitdiffstats
path: root/contrib/netbsd-tests/fs/vfs
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2014-12-31 20:13:31 +0000
committerngie <ngie@FreeBSD.org>2014-12-31 20:13:31 +0000
commitb429a2bfd1380c777b9d59e54e17886b3855073e (patch)
treef5eb9fb5c3b79a2f3a7cba500581d24f4676622d /contrib/netbsd-tests/fs/vfs
parent155ee9c2f7fcb97a502844e0ca346b9f919b8cb2 (diff)
downloadFreeBSD-src-b429a2bfd1380c777b9d59e54e17886b3855073e.zip
FreeBSD-src-b429a2bfd1380c777b9d59e54e17886b3855073e.tar.gz
MFC r272343,r272458,r272890,r272891,r272901,r272902,r272903,r272905,r272908,r272909,r272910,r272914,r272915,r272979,r272980,r273010,r273011,r273012,r273015,r273017,r273019,r273020,r273021,r273022,r273023,r273024,r273025,r273389,r273390,r273391,r273393,r273395,r273396,r273397,r273410,r273516,r273517,r273520,r273521,r273522,r273523,r273524,r273525,r273526,r273527,r273528,r273529,r273530,r273533,r273534,r273535,r273536,r273537,r273538,r273539,r273540,r273572,r273574,r273578,r273579,r273591,r273592,r273928,r273933,r273935,r273936,r273937,r273938,r273942,r273943,r273945,r273946,r273947,r273948,r273949,r273950,r273951,r273952,r274061,r274062,r274066,r274067,r274072,r274074,r274079,r274090,r274142,r274143,r274571,r274572,r274573,r274574,r274575,r274576,r274577,r274579,r274597,r274598,r274599,r274600,r274601,r274626,r275033,r276046,r276430:
r272343: r272458: Import the NetBSD test suite from ^/vendor/NetBSD/tests/09.30.2014_20.45 , minus the vendor Makefiles Provide directions for how to bootstrap the vendor sources in FREEBSD-upgrade MFC after 2 weeks Discussed with: rpaulo Sponsored by: EMC / Isilon Storage Division r272890: Only build/run hsearch_basic and hsearch_r_basic on NetBSD hdestroy1 is not present on FreeBSD Sponsored by: EMC / Isilon Storage Division r272891: Expect SIGSEGV in lib/libc/stdlib/t_getenv:setenv_basic See bin/189805 for more details In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r272901: Disable tests that don't pass on FreeBSD due to missing support in humanize_number(3). Bringing in additional revisions from NetBSD's humanize_number(3) will fix the tests Account for the fact that util.h on NetBSD is libutil.h on FreeBSD Submitted by: pho Sponsored by: EMC / Isilon Storage Division r272902: Add missing #include <sys/time.h> for gettimeofday Sponsored by: EMC / Isilon Storage Division r272903: FreeBSD returns ENOTTY instead of EBADF in ttyname_r; mark it as an expected failure PR: 191936 In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r272905: FreeBSD doesn't support strings greater than MAXHOSTNAMELEN-1 in {get,set}{domain,host}name. Adjust the tests to not exceed that value when testing out the code Add a positive and negative test for MAXHOSTNAMELEN-1 and MAXHOSTNAMELEN, respectively PR: 181127 In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r272908: Disable the invalid pointer test on FreeBSD FreeBSD segfaults on invalid pointers passed to getcwd because it throbs the address passed in in libc, whereas NetBSD just passes the information off to the syscall, which allows the kernel to return EFAULT on bad pointers. In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r272909: Handle getting/setting niceness/priority correctly on FreeBSD vs NetBSD This might be fallout from PR: 189821 Submitted by: pho Sponsored by: EMC / Isilon Storage Division r272910: SIGPWR does not exist on FreeBSD Sponsored by: EMC / Isilon Storage Division r272914: Skip over t_spawn_open_nonexistent_diag because it requires NetBSD specific additions to posix_spawn Sponsored by: EMC / Isilon Storage Division r272915: Port the testcase to FreeBSD - Make #include path to h_macros.h a non-relative path - __gl_stat_t is synonymous with struct stat on FreeBSD - FreeBSD doesn't have _DIRENT_RECLEN - Skip over glob_star on FreeBSD (testcase doesn't pass) In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r272979: Only #include <sys/tls.h> on NetBSD Sponsored by: EMC / Isilon Storage Division r272980: #include libutil.h for fparseln on FreeBSD Sponsored by: EMC / Isilon Storage Division r273010: Implement 64MB memory limit for test to ensure that it fails reliably in 600 seconds; it would previously fail inconsistently when run in some virtual machine configurations This patch might need to be reverted or revisited later (see the attached PR for more details) PR: 169302 Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273011: Fix compilation errors with missing wide-type headers and fix compilation warnings with -Wformat In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273012: - Add libutil #include for fparseln - Change ATF_REQUIRE_EQ_MSG to ATF_CHECK_EQ_MSG to gather all failing results possible (currently 12 with leftassoc) - Mark leftassoc "atf_tc_expect_fail" on FreeBSD (PR coming soon after further analysis is done on the code) In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273015: Expect nice_err to fail on FreeBSD with unprivileged users PR: 189821 Sponsored by: EMC / Isilon Storage Division r273017: Add #include <stdio.h> for printf Sponsored by: EMC / Isilon Storage Division r273019: Do initial port of contrib/netbsd-tests/lib/libc/locale t_io: - Expect failures potentially related to implementation-specific knowledge of the zh_TW.Big5 locale [*] t_mbrtowc: - Handle unknown locales more gracefully (do not test if the locale doesn't exist) - Expect failure with mbrtowc_internal dealing with Japanese locales (potentially related to implementation detail knowledge of the ja_* locales) [*]. t_mbstowcs, t_mbtowc, t_wctomb: - Handle unknown locales more gracefully (do not test if the locale doesn't exist) t_wcstod: - Treat FreeBSD like NetBSD and Linux in the XXX: FIXME section [*] More investigation is required to determine the root cause of the failures Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273020: memmem with NUL length "needle" (aka small) strings on FreeBSD/OSX returns NULL instead of the "haystack" value (aka big) Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273021: Use 1 as a random seed, as recommended in srandom(3). Adjust the random values accordingly Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273022: Add #include <stdio.h> to get sys_nerr definition Sponsored by: EMC / Isilon Storage Division r273023: __isnanl is automatically picked according to data type in <math.h>. There isn't a need for the explicit __isnanl test Sponsored by: EMC / Isilon Storage Division r273024: Only test the return value in mktime_negyear Testing for the errno is an optional requirement according to POSIX, and FreeBSD doesn't document that errno would be set on failure with mktime Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273025: Change ATF_REQUIRE_MSG calls to ATF_CHECK_MSG to get as many errors as possible t_strptime:common.. - Expect the testcase body as a whole to fail. Multiple PRs will be filed to track the issues (there are 18 check failures) t_strptime:day.. - %EA and %OA seem to be case insensitive on FreeBSD r273389: Port lib/libc/gen/t_siginfo to FreeBSD - mcontext_t on FreeBSD doesn't have a __gregs field (it's split out on FreeBSD into separate fields). In order to avoid muddying the test code with MD code, the debugging trace info has not been implemented - FreeBSD does not implement the si_stime and si_utime fields in siginfo_t, so omit the debugging code that dumps the values - sys/inttypes.h doesn't exist on FreeBSD Sponsored by: EMC / Isilon Storage Division r273390: libutil.h is required for fparseln on FreeBSD Sponsored by: EMC / Isilon Storage Division r273391: Add missing #include for sys/stat.h for fchmod Sponsored by: EMC / Isilon Storage Division r273393: Port t_write to FreeBSD - Mark the signo variable for the signal handle __unused - Use limits.h instead of sys/syslimits.h (the latter does not exist on FreeBSD) Sponsored by: EMC / Isilon Storage Division r273395: Mark osi __unused so this compiles cleanly on FreeBSD Sponsored by: EMC / Isilon Storage Division r273396: unlink("/") fails with EISDIR instead of EBUSY on FreeBSD; test for that instead Sponsored by: EMC / Isilon Storage Division r273397: Port t_chroot to FreeBSD - Add missing #include sys/stat.h for mkdir(2) - Omit the fchroot(2) tests because the support is not present on FreeBSD Sponsored by: EMC / Isilon Storage Division r273410: Add sys/socket.h #include for bind(2), et al Sponsored by: EMC / Isilon Storage Division r273516: Add netinet/in.h for struct sockaddr_in Sponsored by: EMC / Isilon Storage Division r273517: Expect getgroups_err to fail on FreeBSD PR: 189941 Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273520: Port t_pipe2.c to FreeBSD - Omit the pipe2_nosigpipe testcase on FreeBSD (FreeBSD doesn't have O_NOSIGPIPE). - Convert "fcntl(n, F_CLOSEM)" to "closefrom(n)". - Save and restore the resource limit on the number of files (RLIMIT_NOFILE). In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273521: Convert "fcntl(n, F_CLOSEM)" to "closefrom(n)" Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273522: - Mark unused parameters __unused in handler - Call sigqueue with getpid() instead of 0 -- the latter idiom appears to only be valid on NetBSD In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273523: Add limits.h #include for LINE_MAX Sponsored by: EMC / Isilon Storage Division r273524: Add sys/socket.h #include for struct sockaddr_in Sponsored by: EMC / Isilon Storage Division r273525: Port t_mmap.c to FreeBSD - Add needed headers for the testcases - Omit mmap_block on non-NetBSD OSes - Use "security.bsd.map_at_zero" instead of "vm.user_va0_disable" Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273526: Omit the pollts testcases on FreeBSD Sponsored by: EMC / Isilon Storage Division r273527: Omit all of the testcases as revoke(2) is only implemented on devfs(5) Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273528: Mark signo __unused in handler(..) Sponsored by: EMC / Isilon Storage Division r273529: - Omit the poll testcases on FreeBSD (they require pollts) - Add necessary headers for the testcases Sponsored by: EMC / Isilon Storage Division r273530: Add limits.h #include for INT_MAX Sponsored by: EMC / Isilon Storage Division r273533: Use <atf_srcdir>/truncate_test.root_owned instead of /usr/bin/fpr as fpr does not exist on FreeBSD truncate_test.root_owned will be generated at build time and owned by root In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273534: - Mark sig/signo __unused - Do not provide a relative path via #include "h_macros.h" Sponsored by: EMC / Isilon Storage Division r273535: - Omit setrlimit_nthr testcase on FreeBSD (requires lwp.h, et al) - Expect overflow with rlim_max at INT64_MAX, not UINT64_MAX (rlim_t is int64_t on FreeBSD) In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273536: Add limits.h #include for SSIZE_MAX Sponsored by: EMC / Isilon Storage Division r273537: Add limits.h #include for SSIZE_MAX Sponsored by: EMC / Isilon Storage Division r273538: Fix a typo (__FreeBSD__ -> __NetBSD__ when omitting setrlimit_nthr) r273539: Mark signum __unused Sponsored by: EMC / Isilon Storage Division r273540: Omit the mprotect_exec testcase on FreeBSD Sponsored by: EMC / Isilon Storage Division r273572: - Ignore EINVAL check with mknod(path, S_IFCHR, -1) as the testcase is always executed on a non-devfs filesystem - Expect mknod(path, S_IFREG, 0) to fail on FreeBSD Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273574: - Test for EINVAL requirement when passing an invalid flag in to msync(2) - Expect ENOMEM instead of EFAULT when msync'ing a previously munmap'ed region on FreeBSD Submitted by: pho Sponsored by: EMC / Isilon Storage Division r273578: - Add inttypes.h and stdint.h in lieu of int_limits.h from NetBSD - Use #include "h_macros.h" instead of relative path analog Sponsored by: EMC / Isilon Storage Division r273579: - Mark signo __unused in the signal handler function - Effectively #if 0 out some code that does not fail on FreeBSD In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273591: Correct my previous commit: - getrusage_utime_back succeeds reliably on FreeBSD - getrusage_utime_zero passes/fails in a seemingly non-deterministic manner. Skip it for now (and fix it later) In the initial port of this testcase to FreeBSD, the results failed reliably in the same manner as it does on NetBSD Sponsored by: EMC / Isilon Storage Division r273592: - Add sys/types.h for the APIs in sys/sysctl.h - Poke at VM_MIN_ADDRESS in machine/vmparam.h because FreeBSD doesn't have a vm.minaddress sysctl analog - Expect ENOMEM instead of EAGAIN in mlock_limits - Provide mlock an mmap'ed page twice to simulate MAP_WIRED on NetBSD In collaboration with: pho Sponsored by: EMC / Isilon Storage Division r273928: Put mtree test files into a subdirectory. Kyua 0.11 points TMPDIR to the test's work directory, and atf_check creates auxiliary files in TMPDIR. This confuses a couple of mtree tests that were using the work directory's root to validate the contents of the directory. Fix the two affected tests by creating an auxiliary directory to use for the mtree tests. (Kyua should probably do this on its own; filed bug #133 upstream to take a look at this.) r273933: Don't prune duplicate services in the expected output from /etc/services on FreeBSD Submitted by: pho r273935: Port tests to FreeBSD/Linux Some of the testcases don't work outside of NetBSD, and the behavior of ether_aton_r differs between FreeBSD, Linux, and NetBSD, and the calls to the API need to be massaged for FreeBSD and Linux. Submitted by: pho r273936: Port lib/libc/net/h_dns_server to FreeBSD Submitted by: pho r273937: Port lib/libc/sys/t_dup to FreeBSD/Linux - The requirements differ between FreeBSD/Linux when dealing with oldd/newd being equal (both fail with EINVAL, not EBADF) - Add an EBADF testcase - Fix compilation issues on clang In collaboration with: pho r273938: getitimer on FreeBSD returns the last set time instead of the remaining time; test for that instead Submitted by: pho r273942: Skip :sethostname_basic because it messes up the test host's hostname Convert code from #if defined(__FreeBSD__) to #ifdef __FreeBSD__ r273943: Port t_kevent to FreeBSD Submitted by: pho r273945: Port t_mincore to FreeBSD Mark :mincore_resid as atf_tc_expect_fail on FreeBSD because of new bug discovered in running the tests (it succeeded from earlier on in the year to September/October on FreeBSD, at least) Submitted by: pho r273946: Port h_atexit to FreeBSD __cxa_atexit varies between FreeBSD and NetBSD, and thus we must use pointers instead of static fields in the BSS. More extensive discussion is included in the source code In collaboration with: kib Submitted by: pho r273947: Expect :snprintf_posarg_error to blow up with a SIGSEGV on !NetBSD OSes r273948: Disable testcases 12 and 15-22 on FreeBSD Submitted by: pho r273949: Add new atf_tc_expect_fail to fflush_err; this is a new (within the past couple months) bug r273950: Skip :fopen_regular on !NetBSD because it's a NetBSD specific test Submitted by: pho r273951: Expect :sscanf_whitespace to fail on !NetBSD OSes Submitted by: pho r273952: Port h_hash and t_sha2 to FreeBSD t_sha2 contains dirty copy-paste hacks that need to be fixed with the openssh OpenBSD compat layer Submitted by: pho r274061: Port t_db.sh to FreeBSD - The blocksize on FreeBSD is 32kB, not 64kB - Add some detection for MK_DICT == no; /nonexistent is echoed along with atf_skip to ensure that the test will fail if dict(..) is called in the non-final stage of the pipeline Submitted by: pho r274062: inet_network on FreeBSD returns NULL when provided "0x" to inet_network Submitted by: pho r274066: Port lib/libc/ssp to FreeBSD In most cases, the buffers and data were resized, but when dealing with the helpers, some of the code was adjusted to fail more reliably Submitted by: pho r274067: rpc_control on FreeBSD is a public-ish API (not prefixed with __), not private like NetBSD Submitted by: pho r274072: Finish off lib/libc/stdlib/t_strtod.c port by checking for "y" twice on FreeBSD, and always assume long long double exists on FreeBSD Submitted by: pho r274074: Add Makefile snippet to ease porting NetBSD testcases to FreeBSD from contrib/netbsd-tests This Makefile snippet handles polluting testcases with -lnetbsd, specific headers for ATF version differences, and does necessary rewriting for the testcases to match the format discussed on the TestSuite wiki page (t_<foo> -> <foo>_test) One must define SRCTOP (inspired by projects/bmake), OBJTOP, and TESTSRC (e.g. contrib/netbsd-tests/lib/libc/gen) to use the Makefile snippet Test programs are specific either via NETBSD_ATF_TESTS_C or NETBSD_ATF_TESTS_SH C++ analogs aren't currently implemented. The imported testcases will be cleaned up to use this Makefile snippet pseudo "API". r274079: Import proper fix for misc/49356 (/usr/include/atf-c/config.h) after atf-c/config.h was removed from the build Pointyhat to: me (again, for not running make delete-old after running test builds) r274090: Fix the Jenkins test run by skipping the negative testcases earlier The problem is that lib.libc.locale.t_io:bad_big5_wprintf was printing out illegal Unicode characters, which causes XML parsers to bail immediately, e.g. % kyua report-junit > ~/report.junit % python2 -c 'import xml.dom.minidom as md; md.parse("/home/ngie/report.junit")' Traceback (most recent call last): File "<string>", line 1, in <module> File "/usr/local/lib/python2.7/xml/dom/minidom.py", line 1918, in parse return expatbuilder.parse(file) File "/usr/local/lib/python2.7/xml/dom/expatbuilder.py", line 924, in parse result = builder.parseFile(fp) File "/usr/local/lib/python2.7/xml/dom/expatbuilder.py", line 207, in parseFile parser.Parse(buffer, 0) xml.parsers.expat.ExpatError: not well-formed (invalid token): line 27137, column 13 r274142: Remove expected failure from lib.libc.sys.t_mincore:mincore_resid The failure was added based on observation seen on 11.0-CURRENT @ r273153, not based on internal testing at EMC/Isilon PR: 194829 Tested with the following configuration: - amd64/i386 - 11.0-CURRENT @ r273153 - 100 times in a tight loop as root with the following commands... -- kyua test lib/libc -- kyua test lib/libc/sys -- kyua test lib/libc/sys/mincore_test r274143: Expect lib.libc.sys.getcontext_test.setcontext_link to fail on amd64; add additional debugging to make the underlying problem more visible Calling setcontext(2) on amd64 as shown in the test program is failing on amd64, not i386, with a return code of -1 and an errno of EINVAL Further investigation is being done in the PR to determine the root cause for the failure PR: 194828 Tested with the following configuration: - amd64/i386 - 11.0-CURRENT @ r273153 - 100 times in a tight loop as root with the following commands... -- kyua test lib/libc -- kyua test lib/libc/sys -- kyua test lib/libc/sys/getcontext_test r274571: Use _exit instead of exit so the file descriptors aren't flushed twice in the child processes Submitted by: pho r274572: Only expect timeouts on powerpc with NetBSD Submitted by: pho r274573: Expect :pthread_detach to fail with EINVAL instead of ESRCH on FreeBSD PR: 191906 In collaboration with: pho r274574: Add pthread_np.h #include and initialize the pthread attribute on FreeBSD Submitted by: pho r274575: #ifdef out a printf on !NetBSD that causes the testcase to fail when comparing the output from the helper program Submitted by: pho r274576: Port helper program to FreeBSD, similar to ../../lib/libc/stdlib/h_atexit.c Submitted by: pho In collaboration with: kib r274577: Add missing sys/time.h #include for timespecsub macro in lib/libnetbsd/sys/time.h r274579: Call sem_unlink on semaphores before attempting to create them Due to the lack of uniqueness in the semaphore name, and the fact that the tests don't have cleanup routines, an interrupted test can leave a semaphore "laying around", causing all subsequent attempts to run the test to fail I will file a NetBSD PR for this issue soon r274597: Skip the long-double epsilon checks on FreeBSD/i386 Sponsored by: EMC / Isilon Storage Division r274598: Reset errno to 0 before running scalbn to be sure that the tested errno is valid Sponsored by: EMC / Isilon Storage Division r274599: Alias isinff to isinf on FreeBSD isinf on FreeBSD automatically picks the appropriate type per math.h Sponsored by: EMC / Isilon Storage Division r274600: - Expect exp2_powers to fail on FreeBSD/i386 - Expect exp2_values to fail on FreeBSD due to the small epsilon Sponsored by: EMC / Isilon Storage Division r274601: - Skip over the testcases that call cbrtl on platforms where LDBL_PREC == 53 (arm, mips, powerpc). This fixes the build on these platforms, based on some ad hoc tinderbox runs I did a while ago - Skip cast the arguments to powl as long double so powl properly interprets those arugments at compile-time when picking the type Sponsored by: EMC / Isilon Storage Division r274626: Mechanically replace #if defined(__FreeBSD__) and #if defined(__NetBSD__) with their #ifdef equivalents for everything changed in contrib/netbsd-tests. There are some items from the vendor tree that use #if defined(__FreeBSD__) or #if defined(__NetBSD__) which are being left alone Requested by: bde, rpaulo Sponsored by: EMC / Isilon Storage Division r275033: Only pass 6 arguments to the 'run' function on amd64. amd64's makecontext on FreeBSD only supports a maximum of 6 arguments. This fixes the setcontext_link test on amd64. PR: 194828 r276046: Add __FreeBSD_version guards around hsearch_r to ease MFCing the code to stable/10 It was added when __FreeBSD_version was ~1100027 r276430: Expect access_test:access_inval to fail before __FreeBSD_version == 1100033 This will allow me to MFC the test, as jilles@ requested that I don't MFC the access(2) KBI change to 10-STABLE in r271655
Diffstat (limited to 'contrib/netbsd-tests/fs/vfs')
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_full.c101
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_io.c250
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_renamerace.c190
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_rmdirrace.c106
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_ro.c203
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_union.c204
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_unpriv.c241
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_vfsops.c211
-rw-r--r--contrib/netbsd-tests/fs/vfs/t_vnops.c1001
9 files changed, 2507 insertions, 0 deletions
diff --git a/contrib/netbsd-tests/fs/vfs/t_full.c b/contrib/netbsd-tests/fs/vfs/t_full.c
new file mode 100644
index 0000000..f338a02
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_full.c
@@ -0,0 +1,101 @@
+/* $NetBSD: t_full.c,v 1.8 2013/03/16 05:45:37 jmmv Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rump/rump_syscalls.h>
+#include <rump/rump.h>
+
+#include "../common/h_fsmacros.h"
+#include "../../h_macros.h"
+
+/*
+ * Write this much over the image size. This is to force an NFS commit,
+ * since we might just stuff data into the cache and miss the problem.
+ */
+#define NFSBONUS (1<<16)
+
+static void
+fillfs(const atf_tc_t *tc, const char *mp)
+{
+ char buf[8192];
+ size_t written;
+ ssize_t n = 0; /* xxxgcc */
+ size_t bonus;
+ int fd, i = 0;
+
+ if (FSTYPE_P2K_FFS(tc) || FSTYPE_PUFFS(tc) || FSTYPE_RUMPFS(tc)) {
+ atf_tc_skip("fs does not support explicit block allocation "
+ "(GOP_ALLOC)");
+ }
+
+ bonus = 0;
+ if (FSTYPE_NFS(tc))
+ bonus = NFSBONUS;
+
+ if (rump_sys_chdir(mp) == -1)
+ atf_tc_fail_errno("chdir mountpoint");
+ fd = rump_sys_open("afile", O_CREAT | O_RDWR);
+ if (fd == -1)
+ atf_tc_fail_errno("create file");
+
+ for (written = 0; written < FSTEST_IMGSIZE + bonus; written +=n) {
+ memset(buf, i++, sizeof(buf)); /* known garbage */
+ n = rump_sys_write(fd, buf, sizeof(buf));
+ if (n == -1)
+ break;
+ }
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (n == -1) {
+ if (errno != ENOSPC)
+ atf_tc_fail_errno("write");
+ } else {
+ atf_tc_fail("filled file system over size limit");
+ }
+
+ rump_sys_close(fd);
+ rump_sys_chdir("/");
+}
+
+ATF_TC_FSAPPLY(fillfs, "fills file system, expects ENOSPC");
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY(fillfs);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/fs/vfs/t_io.c b/contrib/netbsd-tests/fs/vfs/t_io.c
new file mode 100644
index 0000000..67d8657
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_io.c
@@ -0,0 +1,250 @@
+/* $NetBSD: t_io.c,v 1.12 2013/08/04 11:02:02 pooka Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rump/rump_syscalls.h>
+#include <rump/rump.h>
+
+#include "../common/h_fsmacros.h"
+#include "../../h_macros.h"
+
+#define TESTSTR "this is a string. collect enough and you'll have Em"
+#define TESTSZ sizeof(TESTSTR)
+
+static void
+holywrite(const atf_tc_t *tc, const char *mp)
+{
+ char buf[1024];
+ char *b2, *b3;
+ size_t therange = getpagesize()+1;
+ int fd;
+
+ FSTEST_ENTER();
+
+ RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666));
+
+ memset(buf, 'A', sizeof(buf));
+ RL(rump_sys_pwrite(fd, buf, 1, getpagesize()));
+
+ memset(buf, 'B', sizeof(buf));
+ RL(rump_sys_pwrite(fd, buf, 2, getpagesize()-1));
+
+ REQUIRE_LIBC(b2 = malloc(2 * getpagesize()), NULL);
+ REQUIRE_LIBC(b3 = malloc(2 * getpagesize()), NULL);
+
+ RL(rump_sys_pread(fd, b2, therange, 0));
+
+ memset(b3, 0, therange);
+ memset(b3 + getpagesize() - 1, 'B', 2);
+
+ ATF_REQUIRE_EQ(memcmp(b2, b3, therange), 0);
+
+ rump_sys_close(fd);
+ FSTEST_EXIT();
+}
+
+static void
+extendbody(const atf_tc_t *tc, off_t seekcnt)
+{
+ char buf[TESTSZ+1];
+ struct stat sb;
+ int fd;
+
+ FSTEST_ENTER();
+ RL(fd = rump_sys_open("testfile",
+ O_CREAT | O_RDWR | (seekcnt ? O_APPEND : 0)));
+ RL(rump_sys_ftruncate(fd, seekcnt));
+ RL(rump_sys_fstat(fd, &sb));
+ ATF_REQUIRE_EQ(sb.st_size, seekcnt);
+
+ ATF_REQUIRE_EQ(rump_sys_write(fd, TESTSTR, TESTSZ), TESTSZ);
+ ATF_REQUIRE_EQ(rump_sys_pread(fd, buf, TESTSZ, seekcnt), TESTSZ);
+ ATF_REQUIRE_STREQ(buf, TESTSTR);
+
+ RL(rump_sys_fstat(fd, &sb));
+ ATF_REQUIRE_EQ(sb.st_size, (off_t)TESTSZ + seekcnt);
+ RL(rump_sys_close(fd));
+ FSTEST_EXIT();
+}
+
+static void
+extendfile(const atf_tc_t *tc, const char *mp)
+{
+
+ extendbody(tc, 0);
+}
+
+static void
+extendfile_append(const atf_tc_t *tc, const char *mp)
+{
+
+ extendbody(tc, 37);
+}
+
+static void
+overwritebody(const atf_tc_t *tc, off_t count, bool dotrunc)
+{
+ char *buf;
+ int fd;
+
+ REQUIRE_LIBC(buf = malloc(count), NULL);
+ FSTEST_ENTER();
+ RL(fd = rump_sys_open("testi", O_CREAT | O_RDWR, 0666));
+ ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count);
+ RL(rump_sys_close(fd));
+
+ RL(fd = rump_sys_open("testi", O_RDWR));
+ if (dotrunc)
+ RL(rump_sys_ftruncate(fd, 0));
+ ATF_REQUIRE_EQ(rump_sys_write(fd, buf, count), count);
+ RL(rump_sys_close(fd));
+ FSTEST_EXIT();
+}
+
+static void
+overwrite512(const atf_tc_t *tc, const char *mp)
+{
+
+ overwritebody(tc, 512, false);
+}
+
+static void
+overwrite64k(const atf_tc_t *tc, const char *mp)
+{
+
+ overwritebody(tc, 1<<16, false);
+}
+
+static void
+overwrite_trunc(const atf_tc_t *tc, const char *mp)
+{
+
+ overwritebody(tc, 1<<16, true);
+}
+
+static void
+shrinkfile(const atf_tc_t *tc, const char *mp)
+{
+ int fd;
+
+ FSTEST_ENTER();
+ RL(fd = rump_sys_open("file", O_RDWR|O_CREAT|O_TRUNC, 0666));
+ RL(rump_sys_ftruncate(fd, 2));
+ RL(rump_sys_ftruncate(fd, 1));
+ rump_sys_close(fd);
+ FSTEST_EXIT();
+}
+
+#define TBSIZE 9000
+static void
+read_after_unlink(const atf_tc_t *tc, const char *mp)
+{
+ char buf[TBSIZE], buf2[TBSIZE];
+ int fd;
+
+ FSTEST_ENTER();
+
+ /* create file and put some content into it */
+ RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666));
+ memset(buf, 'D', TBSIZE);
+ ATF_REQUIRE_EQ(rump_sys_write(fd, buf, TBSIZE), TBSIZE);
+ rump_sys_close(fd);
+
+ /* flush buffers from UBC to file system */
+ ATF_REQUIRE_ERRNO(EBUSY, rump_sys_unmount(mp, 0) == -1);
+
+ RL(fd = rump_sys_open("file", O_RDWR));
+ RL(rump_sys_unlink("file"));
+
+ ATF_REQUIRE_EQ(rump_sys_read(fd, buf2, TBSIZE), TBSIZE);
+ ATF_REQUIRE_EQ(memcmp(buf, buf2, TBSIZE), 0);
+ rump_sys_close(fd);
+
+ FSTEST_EXIT();
+}
+
+static void
+wrrd_after_unlink(const atf_tc_t *tc, const char *mp)
+{
+ int value = 0x11;
+ int v2;
+ int fd;
+
+ FSTEST_ENTER();
+
+ RL(fd = rump_sys_open("file", O_RDWR|O_CREAT, 0666));
+ RL(rump_sys_unlink("file"));
+
+ RL(rump_sys_pwrite(fd, &value, sizeof(value), 654321));
+
+ /*
+ * We can't easily invalidate the buffer since we hold a
+ * reference, but try to get them to flush anyway.
+ */
+ RL(rump_sys_fsync(fd));
+ RL(rump_sys_pread(fd, &v2, sizeof(v2), 654321));
+ rump_sys_close(fd);
+
+ ATF_REQUIRE_EQ(value, v2);
+ FSTEST_EXIT();
+}
+
+ATF_TC_FSAPPLY(holywrite, "create a sparse file and fill hole");
+ATF_TC_FSAPPLY(extendfile, "check that extending a file works");
+ATF_TC_FSAPPLY(extendfile_append, "check that extending a file works "
+ "with a append-only fd (PR kern/44307)");
+ATF_TC_FSAPPLY(overwrite512, "write a 512 byte file twice");
+ATF_TC_FSAPPLY(overwrite64k, "write a 64k byte file twice");
+ATF_TC_FSAPPLY(overwrite_trunc, "write 64k + truncate + rewrite");
+ATF_TC_FSAPPLY(shrinkfile, "shrink file");
+ATF_TC_FSAPPLY(read_after_unlink, "contents can be read off disk after unlink");
+ATF_TC_FSAPPLY(wrrd_after_unlink, "file can be written and read after unlink");
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY(holywrite);
+ ATF_TP_FSAPPLY(extendfile);
+ ATF_TP_FSAPPLY(extendfile_append);
+ ATF_TP_FSAPPLY(overwrite512);
+ ATF_TP_FSAPPLY(overwrite64k);
+ ATF_TP_FSAPPLY(overwrite_trunc);
+ ATF_TP_FSAPPLY(shrinkfile);
+ ATF_TP_FSAPPLY(read_after_unlink);
+ ATF_TP_FSAPPLY(wrrd_after_unlink);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/fs/vfs/t_renamerace.c b/contrib/netbsd-tests/fs/vfs/t_renamerace.c
new file mode 100644
index 0000000..70e02f3
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_renamerace.c
@@ -0,0 +1,190 @@
+/* $NetBSD: t_renamerace.c,v 1.32 2014/07/29 09:15:48 gson Exp $ */
+
+/*
+ * Modified for rump and atf from a program supplied
+ * by Nicolas Joly in kern/40948
+ */
+
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/utsname.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rump.h>
+#include <rump/rump_syscalls.h>
+
+/* Bump the size of the test file system image to a larger value.
+ *
+ * These tests cause a lot of churn in the file system by creating and
+ * deleting files/directories in quick succession. A faster CPU will cause
+ * more churn because the tests are capped by a run time period in seconds,
+ * not number of operations.
+ *
+ * This is all fine except for LFS, because the lfs_cleanerd cannot keep up
+ * with the churn and thus causes the test to fail on fast machines. Hence
+ * the reason for this hack. */
+#define FSTEST_IMGSIZE (50000 * 512)
+
+#include "../common/h_fsmacros.h"
+#include "../../h_macros.h"
+
+static volatile int quittingtime;
+pid_t wrkpid;
+
+static void *
+w1(void *arg)
+{
+ int fd;
+
+ rump_pub_lwproc_newlwp(wrkpid);
+
+ while (!quittingtime) {
+ fd = rump_sys_open("rename.test1",
+ O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ if (fd == -1 && errno != EEXIST)
+ atf_tc_fail_errno("create");
+ rump_sys_unlink("rename.test1");
+ rump_sys_close(fd);
+ }
+
+ return NULL;
+}
+
+static void *
+w1_dirs(void *arg)
+{
+
+ rump_pub_lwproc_newlwp(wrkpid);
+
+ while (!quittingtime) {
+ if (rump_sys_mkdir("rename.test1", 0777) == -1)
+ atf_tc_fail_errno("mkdir");
+ rump_sys_rmdir("rename.test1");
+ }
+
+ return NULL;
+}
+
+static void *
+w2(void *arg)
+{
+
+ rump_pub_lwproc_newlwp(wrkpid);
+
+ while (!quittingtime) {
+ rump_sys_rename("rename.test1", "rename.test2");
+ }
+
+ return NULL;
+}
+
+#define NWRK 8
+static void
+renamerace(const atf_tc_t *tc, const char *mp)
+{
+ pthread_t pt1[NWRK], pt2[NWRK];
+ int i;
+
+ /*
+ * Sysvbfs supports only 8 inodes so this test would exhaust
+ * the inode table and creating files would fail with ENOSPC.
+ */
+ if (FSTYPE_SYSVBFS(tc))
+ atf_tc_skip("filesystem has not enough inodes");
+ if (FSTYPE_RUMPFS(tc))
+ atf_tc_skip("rename not supported by file system");
+ if (FSTYPE_UDF(tc))
+ atf_tc_expect_fail("PR kern/49046");
+
+ RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
+ RL(wrkpid = rump_sys_getpid());
+
+ RL(rump_sys_chdir(mp));
+ for (i = 0; i < NWRK; i++)
+ pthread_create(&pt1[i], NULL, w1, NULL);
+
+ for (i = 0; i < NWRK; i++)
+ pthread_create(&pt2[i], NULL, w2, NULL);
+
+ sleep(5);
+ quittingtime = 1;
+
+ for (i = 0; i < NWRK; i++)
+ pthread_join(pt1[i], NULL);
+ for (i = 0; i < NWRK; i++)
+ pthread_join(pt2[i], NULL);
+ RL(rump_sys_chdir("/"));
+
+ if (FSTYPE_UDF(tc))
+ atf_tc_fail("race did not trigger this time");
+
+ if (FSTYPE_MSDOS(tc)) {
+ atf_tc_expect_fail("PR kern/44661");
+ /*
+ * XXX: race does not trigger every time at least
+ * on amd64/qemu.
+ */
+ if (msdosfs_fstest_unmount(tc, mp, 0) != 0) {
+ rump_pub_vfs_mount_print(mp, 1);
+ atf_tc_fail_errno("unmount failed");
+ }
+ atf_tc_fail("race did not trigger this time");
+ }
+}
+
+static void
+renamerace_dirs(const atf_tc_t *tc, const char *mp)
+{
+ pthread_t pt1, pt2;
+
+ if (FSTYPE_SYSVBFS(tc))
+ atf_tc_skip("directories not supported by file system");
+
+ if (FSTYPE_RUMPFS(tc))
+ atf_tc_skip("rename not supported by file system");
+
+ /* XXX: msdosfs also sometimes hangs */
+ if (FSTYPE_MSDOS(tc))
+ atf_tc_expect_signal(-1, "PR kern/43626");
+
+ RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
+ RL(wrkpid = rump_sys_getpid());
+
+ RL(rump_sys_chdir(mp));
+ pthread_create(&pt1, NULL, w1_dirs, NULL);
+ pthread_create(&pt2, NULL, w2, NULL);
+
+ sleep(5);
+ quittingtime = 1;
+
+ pthread_join(pt1, NULL);
+ pthread_join(pt2, NULL);
+ RL(rump_sys_chdir("/"));
+
+ /*
+ * Doesn't always trigger when run on a slow backend
+ * (i.e. not on tmpfs/mfs). So do the usual kludge.
+ */
+ if (FSTYPE_MSDOS(tc))
+ abort();
+}
+
+ATF_TC_FSAPPLY(renamerace, "rename(2) race with file unlinked mid-operation");
+ATF_TC_FSAPPLY(renamerace_dirs, "rename(2) race with directories");
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY(renamerace); /* PR kern/41128 */
+ ATF_TP_FSAPPLY(renamerace_dirs);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/fs/vfs/t_rmdirrace.c b/contrib/netbsd-tests/fs/vfs/t_rmdirrace.c
new file mode 100644
index 0000000..839dbad
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_rmdirrace.c
@@ -0,0 +1,106 @@
+/* $NetBSD: t_rmdirrace.c,v 1.9 2012/02/16 02:47:56 perseant Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Nicolas Joly.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rump/rump_syscalls.h>
+#include <rump/rump.h>
+
+#include "../common/h_fsmacros.h"
+
+#define DIRNAME "rmdir.test"
+
+static void *func1(void *arg)
+{
+
+ while (*(int *)arg != 1)
+ rump_sys_mkdir(DIRNAME, 0755);
+
+ return NULL;
+}
+
+static void *func2(void *arg)
+{
+
+ while (*(int *)arg != 1)
+ rump_sys_rmdir(DIRNAME);
+
+ return NULL;
+}
+
+static void
+race(const atf_tc_t *tc, const char *path)
+{
+ int res, fd, quit;
+ pthread_t th1, th2;
+
+ if (FSTYPE_SYSVBFS(tc))
+ atf_tc_skip("directories not supported by file system");
+
+ fd = rump_sys_open(".", O_RDONLY, 0666);
+ if (fd == -1)
+ atf_tc_fail("open failed");
+ res = rump_sys_chdir(path);
+ if (res == -1)
+ atf_tc_fail("chdir failed");
+
+ quit = 0;
+
+ res = pthread_create(&th1, NULL, func1, &quit);
+ if (res != 0)
+ atf_tc_fail("pthread_create1 failed");
+ res = pthread_create(&th2, NULL, func2, &quit);
+ if (res != 0)
+ atf_tc_fail("pthread_create2 failed");
+
+ sleep(10);
+
+ quit = 1;
+
+ res = pthread_join(th2, NULL);
+ if (res != 0)
+ atf_tc_fail("pthread_join2 failed");
+ res = pthread_join(th1, NULL);
+ if (res != 0)
+ atf_tc_fail("pthread_join1 failed");
+
+ res = rump_sys_fchdir(fd);
+ if (res == -1)
+ atf_tc_fail("fchdir failed");
+}
+
+ATF_FSAPPLY(race, "rmdir(2) race");
diff --git a/contrib/netbsd-tests/fs/vfs/t_ro.c b/contrib/netbsd-tests/fs/vfs/t_ro.c
new file mode 100644
index 0000000..b1e1179
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_ro.c
@@ -0,0 +1,203 @@
+/* $NetBSD: t_ro.c,v 1.5 2011/02/22 21:23:19 yamt Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rump/rump_syscalls.h>
+#include <rump/rump.h>
+
+#include "../common/h_fsmacros.h"
+#include "../../h_macros.h"
+
+#define AFILE "testfile"
+#define ADIR "testdir"
+#define AFIFO "testfifo"
+#define ASYMLINK "testsymlink"
+#define ALINK "testlink"
+#define FUNTEXT "this is some non-humppa text"
+#define FUNSIZE (sizeof(FUNTEXT)-1)
+
+static void
+nullgen(const atf_tc_t *tc, const char *mp)
+{
+
+ return;
+}
+
+static void
+filegen(const atf_tc_t *tc, const char *mp)
+{
+ int fd;
+
+ FSTEST_ENTER();
+ RL(fd = rump_sys_open(AFILE, O_CREAT | O_RDWR, 0777));
+ ATF_REQUIRE_EQ(rump_sys_write(fd, FUNTEXT, FUNSIZE), FUNSIZE);
+ RL(rump_sys_close(fd));
+ FSTEST_EXIT();
+}
+
+/*
+ *
+ * BEGIN tests
+ *
+ */
+
+static void
+create(const atf_tc_t *tc, const char *mp)
+{
+
+ FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_open(AFILE, O_CREAT|O_RDONLY) == -1);
+ FSTEST_EXIT();
+}
+
+static void
+rmfile(const atf_tc_t *tc, const char *mp)
+{
+
+ FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_unlink(AFILE) == -1);
+ FSTEST_EXIT();
+}
+
+static void
+fileio(const atf_tc_t *tc, const char *mp)
+{
+ int fd;
+ char buf[FUNSIZE+1];
+ int expected;
+
+ if (FSTYPE_NFSRO(tc))
+ expected = EACCES;
+ else
+ expected = EROFS;
+
+ FSTEST_ENTER();
+ RL(fd = rump_sys_open(AFILE, O_RDONLY));
+ ATF_REQUIRE_EQ(rump_sys_read(fd, buf, FUNSIZE), FUNSIZE);
+ buf[FUNSIZE] = '\0';
+ ATF_REQUIRE_STREQ(buf, FUNTEXT);
+ RL(rump_sys_close(fd));
+
+ ATF_REQUIRE_ERRNO(expected, rump_sys_open(AFILE, O_WRONLY) == -1);
+ ATF_REQUIRE_ERRNO(expected, rump_sys_open(AFILE, O_RDWR) == -1);
+ FSTEST_EXIT();
+}
+
+static void
+attrs(const atf_tc_t *tc, const char *mp)
+{
+ struct timeval sometvs[2];
+ struct stat sb;
+ int fd;
+
+ FSTEST_ENTER();
+
+ RL(rump_sys_stat(AFILE, &sb));
+
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_chmod(AFILE, 0775) == -1);
+ if (!FSTYPE_MSDOS(tc))
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_chown(AFILE, 1, 1) == -1);
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_utimes(AFILE, sometvs) == -1);
+
+ RL(fd = rump_sys_open(AFILE, O_RDONLY));
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_fchmod(fd, 0775) == -1);
+ if (!FSTYPE_MSDOS(tc))
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_fchown(fd, 1, 1) == -1);
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_futimes(fd, sometvs) == -1);
+ RL(rump_sys_close(fd));
+
+ FSTEST_EXIT();
+}
+
+static void
+createdir(const atf_tc_t *tc, const char *mp)
+{
+
+ FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_mkdir(ADIR, 0775) == -1);
+ FSTEST_EXIT();
+}
+
+static void
+createfifo(const atf_tc_t *tc, const char *mp)
+{
+
+ FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_mkfifo(AFIFO, 0775) == -1);
+ FSTEST_EXIT();
+}
+
+static void
+createsymlink(const atf_tc_t *tc, const char *mp)
+{
+
+ FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_symlink("hoge", ASYMLINK) == -1);
+ FSTEST_EXIT();
+}
+
+static void
+createlink(const atf_tc_t *tc, const char *mp)
+{
+
+ FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(EROFS, rump_sys_link(AFILE, ALINK) == -1);
+ FSTEST_EXIT();
+}
+
+ATF_TC_FSAPPLY_RO(create, "create file on r/o mount", nullgen);
+ATF_TC_FSAPPLY_RO(rmfile, "remove file from r/o mount", filegen);
+ATF_TC_FSAPPLY_RO(fileio, "can read a file but not write it", filegen);
+ATF_TC_FSAPPLY_RO(attrs, "can query but not change attributes", filegen);
+ATF_TC_FSAPPLY_RO(createdir, "create directory on r/o mount", nullgen);
+ATF_TC_FSAPPLY_RO(createfifo, "create fifo on r/o mount", nullgen);
+ATF_TC_FSAPPLY_RO(createsymlink, "create symlink on r/o mount", nullgen);
+ATF_TC_FSAPPLY_RO(createlink, "create hardlink on r/o mount", filegen);
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY_RO(create);
+ ATF_TP_FSAPPLY_RO(rmfile);
+ ATF_TP_FSAPPLY_RO(fileio);
+ ATF_TP_FSAPPLY_RO(attrs);
+ ATF_TP_FSAPPLY_RO(createdir);
+ ATF_TP_FSAPPLY_RO(createfifo);
+ ATF_TP_FSAPPLY_RO(createsymlink);
+ ATF_TP_FSAPPLY_RO(createlink);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/fs/vfs/t_union.c b/contrib/netbsd-tests/fs/vfs/t_union.c
new file mode 100644
index 0000000..bdcef93
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_union.c
@@ -0,0 +1,204 @@
+/* $NetBSD: t_union.c,v 1.8 2011/08/07 06:01:51 hannken Exp $ */
+
+#include <sys/types.h>
+#include <sys/mount.h>
+
+#include <atf-c.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <rump/rump.h>
+#include <rump/rump_syscalls.h>
+
+#include <miscfs/union/union.h>
+
+#include "../../h_macros.h"
+#include "../common/h_fsmacros.h"
+
+#define MSTR "magic bus"
+
+static void
+xput_tfile(const char *mp, const char *path)
+{
+ char pathb[MAXPATHLEN];
+ int fd;
+
+ strcpy(pathb, mp);
+ strcat(pathb, "/");
+ strcat(pathb, path);
+
+ RL(fd = rump_sys_open(pathb, O_CREAT | O_RDWR, 0777));
+ if (rump_sys_write(fd, MSTR, sizeof(MSTR)) != sizeof(MSTR))
+ atf_tc_fail_errno("write to testfile");
+ RL(rump_sys_close(fd));
+}
+
+static int
+xread_tfile(const char *mp, const char *path)
+{
+ char pathb[MAXPATHLEN];
+ char buf[128];
+ int fd;
+
+ strcpy(pathb, mp);
+ strcat(pathb, "/");
+ strcat(pathb, path);
+
+ fd = rump_sys_open(pathb, O_RDONLY);
+ if (fd == -1)
+ return errno;
+ if (rump_sys_read(fd, buf, sizeof(buf)) == -1)
+ atf_tc_fail_errno("read tfile");
+ RL(rump_sys_close(fd));
+ if (strcmp(buf, MSTR) == 0)
+ return 0;
+ return EPROGMISMATCH;
+}
+
+/*
+ * Mount a unionfs for testing. Before calling, "mp" contains
+ * the upper layer. Lowerpath is constructed so that the directory
+ * contains rumpfs.
+ */
+static void
+mountunion(const char *mp, char *lowerpath)
+{
+ struct union_args unionargs;
+
+ sprintf(lowerpath, "/lower");
+ rump_sys_mkdir(lowerpath, 0777);
+
+ /* mount the union with our testfs as the upper layer */
+ memset(&unionargs, 0, sizeof(unionargs));
+ unionargs.target = lowerpath;
+ unionargs.mntflags = UNMNT_BELOW;
+
+ if (rump_sys_mount(MOUNT_UNION, mp, 0,
+ &unionargs, sizeof(unionargs)) == -1) {
+ if (errno == EOPNOTSUPP) {
+ atf_tc_skip("fs does not support VOP_WHITEOUT");
+ } else {
+ atf_tc_fail_errno("union mount");
+ }
+ }
+}
+
+#if 0
+static void
+toggleroot(void)
+{
+ static int status;
+
+ status ^= MNT_RDONLY;
+
+ printf("0x%x\n", status);
+ RL(rump_sys_mount(MOUNT_RUMPFS, "/", status | MNT_UPDATE, NULL, 0));
+}
+#endif
+
+#define TFILE "tensti"
+#define TDIR "testdir"
+#define TDFILE TDIR "/indir"
+
+static void
+basic(const atf_tc_t *tc, const char *mp)
+{
+ char lowerpath[MAXPATHLEN];
+ char dbuf[8192];
+ struct stat sb;
+ struct dirent *dp;
+ int error, fd, dsize;
+
+ mountunion(mp, lowerpath);
+
+ /* create a file in the lower layer */
+ xput_tfile(lowerpath, TFILE);
+
+ /* first, test we can read the old file from the new namespace */
+ error = xread_tfile(mp, TFILE);
+ if (error != 0)
+ atf_tc_fail("union compare failed: %d (%s)",
+ error, strerror(error));
+
+ /* then, test upper layer writes don't affect the lower layer */
+ xput_tfile(mp, "kiekko");
+ if ((error = xread_tfile(lowerpath, "kiekko")) != ENOENT)
+ atf_tc_fail("invisibility failed: %d (%s)",
+ error, strerror(error));
+
+ /* check that we can whiteout stuff in the upper layer */
+ FSTEST_ENTER();
+ RL(rump_sys_unlink(TFILE));
+ ATF_REQUIRE_ERRNO(ENOENT, rump_sys_stat(TFILE, &sb) == -1);
+ FSTEST_EXIT();
+
+ /* check that the removed node is not in the directory listing */
+ RL(fd = rump_sys_open(mp, O_RDONLY));
+ RL(dsize = rump_sys_getdents(fd, dbuf, sizeof(dbuf)));
+ for (dp = (struct dirent *)dbuf;
+ (char *)dp < dbuf + dsize;
+ dp = _DIRENT_NEXT(dp)) {
+ if (strcmp(dp->d_name, TFILE) == 0 && dp->d_type != DT_WHT)
+ atf_tc_fail("removed file non-white-outed");
+ }
+ RL(rump_sys_close(fd));
+
+ RL(rump_sys_unmount(mp, 0));
+}
+
+static void
+whiteout(const atf_tc_t *tc, const char *mp)
+{
+ char lower[MAXPATHLEN];
+ struct stat sb;
+ void *fsarg;
+
+ /*
+ * XXX: use ffs here to make sure any screwups in rumpfs don't
+ * affect the test
+ */
+ RL(ffs_fstest_newfs(tc, &fsarg, "daimage", 1024*1024*5, NULL));
+ RL(ffs_fstest_mount(tc, fsarg, "/lower", 0));
+
+ /* create a file in the lower layer */
+ RL(rump_sys_chdir("/lower"));
+ RL(rump_sys_mkdir(TDIR, 0777));
+ RL(rump_sys_mkdir(TDFILE, 0777));
+ RL(rump_sys_chdir("/"));
+
+ RL(ffs_fstest_unmount(tc, "/lower", 0));
+ RL(ffs_fstest_mount(tc, fsarg, "/lower", MNT_RDONLY));
+
+ mountunion(mp, lower);
+
+ FSTEST_ENTER();
+ ATF_REQUIRE_ERRNO(ENOTEMPTY, rump_sys_rmdir(TDIR) == -1);
+ RL(rump_sys_rmdir(TDFILE));
+ RL(rump_sys_rmdir(TDIR));
+ ATF_REQUIRE_ERRNO(ENOENT, rump_sys_stat(TDFILE, &sb) == -1);
+ ATF_REQUIRE_ERRNO(ENOENT, rump_sys_stat(TDIR, &sb) == -1);
+
+ RL(rump_sys_mkdir(TDIR, 0777));
+ RL(rump_sys_stat(TDIR, &sb));
+ ATF_REQUIRE_ERRNO(ENOENT, rump_sys_stat(TDFILE, &sb) == -1);
+ FSTEST_EXIT();
+
+ RL(rump_sys_unmount(mp, 0));
+}
+
+ATF_TC_FSAPPLY(basic, "check basic union functionality");
+ATF_TC_FSAPPLY(whiteout, "create whiteout in upper layer");
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY(basic);
+ ATF_TP_FSAPPLY(whiteout);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/fs/vfs/t_unpriv.c b/contrib/netbsd-tests/fs/vfs/t_unpriv.c
new file mode 100644
index 0000000..fffffe4
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_unpriv.c
@@ -0,0 +1,241 @@
+/* $NetBSD: t_unpriv.c,v 1.11 2014/08/29 17:39:18 gson Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <atf-c.h>
+#include <libgen.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include <rump/rump_syscalls.h>
+#include <rump/rump.h>
+
+#include "../common/h_fsmacros.h"
+#include "../../h_macros.h"
+
+#define USES_OWNER \
+ if (FSTYPE_MSDOS(tc)) \
+ atf_tc_skip("owner not supported by file system")
+
+static void
+owner(const atf_tc_t *tc, const char *mp)
+{
+
+ USES_OWNER;
+
+ FSTEST_ENTER();
+
+ rump_pub_lwproc_rfork(RUMP_RFCFDG);
+ if (rump_sys_setuid(1) == -1)
+ atf_tc_fail_errno("setuid");
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (rump_sys_chown(".", 1, -1) != -1 || errno != EPERM)
+ atf_tc_fail_errno("chown");
+ if (rump_sys_chmod(".", 0000) != -1 || errno != EPERM)
+ atf_tc_fail_errno("chmod");
+ rump_pub_lwproc_releaselwp();
+
+ if (rump_sys_chown(".", 1, -1) == -1)
+ atf_tc_fail_errno("chown");
+
+ rump_pub_lwproc_rfork(RUMP_RFCFDG);
+ if (rump_sys_setuid(1) == -1)
+ atf_tc_fail_errno("setuid");
+ if (rump_sys_chown(".", 1, -1) == -1)
+ atf_tc_fail_errno("chown");
+ if (rump_sys_chmod(".", 0000) == -1)
+ atf_tc_fail_errno("chmod");
+ rump_pub_lwproc_releaselwp();
+
+ FSTEST_EXIT();
+}
+
+static void
+dirperms(const atf_tc_t *tc, const char *mp)
+{
+ char name[] = "dir.test/file.test";
+ char *dir = dirname(name);
+ int fd;
+
+ if (FSTYPE_SYSVBFS(tc))
+ atf_tc_skip("directories not supported by file system");
+
+ FSTEST_ENTER();
+
+ if (rump_sys_mkdir(dir, 0777) == -1)
+ atf_tc_fail_errno("mkdir");
+
+ rump_pub_lwproc_rfork(RUMP_RFCFDG);
+ if (rump_sys_setuid(1) == -1)
+ atf_tc_fail_errno("setuid");
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (rump_sys_open(name, O_RDWR|O_CREAT, 0666) != -1 || errno != EACCES)
+ atf_tc_fail_errno("open");
+ rump_pub_lwproc_releaselwp();
+
+ if ((fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)) == -1)
+ atf_tc_fail_errno("open");
+ if (rump_sys_close(fd) == -1)
+ atf_tc_fail_errno("close");
+
+ rump_pub_lwproc_rfork(RUMP_RFCFDG);
+ if (rump_sys_setuid(1) == -1)
+ atf_tc_fail_errno("setuid");
+ if (rump_sys_unlink(name) != -1 || errno != EACCES)
+ atf_tc_fail_errno("unlink");
+ rump_pub_lwproc_releaselwp();
+
+ if (rump_sys_unlink(name) == -1)
+ atf_tc_fail_errno("unlink");
+
+ if (rump_sys_rmdir(dir) == -1)
+ atf_tc_fail_errno("rmdir");
+
+ FSTEST_EXIT();
+}
+
+static void
+times(const atf_tc_t *tc, const char *mp)
+{
+ const char *name = "file.test";
+ int fd;
+ unsigned int i, j;
+ struct timeval tmv[2];
+ static struct timeval tmvs[] = {
+ { QUAD_MIN, 0 },
+ { 0, 0 },
+ { QUAD_MAX, 999999 }
+ };
+
+ FSTEST_ENTER();
+
+ if ((fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)) == -1)
+ atf_tc_fail_errno("open");
+ if (rump_sys_close(fd) == -1)
+ atf_tc_fail_errno("close");
+
+ rump_pub_lwproc_rfork(RUMP_RFCFDG);
+ if (rump_sys_setuid(1) == -1)
+ atf_tc_fail_errno("setuid");
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (rump_sys_utimes(name, NULL) != -1 || errno != EACCES)
+ atf_tc_fail_errno("utimes");
+ rump_pub_lwproc_releaselwp();
+
+ if (rump_sys_utimes(name, NULL) == -1)
+ atf_tc_fail_errno("utimes");
+
+ for (i = 0; i < sizeof(tmvs) / sizeof(tmvs[0]); i++) {
+ for (j = 0; j < sizeof(tmvs) / sizeof(tmvs[0]); j++) {
+ tmv[0] = tmvs[i];
+ tmv[1] = tmvs[j];
+ rump_pub_lwproc_rfork(RUMP_RFCFDG);
+ if (rump_sys_setuid(1) == -1)
+ atf_tc_fail_errno("setuid");
+ if (rump_sys_utimes(name, tmv) != -1 || errno != EPERM)
+ atf_tc_fail_errno("utimes");
+ rump_pub_lwproc_releaselwp();
+
+ if (rump_sys_utimes(name, tmv) == -1)
+ atf_tc_fail_errno("utimes");
+ }
+ }
+
+ if (rump_sys_unlink(name) == -1)
+ atf_tc_fail_errno("unlink");
+
+ FSTEST_EXIT();
+}
+
+static void
+flags(const atf_tc_t *tc, const char *mp)
+{
+ const char *name = "file.test";
+ int fd, fflags;
+ struct stat st;
+
+ FSTEST_ENTER();
+
+ if ((fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)) == -1)
+ atf_tc_fail_errno("open");
+ if (rump_sys_close(fd) == -1)
+ atf_tc_fail_errno("close");
+
+ if (rump_sys_stat(name, &st) == -1)
+ atf_tc_fail_errno("stat");
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (rump_sys_chflags(name, st.st_flags) == -1) {
+ if (errno == EOPNOTSUPP)
+ atf_tc_skip("file flags not supported by file system");
+ atf_tc_fail_errno("chflags");
+ }
+
+ fflags = st.st_flags | UF_IMMUTABLE;
+
+ rump_pub_lwproc_rfork(RUMP_RFCFDG);
+ if (rump_sys_setuid(1) == -1)
+ atf_tc_fail_errno("setuid");
+ fflags |= UF_IMMUTABLE;
+ if (rump_sys_chflags(name, fflags) != -1 || errno != EPERM)
+ atf_tc_fail_errno("chflags");
+ rump_pub_lwproc_releaselwp();
+
+ if (rump_sys_chflags(name, fflags) == -1)
+ atf_tc_fail_errno("chflags");
+
+ fflags &= ~UF_IMMUTABLE;
+ if (rump_sys_chflags(name, fflags) == -1)
+ atf_tc_fail_errno("chflags");
+
+ if (rump_sys_unlink(name) == -1)
+ atf_tc_fail_errno("unlink");
+
+ FSTEST_EXIT();
+}
+
+ATF_TC_FSAPPLY(owner, "owner unprivileged checks");
+ATF_TC_FSAPPLY(dirperms, "directory permission checks");
+ATF_TC_FSAPPLY(times, "time set checks");
+ATF_TC_FSAPPLY(flags, "file flags checks");
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY(owner);
+ ATF_TP_FSAPPLY(dirperms);
+ ATF_TP_FSAPPLY(times);
+ ATF_TP_FSAPPLY(flags);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/fs/vfs/t_vfsops.c b/contrib/netbsd-tests/fs/vfs/t_vfsops.c
new file mode 100644
index 0000000..1bcee89
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_vfsops.c
@@ -0,0 +1,211 @@
+/* $NetBSD: t_vfsops.c,v 1.11 2011/04/04 19:16:58 hannken Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+
+#include <atf-c.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rump/rump_syscalls.h>
+#include <rump/rump.h>
+
+#include "../common/h_fsmacros.h"
+#include "../../h_macros.h"
+
+static void
+tmount(const atf_tc_t *tc, const char *path)
+{
+
+ return;
+}
+
+static void
+tstatvfs(const atf_tc_t *tc, const char *path)
+{
+ const char *fstype = atf_tc_get_md_var(tc, "X-fs.mntname");
+ struct statvfs svb;
+
+ if (rump_sys_statvfs1(path, &svb, ST_WAIT) == -1)
+ atf_tc_fail_errno("statvfs");
+
+ ATF_REQUIRE(svb.f_namemax > 0 && svb.f_namemax <= MAXNAMLEN);
+ if (!(FSTYPE_PUFFS(tc) || FSTYPE_P2K_FFS(tc)))
+ ATF_REQUIRE_STREQ(svb.f_fstypename, fstype);
+ ATF_REQUIRE_STREQ(svb.f_mntonname, path);
+}
+
+static void
+tsync(const atf_tc_t *tc, const char *path)
+{
+
+ rump_sys_sync();
+}
+
+#define MAGICSTR "just a string, I like A"
+static void
+tfilehandle(const atf_tc_t *tc, const char *path)
+{
+ char fpath[MAXPATHLEN];
+ char buf[sizeof(MAGICSTR)];
+ size_t fhsize;
+ void *fhp;
+ int fd;
+
+ sprintf(fpath, "%s/file", path);
+ fd = rump_sys_open(fpath, O_RDWR | O_CREAT, 0777);
+ if (fd == -1)
+ atf_tc_fail_errno("open");
+
+ if (rump_sys_write(fd, MAGICSTR, sizeof(MAGICSTR)) != sizeof(MAGICSTR))
+ atf_tc_fail("write to file");
+ rump_sys_close(fd);
+
+ /*
+ * Get file handle size.
+ * This also weeds out unsupported file systems.
+ */
+ fhsize = 0;
+ if (rump_sys_getfh(fpath, NULL, &fhsize) == -1) {
+ if (errno == EOPNOTSUPP) {
+ atf_tc_skip("file handles not supported");
+ } else if (errno != E2BIG) {
+ atf_tc_fail_errno("getfh size");
+ }
+ }
+
+ fhp = malloc(fhsize);
+ if (rump_sys_getfh(fpath, fhp, &fhsize) == -1)
+ atf_tc_fail_errno("getfh");
+
+ /* open file based on file handle */
+ fd = rump_sys_fhopen(fhp, fhsize, O_RDONLY);
+ if (fd == -1) {
+ atf_tc_fail_errno("fhopen");
+ }
+
+ /* check that we got the same file */
+ if (rump_sys_read(fd, buf, sizeof(buf)) != sizeof(MAGICSTR))
+ atf_tc_fail("read fhopened file");
+
+ ATF_REQUIRE_STREQ(buf, MAGICSTR);
+
+ rump_sys_close(fd);
+}
+
+#define FNAME "a_file"
+static void
+tfhremove(const atf_tc_t *tc, const char *path)
+{
+ size_t fhsize;
+ void *fhp;
+ int fd;
+
+ RL(rump_sys_chdir(path));
+ RL(fd = rump_sys_open(FNAME, O_RDWR | O_CREAT, 0777));
+ RL(rump_sys_close(fd));
+
+ fhsize = 0;
+ if (rump_sys_getfh(FNAME, NULL, &fhsize) == -1) {
+ if (errno == EOPNOTSUPP) {
+ atf_tc_skip("file handles not supported");
+ } else if (errno != E2BIG) {
+ atf_tc_fail_errno("getfh size");
+ }
+ }
+
+ fhp = malloc(fhsize);
+ RL(rump_sys_getfh(FNAME, fhp, &fhsize));
+ RL(rump_sys_unlink(FNAME));
+
+ if (FSTYPE_LFS(tc))
+ atf_tc_expect_fail("fhopen() for removed file succeeds "
+ "(PR kern/43745)");
+ ATF_REQUIRE_ERRNO(ESTALE, rump_sys_fhopen(fhp, fhsize, O_RDONLY) == -1);
+ atf_tc_expect_pass();
+
+ RL(rump_sys_chdir("/"));
+}
+#undef FNAME
+
+/*
+ * This test only checks the file system doesn't crash. We *might*
+ * try a valid file handle.
+ */
+static void
+tfhinval(const atf_tc_t *tc, const char *path)
+{
+ size_t fhsize;
+ void *fhp;
+ unsigned long seed;
+ int fd;
+
+ srandom(seed = time(NULL));
+ printf("RNG seed %lu\n", seed);
+
+ RL(rump_sys_chdir(path));
+ fhsize = 0;
+ if (rump_sys_getfh(".", NULL, &fhsize) == -1) {
+ if (errno == EOPNOTSUPP) {
+ atf_tc_skip("file handles not supported");
+ } else if (errno != E2BIG) {
+ atf_tc_fail_errno("getfh size");
+ }
+ }
+
+ fhp = malloc(fhsize);
+ tests_makegarbage(fhp, fhsize);
+ fd = rump_sys_fhopen(fhp, fhsize, O_RDWR);
+ if (fd != -1)
+ rump_sys_close(fd);
+
+ RL(rump_sys_chdir("/"));
+}
+
+ATF_TC_FSAPPLY(tmount, "mount/unmount");
+ATF_TC_FSAPPLY(tstatvfs, "statvfs");
+ATF_TC_FSAPPLY(tsync, "sync");
+ATF_TC_FSAPPLY(tfilehandle, "file handles");
+ATF_TC_FSAPPLY(tfhremove, "fhtovp for removed file");
+ATF_TC_FSAPPLY(tfhinval, "fhopen invalid filehandle");
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY(tmount);
+ ATF_TP_FSAPPLY(tstatvfs);
+ ATF_TP_FSAPPLY(tsync);
+ ATF_TP_FSAPPLY(tfilehandle);
+ ATF_TP_FSAPPLY(tfhremove);
+ ATF_TP_FSAPPLY(tfhinval);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/fs/vfs/t_vnops.c b/contrib/netbsd-tests/fs/vfs/t_vnops.c
new file mode 100644
index 0000000..66b5505
--- /dev/null
+++ b/contrib/netbsd-tests/fs/vfs/t_vnops.c
@@ -0,0 +1,1001 @@
+/* $NetBSD: t_vnops.c,v 1.43 2014/09/09 06:51:00 gson Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+
+#include <assert.h>
+#include <atf-c.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rump_syscalls.h>
+#include <rump/rump.h>
+
+#include "../common/h_fsmacros.h"
+#include "../../h_macros.h"
+
+#define TESTFILE "afile"
+
+#define USES_DIRS \
+ if (FSTYPE_SYSVBFS(tc)) \
+ atf_tc_skip("directories not supported by file system")
+
+#define USES_SYMLINKS \
+ if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc)) \
+ atf_tc_skip("symlinks not supported by file system")
+
+static char *
+md(char *buf, const char *base, const char *tail)
+{
+
+ sprintf(buf, "%s/%s", base, tail);
+ return buf;
+}
+
+static void
+lookup_simple(const atf_tc_t *tc, const char *mountpath)
+{
+ char pb[MAXPATHLEN], final[MAXPATHLEN];
+ struct stat sb1, sb2;
+
+ strcpy(final, mountpath);
+ sprintf(pb, "%s/../%s", mountpath, basename(final));
+ if (rump_sys_stat(pb, &sb1) == -1)
+ atf_tc_fail_errno("stat 1");
+
+ sprintf(pb, "%s/./../%s", mountpath, basename(final));
+ if (rump_sys_stat(pb, &sb2) == -1)
+ atf_tc_fail_errno("stat 2");
+
+ ATF_REQUIRE(memcmp(&sb1, &sb2, sizeof(sb1)) == 0);
+}
+
+static void
+lookup_complex(const atf_tc_t *tc, const char *mountpath)
+{
+ char pb[MAXPATHLEN];
+ struct stat sb1, sb2;
+
+ USES_DIRS;
+
+ if (FSTYPE_UDF(tc))
+ atf_tc_expect_fail("PR kern/49033");
+
+ sprintf(pb, "%s/dir", mountpath);
+ if (rump_sys_mkdir(pb, 0777) == -1)
+ atf_tc_fail_errno("mkdir");
+ if (rump_sys_stat(pb, &sb1) == -1)
+ atf_tc_fail_errno("stat 1");
+
+ sprintf(pb, "%s/./dir/../././dir/.", mountpath);
+ if (rump_sys_stat(pb, &sb2) == -1)
+ atf_tc_fail_errno("stat 2");
+
+ if (memcmp(&sb1, &sb2, sizeof(sb1)) != 0) {
+ printf("what\tsb1\t\tsb2\n");
+
+#define FIELD(FN) \
+ printf(#FN "\t%lld\t%lld\n", \
+ (long long)sb1.FN, (long long)sb2.FN)
+#define TIME(FN) \
+ printf(#FN "\t%lld.%ld\t%lld.%ld\n", \
+ (long long)sb1.FN.tv_sec, sb1.FN.tv_nsec, \
+ (long long)sb2.FN.tv_sec, sb2.FN.tv_nsec)
+
+ FIELD(st_dev);
+ FIELD(st_mode);
+ FIELD(st_ino);
+ FIELD(st_nlink);
+ FIELD(st_uid);
+ FIELD(st_gid);
+ FIELD(st_rdev);
+ TIME(st_atim);
+ TIME(st_mtim);
+ TIME(st_ctim);
+ TIME(st_birthtim);
+ FIELD(st_size);
+ FIELD(st_blocks);
+ FIELD(st_flags);
+ FIELD(st_gen);
+
+#undef FIELD
+#undef TIME
+
+ atf_tc_fail("stat results differ, see ouput for more details");
+ }
+ if (FSTYPE_UDF(tc))
+ atf_tc_fail("random failure of PR kern/49033 "
+ "did not happen this time");
+}
+
+static void
+dir_simple(const atf_tc_t *tc, const char *mountpath)
+{
+ char pb[MAXPATHLEN];
+ struct stat sb;
+
+ USES_DIRS;
+
+ /* check we can create directories */
+ sprintf(pb, "%s/dir", mountpath);
+ if (rump_sys_mkdir(pb, 0777) == -1)
+ atf_tc_fail_errno("mkdir");
+ if (rump_sys_stat(pb, &sb) == -1)
+ atf_tc_fail_errno("stat new directory");
+
+ /* check we can remove then and that it makes them unreachable */
+ if (rump_sys_rmdir(pb) == -1)
+ atf_tc_fail_errno("rmdir");
+ if (rump_sys_stat(pb, &sb) != -1 || errno != ENOENT)
+ atf_tc_fail("ENOENT expected from stat");
+}
+
+static void
+dir_notempty(const atf_tc_t *tc, const char *mountpath)
+{
+ char pb[MAXPATHLEN], pb2[MAXPATHLEN];
+ int fd, rv;
+
+ USES_DIRS;
+
+ /* check we can create directories */
+ sprintf(pb, "%s/dir", mountpath);
+ if (rump_sys_mkdir(pb, 0777) == -1)
+ atf_tc_fail_errno("mkdir");
+
+ sprintf(pb2, "%s/dir/file", mountpath);
+ fd = rump_sys_open(pb2, O_RDWR | O_CREAT, 0777);
+ if (fd == -1)
+ atf_tc_fail_errno("create file");
+ rump_sys_close(fd);
+
+ rv = rump_sys_rmdir(pb);
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (rv != -1 || errno != ENOTEMPTY)
+ atf_tc_fail("non-empty directory removed succesfully");
+
+ if (rump_sys_unlink(pb2) == -1)
+ atf_tc_fail_errno("cannot remove dir/file");
+
+ if (rump_sys_rmdir(pb) == -1)
+ atf_tc_fail_errno("remove directory");
+}
+
+static void
+dir_rmdirdotdot(const atf_tc_t *tc, const char *mp)
+{
+ char pb[MAXPATHLEN];
+ int xerrno;
+
+ USES_DIRS;
+
+ FSTEST_ENTER();
+ RL(rump_sys_mkdir("test", 0777));
+ RL(rump_sys_chdir("test"));
+
+ RL(rump_sys_mkdir("subtest", 0777));
+ RL(rump_sys_chdir("subtest"));
+
+ md(pb, mp, "test/subtest");
+ RL(rump_sys_rmdir(pb));
+ md(pb, mp, "test");
+ RL(rump_sys_rmdir(pb));
+
+ if (FSTYPE_NFS(tc))
+ xerrno = ESTALE;
+ else
+ xerrno = ENOENT;
+ ATF_REQUIRE_ERRNO(xerrno, rump_sys_chdir("..") == -1);
+ FSTEST_EXIT();
+}
+
+static void
+checkfile(const char *path, struct stat *refp)
+{
+ char buf[MAXPATHLEN];
+ struct stat sb;
+ static int n = 1;
+
+ md(buf, path, "file");
+ if (rump_sys_stat(buf, &sb) == -1)
+ atf_tc_fail_errno("cannot stat file %d (%s)", n, buf);
+ if (memcmp(&sb, refp, sizeof(sb)) != 0)
+ atf_tc_fail("stat mismatch %d", n);
+ n++;
+}
+
+static void
+rename_dir(const atf_tc_t *tc, const char *mp)
+{
+ char pb1[MAXPATHLEN], pb2[MAXPATHLEN], pb3[MAXPATHLEN];
+ struct stat ref, sb;
+
+ if (FSTYPE_RUMPFS(tc))
+ atf_tc_skip("rename not supported by file system");
+
+ USES_DIRS;
+
+ md(pb1, mp, "dir1");
+ if (rump_sys_mkdir(pb1, 0777) == -1)
+ atf_tc_fail_errno("mkdir 1");
+
+ md(pb2, mp, "dir2");
+ if (rump_sys_mkdir(pb2, 0777) == -1)
+ atf_tc_fail_errno("mkdir 2");
+ md(pb2, mp, "dir2/subdir");
+ if (rump_sys_mkdir(pb2, 0777) == -1)
+ atf_tc_fail_errno("mkdir 3");
+
+ md(pb3, mp, "dir1/file");
+ if (rump_sys_mknod(pb3, S_IFREG | 0777, -1) == -1)
+ atf_tc_fail_errno("create file");
+ if (rump_sys_stat(pb3, &ref) == -1)
+ atf_tc_fail_errno("stat of file");
+
+ /*
+ * First try ops which should succeed.
+ */
+
+ /* rename within directory */
+ md(pb3, mp, "dir3");
+ if (rump_sys_rename(pb1, pb3) == -1)
+ atf_tc_fail_errno("rename 1");
+ checkfile(pb3, &ref);
+
+ /* rename directory onto itself (two ways, should fail) */
+ md(pb1, mp, "dir3/.");
+ if (rump_sys_rename(pb1, pb3) != -1 || errno != EINVAL)
+ atf_tc_fail_errno("rename 2");
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (rump_sys_rename(pb3, pb1) != -1 || errno != EISDIR)
+ atf_tc_fail_errno("rename 3");
+
+ checkfile(pb3, &ref);
+
+ /* rename father of directory into directory */
+ md(pb1, mp, "dir2/dir");
+ md(pb2, mp, "dir2");
+ if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
+ atf_tc_fail_errno("rename 4");
+
+ /* same for grandfather */
+ md(pb1, mp, "dir2/subdir/dir2");
+ if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL)
+ atf_tc_fail("rename 5");
+
+ checkfile(pb3, &ref);
+
+ /* rename directory over a non-empty directory */
+ if (rump_sys_rename(pb2, pb3) != -1 || errno != ENOTEMPTY)
+ atf_tc_fail("rename 6");
+
+ /* cross-directory rename */
+ md(pb1, mp, "dir3");
+ md(pb2, mp, "dir2/somedir");
+ if (rump_sys_rename(pb1, pb2) == -1)
+ atf_tc_fail_errno("rename 7");
+ checkfile(pb2, &ref);
+
+ /* move to parent directory */
+ md(pb1, mp, "dir2/somedir/../../dir3");
+ if (rump_sys_rename(pb2, pb1) == -1)
+ atf_tc_fail_errno("rename 8");
+ md(pb1, mp, "dir2/../dir3");
+ checkfile(pb1, &ref);
+
+ /* atomic cross-directory rename */
+ md(pb3, mp, "dir2/subdir");
+ if (rump_sys_rename(pb1, pb3) == -1)
+ atf_tc_fail_errno("rename 9");
+ checkfile(pb3, &ref);
+
+ /* rename directory over an empty directory */
+ md(pb1, mp, "parent");
+ md(pb2, mp, "parent/dir1");
+ md(pb3, mp, "parent/dir2");
+ RL(rump_sys_mkdir(pb1, 0777));
+ RL(rump_sys_mkdir(pb2, 0777));
+ RL(rump_sys_mkdir(pb3, 0777));
+ RL(rump_sys_rename(pb2, pb3));
+
+ RL(rump_sys_stat(pb1, &sb));
+ if (! FSTYPE_MSDOS(tc))
+ ATF_CHECK_EQ(sb.st_nlink, 3);
+ RL(rump_sys_rmdir(pb3));
+ RL(rump_sys_rmdir(pb1));
+}
+
+static void
+rename_dotdot(const atf_tc_t *tc, const char *mp)
+{
+
+ if (FSTYPE_RUMPFS(tc))
+ atf_tc_skip("rename not supported by file system");
+
+ USES_DIRS;
+
+ if (rump_sys_chdir(mp) == -1)
+ atf_tc_fail_errno("chdir mountpoint");
+
+ if (rump_sys_mkdir("dir1", 0777) == -1)
+ atf_tc_fail_errno("mkdir 1");
+ if (rump_sys_mkdir("dir2", 0777) == -1)
+ atf_tc_fail_errno("mkdir 2");
+
+ if (rump_sys_rename("dir1", "dir1/..") != -1 || errno != EINVAL)
+ atf_tc_fail_errno("self-dotdot to");
+
+ if (rump_sys_rename("dir1/..", "sometarget") != -1 || errno != EINVAL)
+ atf_tc_fail_errno("self-dotdot from");
+
+ if (rump_sys_rename("dir1", "dir2/..") != -1 || errno != EINVAL)
+ atf_tc_fail("other-dotdot");
+
+ rump_sys_chdir("/");
+}
+
+static void
+rename_reg_nodir(const atf_tc_t *tc, const char *mp)
+{
+ bool haslinks;
+ struct stat sb;
+ ino_t f1ino;
+
+ if (FSTYPE_RUMPFS(tc))
+ atf_tc_skip("rename not supported by file system");
+
+ if (rump_sys_chdir(mp) == -1)
+ atf_tc_fail_errno("chdir mountpoint");
+
+ if (FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))
+ haslinks = false;
+ else
+ haslinks = true;
+
+ if (rump_sys_mknod("file1", S_IFREG | 0777, -1) == -1)
+ atf_tc_fail_errno("create file");
+ if (rump_sys_mknod("file2", S_IFREG | 0777, -1) == -1)
+ atf_tc_fail_errno("create file");
+
+ if (rump_sys_stat("file1", &sb) == -1)
+ atf_tc_fail_errno("stat");
+ f1ino = sb.st_ino;
+
+ if (haslinks) {
+ if (rump_sys_link("file1", "file_link") == -1)
+ atf_tc_fail_errno("link");
+ if (rump_sys_stat("file_link", &sb) == -1)
+ atf_tc_fail_errno("stat");
+ ATF_REQUIRE_EQ(sb.st_ino, f1ino);
+ ATF_REQUIRE_EQ(sb.st_nlink, 2);
+ }
+
+ if (rump_sys_stat("file2", &sb) == -1)
+ atf_tc_fail_errno("stat");
+
+ if (rump_sys_rename("file1", "file3") == -1)
+ atf_tc_fail_errno("rename 1");
+ if (rump_sys_stat("file3", &sb) == -1)
+ atf_tc_fail_errno("stat 1");
+ if (haslinks) {
+ ATF_REQUIRE_EQ(sb.st_ino, f1ino);
+ }
+ if (rump_sys_stat("file1", &sb) != -1 || errno != ENOENT)
+ atf_tc_fail_errno("source 1");
+
+ if (rump_sys_rename("file3", "file2") == -1)
+ atf_tc_fail_errno("rename 2");
+ if (rump_sys_stat("file2", &sb) == -1)
+ atf_tc_fail_errno("stat 2");
+ if (haslinks) {
+ ATF_REQUIRE_EQ(sb.st_ino, f1ino);
+ }
+
+ if (rump_sys_stat("file3", &sb) != -1 || errno != ENOENT)
+ atf_tc_fail_errno("source 2");
+
+ if (haslinks) {
+ if (rump_sys_rename("file2", "file_link") == -1)
+ atf_tc_fail_errno("rename hardlink");
+ if (rump_sys_stat("file2", &sb) != -1 || errno != ENOENT)
+ atf_tc_fail_errno("source 3");
+ if (rump_sys_stat("file_link", &sb) == -1)
+ atf_tc_fail_errno("stat 2");
+ ATF_REQUIRE_EQ(sb.st_ino, f1ino);
+ ATF_REQUIRE_EQ(sb.st_nlink, 1);
+ }
+
+ ATF_CHECK_ERRNO(EFAULT, rump_sys_rename("file2", NULL) == -1);
+ ATF_CHECK_ERRNO(EFAULT, rump_sys_rename(NULL, "file2") == -1);
+
+ rump_sys_chdir("/");
+}
+
+static void
+create_nametoolong(const atf_tc_t *tc, const char *mp)
+{
+ char *name;
+ int fd;
+ long val;
+ size_t len;
+
+ if (rump_sys_chdir(mp) == -1)
+ atf_tc_fail_errno("chdir mountpoint");
+
+ val = rump_sys_pathconf(".", _PC_NAME_MAX);
+ if (val == -1)
+ atf_tc_fail_errno("pathconf");
+
+ len = val + 1;
+ name = malloc(len+1);
+ if (name == NULL)
+ atf_tc_fail_errno("malloc");
+
+ memset(name, 'a', len);
+ *(name+len) = '\0';
+
+ val = rump_sys_pathconf(".", _PC_NO_TRUNC);
+ if (val == -1)
+ atf_tc_fail_errno("pathconf");
+
+ fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666);
+ if (val != 0 && (fd != -1 || errno != ENAMETOOLONG))
+ atf_tc_fail_errno("open");
+
+ if (val == 0 && rump_sys_close(fd) == -1)
+ atf_tc_fail_errno("close");
+ if (val == 0 && rump_sys_unlink(name) == -1)
+ atf_tc_fail_errno("unlink");
+
+ free(name);
+
+ rump_sys_chdir("/");
+}
+
+static void
+create_exist(const atf_tc_t *tc, const char *mp)
+{
+ const char *name = "hoge";
+ int fd;
+
+ RL(rump_sys_chdir(mp));
+ RL(fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666));
+ RL(rump_sys_close(fd));
+ RL(rump_sys_unlink(name));
+ RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
+ RL(rump_sys_close(fd));
+ RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666));
+ RL(rump_sys_close(fd));
+ ATF_REQUIRE_ERRNO(EEXIST,
+ (fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666)));
+ RL(rump_sys_unlink(name));
+ RL(rump_sys_chdir("/"));
+}
+
+static void
+rename_nametoolong(const atf_tc_t *tc, const char *mp)
+{
+ char *name;
+ int res, fd;
+ long val;
+ size_t len;
+
+ if (FSTYPE_RUMPFS(tc))
+ atf_tc_skip("rename not supported by file system");
+
+ if (rump_sys_chdir(mp) == -1)
+ atf_tc_fail_errno("chdir mountpoint");
+
+ val = rump_sys_pathconf(".", _PC_NAME_MAX);
+ if (val == -1)
+ atf_tc_fail_errno("pathconf");
+
+ len = val + 1;
+ name = malloc(len+1);
+ if (name == NULL)
+ atf_tc_fail_errno("malloc");
+
+ memset(name, 'a', len);
+ *(name+len) = '\0';
+
+ fd = rump_sys_open("dummy", O_RDWR|O_CREAT, 0666);
+ if (fd == -1)
+ atf_tc_fail_errno("open");
+ if (rump_sys_close(fd) == -1)
+ atf_tc_fail_errno("close");
+
+ val = rump_sys_pathconf(".", _PC_NO_TRUNC);
+ if (val == -1)
+ atf_tc_fail_errno("pathconf");
+
+ res = rump_sys_rename("dummy", name);
+ if (val != 0 && (res != -1 || errno != ENAMETOOLONG))
+ atf_tc_fail_errno("rename");
+
+ if (val == 0 && rump_sys_unlink(name) == -1)
+ atf_tc_fail_errno("unlink");
+
+ free(name);
+
+ rump_sys_chdir("/");
+}
+
+/*
+ * Test creating a symlink whose length is "len" bytes, not including
+ * the terminating NUL.
+ */
+static void
+symlink_len(const atf_tc_t *tc, const char *mp, size_t len)
+{
+ char *buf;
+ int r;
+
+ USES_SYMLINKS;
+
+ RL(rump_sys_chdir(mp));
+
+ buf = malloc(len + 1);
+ ATF_REQUIRE(buf);
+ memset(buf, 'a', len);
+ buf[len] = '\0';
+ r = rump_sys_symlink(buf, "afile");
+ if (r == -1) {
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, r);
+ } else {
+ RL(rump_sys_unlink("afile"));
+ }
+ free(buf);
+
+ RL(rump_sys_chdir("/"));
+}
+
+static void
+symlink_zerolen(const atf_tc_t *tc, const char *mp)
+{
+ symlink_len(tc, mp, 0);
+}
+
+static void
+symlink_long(const atf_tc_t *tc, const char *mp)
+{
+ /*
+ * Test lengths close to powers of two, as those are likely
+ * to be edge cases.
+ */
+ size_t len;
+ int fuzz;
+ for (len = 2; len <= 65536; len *= 2) {
+ for (fuzz = -1; fuzz <= 1; fuzz++) {
+ symlink_len(tc, mp, len + fuzz);
+ }
+ }
+}
+
+static void
+symlink_root(const atf_tc_t *tc, const char *mp)
+{
+
+ USES_SYMLINKS;
+
+ RL(rump_sys_chdir(mp));
+ RL(rump_sys_symlink("/", "foo"));
+ RL(rump_sys_chdir("foo"));
+}
+
+static void
+attrs(const atf_tc_t *tc, const char *mp)
+{
+ struct stat sb, sb2;
+ struct timeval tv[2];
+ int fd;
+
+ FSTEST_ENTER();
+ RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
+ RL(rump_sys_close(fd));
+ RL(rump_sys_stat(TESTFILE, &sb));
+ if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
+ RL(rump_sys_chown(TESTFILE, 1, 2));
+ sb.st_uid = 1;
+ sb.st_gid = 2;
+ RL(rump_sys_chmod(TESTFILE, 0123));
+ sb.st_mode = (sb.st_mode & ~ACCESSPERMS) | 0123;
+ }
+
+ tv[0].tv_sec = 1000000000; /* need something >1980 for msdosfs */
+ tv[0].tv_usec = 1;
+ tv[1].tv_sec = 1000000002; /* need even seconds for msdosfs */
+ tv[1].tv_usec = 3;
+ RL(rump_sys_utimes(TESTFILE, tv));
+ RL(rump_sys_utimes(TESTFILE, tv)); /* XXX: utimes & birthtime */
+ sb.st_atimespec.tv_sec = 1000000000;
+ sb.st_atimespec.tv_nsec = 1000;
+ sb.st_mtimespec.tv_sec = 1000000002;
+ sb.st_mtimespec.tv_nsec = 3000;
+
+ RL(rump_sys_stat(TESTFILE, &sb2));
+#define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a)
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) {
+ CHECK(st_uid);
+ CHECK(st_gid);
+ CHECK(st_mode);
+ }
+ if (!FSTYPE_MSDOS(tc)) {
+ /* msdosfs has only access date, not time */
+ CHECK(st_atimespec.tv_sec);
+ }
+ CHECK(st_mtimespec.tv_sec);
+ if (!(FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc) ||
+ FSTYPE_SYSVBFS(tc) || FSTYPE_V7FS(tc))) {
+ CHECK(st_atimespec.tv_nsec);
+ CHECK(st_mtimespec.tv_nsec);
+ }
+#undef CHECK
+
+ FSTEST_EXIT();
+}
+
+static void
+fcntl_lock(const atf_tc_t *tc, const char *mp)
+{
+ int fd, fd2;
+ struct flock l;
+ struct lwp *lwp1, *lwp2;
+
+ FSTEST_ENTER();
+ l.l_pid = 0;
+ l.l_start = l.l_len = 1024;
+ l.l_type = F_RDLCK | F_WRLCK;
+ l.l_whence = SEEK_END;
+
+ lwp1 = rump_pub_lwproc_curlwp();
+ RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755));
+ RL(rump_sys_ftruncate(fd, 8192));
+
+ /* PR kern/43321 */
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be broken");
+ RL(rump_sys_fcntl(fd, F_SETLK, &l));
+
+ /* Next, we fork and try to lock the same area */
+ RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
+ lwp2 = rump_pub_lwproc_curlwp();
+ RL(fd2 = rump_sys_open(TESTFILE, O_RDWR, 0));
+ ATF_REQUIRE_ERRNO(EAGAIN, rump_sys_fcntl(fd2, F_SETLK, &l));
+
+ /* Switch back and unlock... */
+ rump_pub_lwproc_switch(lwp1);
+ l.l_type = F_UNLCK;
+ RL(rump_sys_fcntl(fd, F_SETLK, &l));
+
+ /* ... and try to lock again */
+ rump_pub_lwproc_switch(lwp2);
+ l.l_type = F_RDLCK | F_WRLCK;
+ RL(rump_sys_fcntl(fd2, F_SETLK, &l));
+
+ RL(rump_sys_close(fd2));
+ rump_pub_lwproc_releaselwp();
+
+ RL(rump_sys_close(fd));
+
+ FSTEST_EXIT();
+}
+
+static int
+flock_compare(const void *p, const void *q)
+{
+ int a = ((const struct flock *)p)->l_start;
+ int b = ((const struct flock *)q)->l_start;
+ return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+/*
+ * Find all locks set by fcntl_getlock_pids test
+ * using GETLK for a range [start, start+end], and,
+ * if there is a blocking lock, recursively find
+ * all locks to the left (toward the beginning of
+ * a file) and to the right of the lock.
+ * The function also understands "until end of file"
+ * convention when len==0.
+ */
+static unsigned int
+fcntl_getlocks(int fildes, off_t start, off_t len,
+ struct flock *lock, struct flock *end)
+{
+ unsigned int rv = 0;
+ const struct flock l = { start, len, 0, F_RDLCK, SEEK_SET };
+
+ if (lock == end)
+ return rv;
+
+ RL(rump_sys_fcntl(fildes, F_GETLK, &l));
+
+ if (l.l_type == F_UNLCK)
+ return rv;
+
+ *lock++ = l;
+ rv += 1;
+
+ ATF_REQUIRE(l.l_whence == SEEK_SET);
+
+ if (l.l_start > start) {
+ unsigned int n =
+ fcntl_getlocks(fildes, start, l.l_start - start, lock, end);
+ rv += n;
+ lock += n;
+ if (lock == end)
+ return rv;
+ }
+
+ if (l.l_len == 0) /* does l spans until the end? */
+ return rv;
+
+ if (len == 0) /* are we looking for locks until the end? */ {
+ rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end);
+ } else if (l.l_start + l.l_len < start + len) {
+ len -= l.l_start + l.l_len - start;
+ rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end);
+ }
+
+ return rv;
+}
+
+static void
+fcntl_getlock_pids(const atf_tc_t *tc, const char *mp)
+{
+ /* test non-overlaping ranges */
+ struct flock expect[4];
+ const struct flock lock[4] = {
+ { 0, 2, 0, F_WRLCK, SEEK_SET },
+ { 2, 1, 0, F_WRLCK, SEEK_SET },
+ { 7, 5, 0, F_WRLCK, SEEK_SET },
+ { 4, 3, 0, F_WRLCK, SEEK_SET },
+ };
+
+ /* Add extra element to make sure recursion does't stop at array end */
+ struct flock result[5];
+
+ /* Add 5th process */
+ int fd[5];
+ pid_t pid[5];
+ struct lwp *lwp[5];
+
+ unsigned int i, j;
+ const off_t sz = 8192;
+ int omode = 0755;
+ int oflags = O_RDWR | O_CREAT;
+
+ memcpy(expect, lock, sizeof(lock));
+
+ FSTEST_ENTER();
+
+ /*
+ * First, we create 4 processes and let each lock a range of the
+ * file. Note that the third and fourth processes lock in
+ * "reverse" order, i.e. the greater pid locks a range before
+ * the lesser pid.
+ * Then, we create 5th process which doesn't lock anything.
+ */
+ for (i = 0; i < __arraycount(lwp); i++) {
+ RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
+
+ lwp[i] = rump_pub_lwproc_curlwp();
+ pid[i] = rump_sys_getpid();
+
+ RL(fd[i] = rump_sys_open(TESTFILE, oflags, omode));
+ oflags = O_RDWR;
+ omode = 0;
+
+ RL(rump_sys_ftruncate(fd[i], sz));
+
+ if (FSTYPE_ZFS(tc))
+ atf_tc_expect_fail("PR kern/47656: Test known to be "
+ "broken");
+ if (i < __arraycount(lock)) {
+ RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i]));
+ expect[i].l_pid = pid[i];
+ }
+ }
+
+ qsort(expect, __arraycount(expect), sizeof(expect[0]), &flock_compare);
+
+ /*
+ * In the context of each process, recursively find all locks
+ * that would block the current process. Processes 1-4 don't
+ * see their own lock, we insert it to simplify checks.
+ * Process 5 sees all 4 locks.
+ */
+ for (i = 0; i < __arraycount(lwp); i++) {
+ unsigned int nlocks;
+
+ rump_pub_lwproc_switch(lwp[i]);
+
+ memset(result, 0, sizeof(result));
+ nlocks = fcntl_getlocks(fd[i], 0, sz,
+ result, result + __arraycount(result));
+
+ if (i < __arraycount(lock)) {
+ ATF_REQUIRE(nlocks < __arraycount(result));
+ result[nlocks] = lock[i];
+ result[nlocks].l_pid = pid[i];
+ nlocks++;
+ }
+
+ ATF_CHECK_EQ(nlocks, __arraycount(expect));
+
+ qsort(result, nlocks, sizeof(result[0]), &flock_compare);
+
+ for (j = 0; j < nlocks; j++) {
+ ATF_CHECK_EQ(result[j].l_start, expect[j].l_start );
+ ATF_CHECK_EQ(result[j].l_len, expect[j].l_len );
+ ATF_CHECK_EQ(result[j].l_pid, expect[j].l_pid );
+ ATF_CHECK_EQ(result[j].l_type, expect[j].l_type );
+ ATF_CHECK_EQ(result[j].l_whence, expect[j].l_whence);
+ }
+ }
+
+ /*
+ * Release processes. This also releases the fds and locks
+ * making fs unmount possible
+ */
+ for (i = 0; i < __arraycount(lwp); i++) {
+ rump_pub_lwproc_switch(lwp[i]);
+ rump_pub_lwproc_releaselwp();
+ }
+
+ FSTEST_EXIT();
+}
+
+static void
+access_simple(const atf_tc_t *tc, const char *mp)
+{
+ int fd;
+ int tmode;
+
+ FSTEST_ENTER();
+ RL(fd = rump_sys_open("tfile", O_CREAT | O_RDWR, 0777));
+ RL(rump_sys_close(fd));
+
+#define ALLACC (F_OK | X_OK | W_OK | R_OK)
+ if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc))
+ tmode = F_OK;
+ else
+ tmode = ALLACC;
+
+ RL(rump_sys_access("tfile", tmode));
+
+ /* PR kern/44648 */
+ ATF_REQUIRE_ERRNO(EINVAL, rump_sys_access("tfile", ALLACC+1) == -1);
+#undef ALLACC
+ FSTEST_EXIT();
+}
+
+static void
+read_directory(const atf_tc_t *tc, const char *mp)
+{
+ char buf[1024];
+ int fd, res;
+ ssize_t size;
+
+ FSTEST_ENTER();
+ fd = rump_sys_open(".", O_DIRECTORY | O_RDONLY, 0777);
+ ATF_REQUIRE(fd != -1);
+
+ size = rump_sys_pread(fd, buf, sizeof(buf), 0);
+ ATF_CHECK(size != -1 || errno == EISDIR);
+ size = rump_sys_read(fd, buf, sizeof(buf));
+ ATF_CHECK(size != -1 || errno == EISDIR);
+
+ res = rump_sys_close(fd);
+ ATF_REQUIRE(res != -1);
+ FSTEST_EXIT();
+}
+
+static void
+lstat_symlink(const atf_tc_t *tc, const char *mp)
+{
+ const char *src, *dst;
+ int res;
+ struct stat st;
+
+ USES_SYMLINKS;
+
+ if (FSTYPE_V7FS(tc))
+ atf_tc_expect_fail("PR kern/48864");
+
+ FSTEST_ENTER();
+
+ src = "source";
+ dst = "destination";
+
+ res = rump_sys_symlink(src, dst);
+ ATF_REQUIRE(res != -1);
+ res = rump_sys_lstat(dst, &st);
+ ATF_REQUIRE(res != -1);
+
+ ATF_CHECK(S_ISLNK(st.st_mode) != 0);
+ ATF_CHECK(st.st_size == (off_t)strlen(src));
+
+ FSTEST_EXIT();
+}
+
+ATF_TC_FSAPPLY(lookup_simple, "simple lookup (./.. on root)");
+ATF_TC_FSAPPLY(lookup_complex, "lookup of non-dot entries");
+ATF_TC_FSAPPLY(dir_simple, "mkdir/rmdir");
+ATF_TC_FSAPPLY(dir_notempty, "non-empty directories cannot be removed");
+ATF_TC_FSAPPLY(dir_rmdirdotdot, "remove .. and try to cd out (PR kern/44657)");
+ATF_TC_FSAPPLY(rename_dir, "exercise various directory renaming ops "
+"(PR kern/44288)");
+ATF_TC_FSAPPLY(rename_dotdot, "rename dir .. (PR kern/43617)");
+ATF_TC_FSAPPLY(rename_reg_nodir, "rename regular files, no subdirectories");
+ATF_TC_FSAPPLY(create_nametoolong, "create file with name too long");
+ATF_TC_FSAPPLY(create_exist, "create with O_EXCL");
+ATF_TC_FSAPPLY(rename_nametoolong, "rename to file with name too long");
+ATF_TC_FSAPPLY(symlink_zerolen, "symlink with target of length 0");
+ATF_TC_FSAPPLY(symlink_long, "symlink with target of length > 0");
+ATF_TC_FSAPPLY(symlink_root, "symlink to root directory");
+ATF_TC_FSAPPLY(attrs, "check setting attributes works");
+ATF_TC_FSAPPLY(fcntl_lock, "check fcntl F_SETLK");
+ATF_TC_FSAPPLY(fcntl_getlock_pids,"fcntl F_GETLK w/ many procs, PR kern/44494");
+ATF_TC_FSAPPLY(access_simple, "access(2)");
+ATF_TC_FSAPPLY(read_directory, "read(2) on directories");
+ATF_TC_FSAPPLY(lstat_symlink, "lstat(2) values for symbolic links");
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_FSAPPLY(lookup_simple);
+ ATF_TP_FSAPPLY(lookup_complex);
+ ATF_TP_FSAPPLY(dir_simple);
+ ATF_TP_FSAPPLY(dir_notempty);
+ ATF_TP_FSAPPLY(dir_rmdirdotdot);
+ ATF_TP_FSAPPLY(rename_dir);
+ ATF_TP_FSAPPLY(rename_dotdot);
+ ATF_TP_FSAPPLY(rename_reg_nodir);
+ ATF_TP_FSAPPLY(create_nametoolong);
+ ATF_TP_FSAPPLY(create_exist);
+ ATF_TP_FSAPPLY(rename_nametoolong);
+ ATF_TP_FSAPPLY(symlink_zerolen);
+ ATF_TP_FSAPPLY(symlink_long);
+ ATF_TP_FSAPPLY(symlink_root);
+ ATF_TP_FSAPPLY(attrs);
+ ATF_TP_FSAPPLY(fcntl_lock);
+ ATF_TP_FSAPPLY(fcntl_getlock_pids);
+ ATF_TP_FSAPPLY(access_simple);
+ ATF_TP_FSAPPLY(read_directory);
+ ATF_TP_FSAPPLY(lstat_symlink);
+
+ return atf_no_error();
+}
OpenPOWER on IntegriCloud