1*84d9c625SLionel Sambuc /* $NetBSD: t_vnops.c,v 1.38 2013/10/19 17:45:00 christos Exp $ */ 211be35a1SLionel Sambuc 311be35a1SLionel Sambuc /*- 411be35a1SLionel Sambuc * Copyright (c) 2010 The NetBSD Foundation, Inc. 511be35a1SLionel Sambuc * All rights reserved. 611be35a1SLionel Sambuc * 711be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without 811be35a1SLionel Sambuc * modification, are permitted provided that the following conditions 911be35a1SLionel Sambuc * are met: 1011be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright 1111be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer. 1211be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 1311be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the 1411be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution. 1511be35a1SLionel Sambuc * 1611be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1711be35a1SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1811be35a1SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1911be35a1SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2011be35a1SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2111be35a1SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2211be35a1SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2311be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2411be35a1SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2511be35a1SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2611be35a1SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE. 2711be35a1SLionel Sambuc */ 2811be35a1SLionel Sambuc 2911be35a1SLionel Sambuc #include <sys/stat.h> 3011be35a1SLionel Sambuc #include <sys/statvfs.h> 3111be35a1SLionel Sambuc 3211be35a1SLionel Sambuc #include <assert.h> 3311be35a1SLionel Sambuc #include <atf-c.h> 3411be35a1SLionel Sambuc #include <fcntl.h> 3511be35a1SLionel Sambuc #include <libgen.h> 3611be35a1SLionel Sambuc #include <stdlib.h> 3711be35a1SLionel Sambuc #include <string.h> 3811be35a1SLionel Sambuc #include <unistd.h> 3911be35a1SLionel Sambuc 4011be35a1SLionel Sambuc #include <rump/rump_syscalls.h> 4111be35a1SLionel Sambuc #include <rump/rump.h> 4211be35a1SLionel Sambuc 4311be35a1SLionel Sambuc #include "../common/h_fsmacros.h" 4411be35a1SLionel Sambuc #include "../../h_macros.h" 4511be35a1SLionel Sambuc 4611be35a1SLionel Sambuc #define TESTFILE "afile" 4711be35a1SLionel Sambuc 4811be35a1SLionel Sambuc #define USES_DIRS \ 4911be35a1SLionel Sambuc if (FSTYPE_SYSVBFS(tc)) \ 5011be35a1SLionel Sambuc atf_tc_skip("directories not supported by file system") 5111be35a1SLionel Sambuc 5211be35a1SLionel Sambuc #define USES_SYMLINKS \ 5311be35a1SLionel Sambuc if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc)) \ 5411be35a1SLionel Sambuc atf_tc_skip("symlinks not supported by file system") 5511be35a1SLionel Sambuc 5611be35a1SLionel Sambuc static char * 5711be35a1SLionel Sambuc md(char *buf, const char *base, const char *tail) 5811be35a1SLionel Sambuc { 5911be35a1SLionel Sambuc 6011be35a1SLionel Sambuc sprintf(buf, "%s/%s", base, tail); 6111be35a1SLionel Sambuc return buf; 6211be35a1SLionel Sambuc } 6311be35a1SLionel Sambuc 6411be35a1SLionel Sambuc static void 6511be35a1SLionel Sambuc lookup_simple(const atf_tc_t *tc, const char *mountpath) 6611be35a1SLionel Sambuc { 6711be35a1SLionel Sambuc char pb[MAXPATHLEN], final[MAXPATHLEN]; 6811be35a1SLionel Sambuc struct stat sb1, sb2; 6911be35a1SLionel Sambuc 7011be35a1SLionel Sambuc strcpy(final, mountpath); 7111be35a1SLionel Sambuc sprintf(pb, "%s/../%s", mountpath, basename(final)); 7211be35a1SLionel Sambuc if (rump_sys_stat(pb, &sb1) == -1) 7311be35a1SLionel Sambuc atf_tc_fail_errno("stat 1"); 7411be35a1SLionel Sambuc 7511be35a1SLionel Sambuc sprintf(pb, "%s/./../%s", mountpath, basename(final)); 7611be35a1SLionel Sambuc if (rump_sys_stat(pb, &sb2) == -1) 7711be35a1SLionel Sambuc atf_tc_fail_errno("stat 2"); 7811be35a1SLionel Sambuc 7911be35a1SLionel Sambuc ATF_REQUIRE(memcmp(&sb1, &sb2, sizeof(sb1)) == 0); 8011be35a1SLionel Sambuc } 8111be35a1SLionel Sambuc 8211be35a1SLionel Sambuc static void 8311be35a1SLionel Sambuc lookup_complex(const atf_tc_t *tc, const char *mountpath) 8411be35a1SLionel Sambuc { 8511be35a1SLionel Sambuc char pb[MAXPATHLEN]; 8611be35a1SLionel Sambuc struct stat sb1, sb2; 8711be35a1SLionel Sambuc 8811be35a1SLionel Sambuc USES_DIRS; 8911be35a1SLionel Sambuc 9011be35a1SLionel Sambuc sprintf(pb, "%s/dir", mountpath); 9111be35a1SLionel Sambuc if (rump_sys_mkdir(pb, 0777) == -1) 9211be35a1SLionel Sambuc atf_tc_fail_errno("mkdir"); 9311be35a1SLionel Sambuc if (rump_sys_stat(pb, &sb1) == -1) 9411be35a1SLionel Sambuc atf_tc_fail_errno("stat 1"); 9511be35a1SLionel Sambuc 9611be35a1SLionel Sambuc sprintf(pb, "%s/./dir/../././dir/.", mountpath); 9711be35a1SLionel Sambuc if (rump_sys_stat(pb, &sb2) == -1) 9811be35a1SLionel Sambuc atf_tc_fail_errno("stat 2"); 9911be35a1SLionel Sambuc 10011be35a1SLionel Sambuc ATF_REQUIRE(memcmp(&sb1, &sb2, sizeof(sb1)) == 0); 10111be35a1SLionel Sambuc } 10211be35a1SLionel Sambuc 10311be35a1SLionel Sambuc static void 10411be35a1SLionel Sambuc dir_simple(const atf_tc_t *tc, const char *mountpath) 10511be35a1SLionel Sambuc { 10611be35a1SLionel Sambuc char pb[MAXPATHLEN]; 10711be35a1SLionel Sambuc struct stat sb; 10811be35a1SLionel Sambuc 10911be35a1SLionel Sambuc USES_DIRS; 11011be35a1SLionel Sambuc 11111be35a1SLionel Sambuc /* check we can create directories */ 11211be35a1SLionel Sambuc sprintf(pb, "%s/dir", mountpath); 11311be35a1SLionel Sambuc if (rump_sys_mkdir(pb, 0777) == -1) 11411be35a1SLionel Sambuc atf_tc_fail_errno("mkdir"); 11511be35a1SLionel Sambuc if (rump_sys_stat(pb, &sb) == -1) 11611be35a1SLionel Sambuc atf_tc_fail_errno("stat new directory"); 11711be35a1SLionel Sambuc 11811be35a1SLionel Sambuc /* check we can remove then and that it makes them unreachable */ 11911be35a1SLionel Sambuc if (rump_sys_rmdir(pb) == -1) 12011be35a1SLionel Sambuc atf_tc_fail_errno("rmdir"); 12111be35a1SLionel Sambuc if (rump_sys_stat(pb, &sb) != -1 || errno != ENOENT) 12211be35a1SLionel Sambuc atf_tc_fail("ENOENT expected from stat"); 12311be35a1SLionel Sambuc } 12411be35a1SLionel Sambuc 12511be35a1SLionel Sambuc static void 12611be35a1SLionel Sambuc dir_notempty(const atf_tc_t *tc, const char *mountpath) 12711be35a1SLionel Sambuc { 12811be35a1SLionel Sambuc char pb[MAXPATHLEN], pb2[MAXPATHLEN]; 12911be35a1SLionel Sambuc int fd, rv; 13011be35a1SLionel Sambuc 13111be35a1SLionel Sambuc USES_DIRS; 13211be35a1SLionel Sambuc 13311be35a1SLionel Sambuc /* check we can create directories */ 13411be35a1SLionel Sambuc sprintf(pb, "%s/dir", mountpath); 13511be35a1SLionel Sambuc if (rump_sys_mkdir(pb, 0777) == -1) 13611be35a1SLionel Sambuc atf_tc_fail_errno("mkdir"); 13711be35a1SLionel Sambuc 13811be35a1SLionel Sambuc sprintf(pb2, "%s/dir/file", mountpath); 13911be35a1SLionel Sambuc fd = rump_sys_open(pb2, O_RDWR | O_CREAT, 0777); 14011be35a1SLionel Sambuc if (fd == -1) 14111be35a1SLionel Sambuc atf_tc_fail_errno("create file"); 14211be35a1SLionel Sambuc rump_sys_close(fd); 14311be35a1SLionel Sambuc 14411be35a1SLionel Sambuc rv = rump_sys_rmdir(pb); 14511be35a1SLionel Sambuc if (FSTYPE_ZFS(tc)) 14611be35a1SLionel Sambuc atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 14711be35a1SLionel Sambuc if (rv != -1 || errno != ENOTEMPTY) 14811be35a1SLionel Sambuc atf_tc_fail("non-empty directory removed succesfully"); 14911be35a1SLionel Sambuc 15011be35a1SLionel Sambuc if (rump_sys_unlink(pb2) == -1) 15111be35a1SLionel Sambuc atf_tc_fail_errno("cannot remove dir/file"); 15211be35a1SLionel Sambuc 15311be35a1SLionel Sambuc if (rump_sys_rmdir(pb) == -1) 15411be35a1SLionel Sambuc atf_tc_fail_errno("remove directory"); 15511be35a1SLionel Sambuc } 15611be35a1SLionel Sambuc 15711be35a1SLionel Sambuc static void 15811be35a1SLionel Sambuc dir_rmdirdotdot(const atf_tc_t *tc, const char *mp) 15911be35a1SLionel Sambuc { 16011be35a1SLionel Sambuc char pb[MAXPATHLEN]; 16111be35a1SLionel Sambuc int xerrno; 16211be35a1SLionel Sambuc 16311be35a1SLionel Sambuc USES_DIRS; 16411be35a1SLionel Sambuc 16511be35a1SLionel Sambuc FSTEST_ENTER(); 16611be35a1SLionel Sambuc RL(rump_sys_mkdir("test", 0777)); 16711be35a1SLionel Sambuc RL(rump_sys_chdir("test")); 16811be35a1SLionel Sambuc 16911be35a1SLionel Sambuc RL(rump_sys_mkdir("subtest", 0777)); 17011be35a1SLionel Sambuc RL(rump_sys_chdir("subtest")); 17111be35a1SLionel Sambuc 17211be35a1SLionel Sambuc md(pb, mp, "test/subtest"); 17311be35a1SLionel Sambuc RL(rump_sys_rmdir(pb)); 17411be35a1SLionel Sambuc md(pb, mp, "test"); 17511be35a1SLionel Sambuc RL(rump_sys_rmdir(pb)); 17611be35a1SLionel Sambuc 17711be35a1SLionel Sambuc if (FSTYPE_NFS(tc)) 17811be35a1SLionel Sambuc xerrno = ESTALE; 17911be35a1SLionel Sambuc else 18011be35a1SLionel Sambuc xerrno = ENOENT; 18111be35a1SLionel Sambuc ATF_REQUIRE_ERRNO(xerrno, rump_sys_chdir("..") == -1); 18211be35a1SLionel Sambuc FSTEST_EXIT(); 18311be35a1SLionel Sambuc } 18411be35a1SLionel Sambuc 18511be35a1SLionel Sambuc static void 18611be35a1SLionel Sambuc checkfile(const char *path, struct stat *refp) 18711be35a1SLionel Sambuc { 18811be35a1SLionel Sambuc char buf[MAXPATHLEN]; 18911be35a1SLionel Sambuc struct stat sb; 19011be35a1SLionel Sambuc static int n = 1; 19111be35a1SLionel Sambuc 19211be35a1SLionel Sambuc md(buf, path, "file"); 19311be35a1SLionel Sambuc if (rump_sys_stat(buf, &sb) == -1) 19411be35a1SLionel Sambuc atf_tc_fail_errno("cannot stat file %d (%s)", n, buf); 19511be35a1SLionel Sambuc if (memcmp(&sb, refp, sizeof(sb)) != 0) 19611be35a1SLionel Sambuc atf_tc_fail("stat mismatch %d", n); 19711be35a1SLionel Sambuc n++; 19811be35a1SLionel Sambuc } 19911be35a1SLionel Sambuc 20011be35a1SLionel Sambuc static void 20111be35a1SLionel Sambuc rename_dir(const atf_tc_t *tc, const char *mp) 20211be35a1SLionel Sambuc { 20311be35a1SLionel Sambuc char pb1[MAXPATHLEN], pb2[MAXPATHLEN], pb3[MAXPATHLEN]; 20411be35a1SLionel Sambuc struct stat ref, sb; 20511be35a1SLionel Sambuc 20611be35a1SLionel Sambuc if (FSTYPE_RUMPFS(tc)) 20711be35a1SLionel Sambuc atf_tc_skip("rename not supported by file system"); 20811be35a1SLionel Sambuc 20911be35a1SLionel Sambuc USES_DIRS; 21011be35a1SLionel Sambuc 21111be35a1SLionel Sambuc md(pb1, mp, "dir1"); 21211be35a1SLionel Sambuc if (rump_sys_mkdir(pb1, 0777) == -1) 21311be35a1SLionel Sambuc atf_tc_fail_errno("mkdir 1"); 21411be35a1SLionel Sambuc 21511be35a1SLionel Sambuc md(pb2, mp, "dir2"); 21611be35a1SLionel Sambuc if (rump_sys_mkdir(pb2, 0777) == -1) 21711be35a1SLionel Sambuc atf_tc_fail_errno("mkdir 2"); 21811be35a1SLionel Sambuc md(pb2, mp, "dir2/subdir"); 21911be35a1SLionel Sambuc if (rump_sys_mkdir(pb2, 0777) == -1) 22011be35a1SLionel Sambuc atf_tc_fail_errno("mkdir 3"); 22111be35a1SLionel Sambuc 22211be35a1SLionel Sambuc md(pb3, mp, "dir1/file"); 22311be35a1SLionel Sambuc if (rump_sys_mknod(pb3, S_IFREG | 0777, -1) == -1) 22411be35a1SLionel Sambuc atf_tc_fail_errno("create file"); 22511be35a1SLionel Sambuc if (rump_sys_stat(pb3, &ref) == -1) 22611be35a1SLionel Sambuc atf_tc_fail_errno("stat of file"); 22711be35a1SLionel Sambuc 22811be35a1SLionel Sambuc /* 22911be35a1SLionel Sambuc * First try ops which should succeed. 23011be35a1SLionel Sambuc */ 23111be35a1SLionel Sambuc 23211be35a1SLionel Sambuc /* rename within directory */ 23311be35a1SLionel Sambuc md(pb3, mp, "dir3"); 23411be35a1SLionel Sambuc if (rump_sys_rename(pb1, pb3) == -1) 23511be35a1SLionel Sambuc atf_tc_fail_errno("rename 1"); 23611be35a1SLionel Sambuc checkfile(pb3, &ref); 23711be35a1SLionel Sambuc 23811be35a1SLionel Sambuc /* rename directory onto itself (two ways, should fail) */ 23911be35a1SLionel Sambuc md(pb1, mp, "dir3/."); 24011be35a1SLionel Sambuc if (rump_sys_rename(pb1, pb3) != -1 || errno != EINVAL) 24111be35a1SLionel Sambuc atf_tc_fail_errno("rename 2"); 24211be35a1SLionel Sambuc if (FSTYPE_ZFS(tc)) 24311be35a1SLionel Sambuc atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 24411be35a1SLionel Sambuc if (rump_sys_rename(pb3, pb1) != -1 || errno != EISDIR) 24511be35a1SLionel Sambuc atf_tc_fail_errno("rename 3"); 24611be35a1SLionel Sambuc 24711be35a1SLionel Sambuc checkfile(pb3, &ref); 24811be35a1SLionel Sambuc 24911be35a1SLionel Sambuc /* rename father of directory into directory */ 25011be35a1SLionel Sambuc md(pb1, mp, "dir2/dir"); 25111be35a1SLionel Sambuc md(pb2, mp, "dir2"); 25211be35a1SLionel Sambuc if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL) 25311be35a1SLionel Sambuc atf_tc_fail_errno("rename 4"); 25411be35a1SLionel Sambuc 25511be35a1SLionel Sambuc /* same for grandfather */ 25611be35a1SLionel Sambuc md(pb1, mp, "dir2/subdir/dir2"); 25711be35a1SLionel Sambuc if (rump_sys_rename(pb2, pb1) != -1 || errno != EINVAL) 25811be35a1SLionel Sambuc atf_tc_fail("rename 5"); 25911be35a1SLionel Sambuc 26011be35a1SLionel Sambuc checkfile(pb3, &ref); 26111be35a1SLionel Sambuc 26211be35a1SLionel Sambuc /* rename directory over a non-empty directory */ 26311be35a1SLionel Sambuc if (rump_sys_rename(pb2, pb3) != -1 || errno != ENOTEMPTY) 26411be35a1SLionel Sambuc atf_tc_fail("rename 6"); 26511be35a1SLionel Sambuc 26611be35a1SLionel Sambuc /* cross-directory rename */ 26711be35a1SLionel Sambuc md(pb1, mp, "dir3"); 26811be35a1SLionel Sambuc md(pb2, mp, "dir2/somedir"); 26911be35a1SLionel Sambuc if (rump_sys_rename(pb1, pb2) == -1) 27011be35a1SLionel Sambuc atf_tc_fail_errno("rename 7"); 27111be35a1SLionel Sambuc checkfile(pb2, &ref); 27211be35a1SLionel Sambuc 27311be35a1SLionel Sambuc /* move to parent directory */ 27411be35a1SLionel Sambuc md(pb1, mp, "dir2/somedir/../../dir3"); 27511be35a1SLionel Sambuc if (rump_sys_rename(pb2, pb1) == -1) 27611be35a1SLionel Sambuc atf_tc_fail_errno("rename 8"); 27711be35a1SLionel Sambuc md(pb1, mp, "dir2/../dir3"); 27811be35a1SLionel Sambuc checkfile(pb1, &ref); 27911be35a1SLionel Sambuc 28011be35a1SLionel Sambuc /* atomic cross-directory rename */ 28111be35a1SLionel Sambuc md(pb3, mp, "dir2/subdir"); 28211be35a1SLionel Sambuc if (rump_sys_rename(pb1, pb3) == -1) 28311be35a1SLionel Sambuc atf_tc_fail_errno("rename 9"); 28411be35a1SLionel Sambuc checkfile(pb3, &ref); 28511be35a1SLionel Sambuc 28611be35a1SLionel Sambuc /* rename directory over an empty directory */ 28711be35a1SLionel Sambuc md(pb1, mp, "parent"); 28811be35a1SLionel Sambuc md(pb2, mp, "parent/dir1"); 28911be35a1SLionel Sambuc md(pb3, mp, "parent/dir2"); 29011be35a1SLionel Sambuc RL(rump_sys_mkdir(pb1, 0777)); 29111be35a1SLionel Sambuc RL(rump_sys_mkdir(pb2, 0777)); 29211be35a1SLionel Sambuc RL(rump_sys_mkdir(pb3, 0777)); 29311be35a1SLionel Sambuc RL(rump_sys_rename(pb2, pb3)); 29411be35a1SLionel Sambuc 29511be35a1SLionel Sambuc RL(rump_sys_stat(pb1, &sb)); 29611be35a1SLionel Sambuc if (! FSTYPE_MSDOS(tc)) 29711be35a1SLionel Sambuc ATF_CHECK_EQ(sb.st_nlink, 3); 29811be35a1SLionel Sambuc RL(rump_sys_rmdir(pb3)); 29911be35a1SLionel Sambuc RL(rump_sys_rmdir(pb1)); 30011be35a1SLionel Sambuc } 30111be35a1SLionel Sambuc 30211be35a1SLionel Sambuc static void 30311be35a1SLionel Sambuc rename_dotdot(const atf_tc_t *tc, const char *mp) 30411be35a1SLionel Sambuc { 30511be35a1SLionel Sambuc 30611be35a1SLionel Sambuc if (FSTYPE_RUMPFS(tc)) 30711be35a1SLionel Sambuc atf_tc_skip("rename not supported by file system"); 30811be35a1SLionel Sambuc 30911be35a1SLionel Sambuc USES_DIRS; 31011be35a1SLionel Sambuc 31111be35a1SLionel Sambuc if (rump_sys_chdir(mp) == -1) 31211be35a1SLionel Sambuc atf_tc_fail_errno("chdir mountpoint"); 31311be35a1SLionel Sambuc 31411be35a1SLionel Sambuc if (rump_sys_mkdir("dir1", 0777) == -1) 31511be35a1SLionel Sambuc atf_tc_fail_errno("mkdir 1"); 31611be35a1SLionel Sambuc if (rump_sys_mkdir("dir2", 0777) == -1) 31711be35a1SLionel Sambuc atf_tc_fail_errno("mkdir 2"); 31811be35a1SLionel Sambuc 31911be35a1SLionel Sambuc if (rump_sys_rename("dir1", "dir1/..") != -1 || errno != EINVAL) 32011be35a1SLionel Sambuc atf_tc_fail_errno("self-dotdot to"); 32111be35a1SLionel Sambuc 32211be35a1SLionel Sambuc if (rump_sys_rename("dir1/..", "sometarget") != -1 || errno != EINVAL) 32311be35a1SLionel Sambuc atf_tc_fail_errno("self-dotdot from"); 32411be35a1SLionel Sambuc 32511be35a1SLionel Sambuc if (rump_sys_rename("dir1", "dir2/..") != -1 || errno != EINVAL) 32611be35a1SLionel Sambuc atf_tc_fail("other-dotdot"); 32711be35a1SLionel Sambuc 32811be35a1SLionel Sambuc rump_sys_chdir("/"); 32911be35a1SLionel Sambuc } 33011be35a1SLionel Sambuc 33111be35a1SLionel Sambuc static void 33211be35a1SLionel Sambuc rename_reg_nodir(const atf_tc_t *tc, const char *mp) 33311be35a1SLionel Sambuc { 33411be35a1SLionel Sambuc bool haslinks; 33511be35a1SLionel Sambuc struct stat sb; 336*84d9c625SLionel Sambuc ino_t f1ino; 33711be35a1SLionel Sambuc 33811be35a1SLionel Sambuc if (FSTYPE_RUMPFS(tc)) 33911be35a1SLionel Sambuc atf_tc_skip("rename not supported by file system"); 34011be35a1SLionel Sambuc 34111be35a1SLionel Sambuc if (rump_sys_chdir(mp) == -1) 34211be35a1SLionel Sambuc atf_tc_fail_errno("chdir mountpoint"); 34311be35a1SLionel Sambuc 34411be35a1SLionel Sambuc if (FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc)) 34511be35a1SLionel Sambuc haslinks = false; 34611be35a1SLionel Sambuc else 34711be35a1SLionel Sambuc haslinks = true; 34811be35a1SLionel Sambuc 34911be35a1SLionel Sambuc if (rump_sys_mknod("file1", S_IFREG | 0777, -1) == -1) 35011be35a1SLionel Sambuc atf_tc_fail_errno("create file"); 35111be35a1SLionel Sambuc if (rump_sys_mknod("file2", S_IFREG | 0777, -1) == -1) 35211be35a1SLionel Sambuc atf_tc_fail_errno("create file"); 35311be35a1SLionel Sambuc 35411be35a1SLionel Sambuc if (rump_sys_stat("file1", &sb) == -1) 35511be35a1SLionel Sambuc atf_tc_fail_errno("stat"); 35611be35a1SLionel Sambuc f1ino = sb.st_ino; 35711be35a1SLionel Sambuc 35811be35a1SLionel Sambuc if (haslinks) { 35911be35a1SLionel Sambuc if (rump_sys_link("file1", "file_link") == -1) 36011be35a1SLionel Sambuc atf_tc_fail_errno("link"); 36111be35a1SLionel Sambuc if (rump_sys_stat("file_link", &sb) == -1) 36211be35a1SLionel Sambuc atf_tc_fail_errno("stat"); 36311be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_ino, f1ino); 36411be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_nlink, 2); 36511be35a1SLionel Sambuc } 36611be35a1SLionel Sambuc 36711be35a1SLionel Sambuc if (rump_sys_stat("file2", &sb) == -1) 36811be35a1SLionel Sambuc atf_tc_fail_errno("stat"); 36911be35a1SLionel Sambuc 37011be35a1SLionel Sambuc if (rump_sys_rename("file1", "file3") == -1) 37111be35a1SLionel Sambuc atf_tc_fail_errno("rename 1"); 37211be35a1SLionel Sambuc if (rump_sys_stat("file3", &sb) == -1) 37311be35a1SLionel Sambuc atf_tc_fail_errno("stat 1"); 37411be35a1SLionel Sambuc if (haslinks) { 37511be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_ino, f1ino); 37611be35a1SLionel Sambuc } 37711be35a1SLionel Sambuc if (rump_sys_stat("file1", &sb) != -1 || errno != ENOENT) 37811be35a1SLionel Sambuc atf_tc_fail_errno("source 1"); 37911be35a1SLionel Sambuc 38011be35a1SLionel Sambuc if (rump_sys_rename("file3", "file2") == -1) 38111be35a1SLionel Sambuc atf_tc_fail_errno("rename 2"); 38211be35a1SLionel Sambuc if (rump_sys_stat("file2", &sb) == -1) 38311be35a1SLionel Sambuc atf_tc_fail_errno("stat 2"); 38411be35a1SLionel Sambuc if (haslinks) { 38511be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_ino, f1ino); 38611be35a1SLionel Sambuc } 38711be35a1SLionel Sambuc 38811be35a1SLionel Sambuc if (rump_sys_stat("file3", &sb) != -1 || errno != ENOENT) 38911be35a1SLionel Sambuc atf_tc_fail_errno("source 2"); 39011be35a1SLionel Sambuc 39111be35a1SLionel Sambuc if (haslinks) { 39211be35a1SLionel Sambuc if (rump_sys_rename("file2", "file_link") == -1) 39311be35a1SLionel Sambuc atf_tc_fail_errno("rename hardlink"); 39411be35a1SLionel Sambuc if (rump_sys_stat("file2", &sb) != -1 || errno != ENOENT) 39511be35a1SLionel Sambuc atf_tc_fail_errno("source 3"); 39611be35a1SLionel Sambuc if (rump_sys_stat("file_link", &sb) == -1) 39711be35a1SLionel Sambuc atf_tc_fail_errno("stat 2"); 39811be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_ino, f1ino); 39911be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_nlink, 1); 40011be35a1SLionel Sambuc } 40111be35a1SLionel Sambuc 402*84d9c625SLionel Sambuc ATF_CHECK_ERRNO(EFAULT, rump_sys_rename("file2", NULL) == -1); 403*84d9c625SLionel Sambuc ATF_CHECK_ERRNO(EFAULT, rump_sys_rename(NULL, "file2") == -1); 404*84d9c625SLionel Sambuc 40511be35a1SLionel Sambuc rump_sys_chdir("/"); 40611be35a1SLionel Sambuc } 40711be35a1SLionel Sambuc 40811be35a1SLionel Sambuc static void 40911be35a1SLionel Sambuc create_nametoolong(const atf_tc_t *tc, const char *mp) 41011be35a1SLionel Sambuc { 41111be35a1SLionel Sambuc char *name; 41211be35a1SLionel Sambuc int fd; 41311be35a1SLionel Sambuc long val; 41411be35a1SLionel Sambuc size_t len; 41511be35a1SLionel Sambuc 41611be35a1SLionel Sambuc if (rump_sys_chdir(mp) == -1) 41711be35a1SLionel Sambuc atf_tc_fail_errno("chdir mountpoint"); 41811be35a1SLionel Sambuc 41911be35a1SLionel Sambuc val = rump_sys_pathconf(".", _PC_NAME_MAX); 42011be35a1SLionel Sambuc if (val == -1) 42111be35a1SLionel Sambuc atf_tc_fail_errno("pathconf"); 42211be35a1SLionel Sambuc 42311be35a1SLionel Sambuc len = val + 1; 42411be35a1SLionel Sambuc name = malloc(len+1); 42511be35a1SLionel Sambuc if (name == NULL) 42611be35a1SLionel Sambuc atf_tc_fail_errno("malloc"); 42711be35a1SLionel Sambuc 42811be35a1SLionel Sambuc memset(name, 'a', len); 42911be35a1SLionel Sambuc *(name+len) = '\0'; 43011be35a1SLionel Sambuc 43111be35a1SLionel Sambuc val = rump_sys_pathconf(".", _PC_NO_TRUNC); 43211be35a1SLionel Sambuc if (val == -1) 43311be35a1SLionel Sambuc atf_tc_fail_errno("pathconf"); 43411be35a1SLionel Sambuc 43511be35a1SLionel Sambuc fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666); 43611be35a1SLionel Sambuc if (val != 0 && (fd != -1 || errno != ENAMETOOLONG)) 43711be35a1SLionel Sambuc atf_tc_fail_errno("open"); 43811be35a1SLionel Sambuc 43911be35a1SLionel Sambuc if (val == 0 && rump_sys_close(fd) == -1) 44011be35a1SLionel Sambuc atf_tc_fail_errno("close"); 44111be35a1SLionel Sambuc if (val == 0 && rump_sys_unlink(name) == -1) 44211be35a1SLionel Sambuc atf_tc_fail_errno("unlink"); 44311be35a1SLionel Sambuc 44411be35a1SLionel Sambuc free(name); 44511be35a1SLionel Sambuc 44611be35a1SLionel Sambuc rump_sys_chdir("/"); 44711be35a1SLionel Sambuc } 44811be35a1SLionel Sambuc 44911be35a1SLionel Sambuc static void 45011be35a1SLionel Sambuc create_exist(const atf_tc_t *tc, const char *mp) 45111be35a1SLionel Sambuc { 45211be35a1SLionel Sambuc const char *name = "hoge"; 45311be35a1SLionel Sambuc int fd; 45411be35a1SLionel Sambuc 45511be35a1SLionel Sambuc RL(rump_sys_chdir(mp)); 45611be35a1SLionel Sambuc RL(fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666)); 45711be35a1SLionel Sambuc RL(rump_sys_close(fd)); 45811be35a1SLionel Sambuc RL(rump_sys_unlink(name)); 45911be35a1SLionel Sambuc RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)); 46011be35a1SLionel Sambuc RL(rump_sys_close(fd)); 46111be35a1SLionel Sambuc RL(fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)); 46211be35a1SLionel Sambuc RL(rump_sys_close(fd)); 46311be35a1SLionel Sambuc ATF_REQUIRE_ERRNO(EEXIST, 46411be35a1SLionel Sambuc (fd = rump_sys_open(name, O_RDWR|O_CREAT|O_EXCL, 0666))); 46511be35a1SLionel Sambuc RL(rump_sys_unlink(name)); 46611be35a1SLionel Sambuc RL(rump_sys_chdir("/")); 46711be35a1SLionel Sambuc } 46811be35a1SLionel Sambuc 46911be35a1SLionel Sambuc static void 47011be35a1SLionel Sambuc rename_nametoolong(const atf_tc_t *tc, const char *mp) 47111be35a1SLionel Sambuc { 47211be35a1SLionel Sambuc char *name; 47311be35a1SLionel Sambuc int res, fd; 47411be35a1SLionel Sambuc long val; 47511be35a1SLionel Sambuc size_t len; 47611be35a1SLionel Sambuc 47711be35a1SLionel Sambuc if (FSTYPE_RUMPFS(tc)) 47811be35a1SLionel Sambuc atf_tc_skip("rename not supported by file system"); 47911be35a1SLionel Sambuc 48011be35a1SLionel Sambuc if (rump_sys_chdir(mp) == -1) 48111be35a1SLionel Sambuc atf_tc_fail_errno("chdir mountpoint"); 48211be35a1SLionel Sambuc 48311be35a1SLionel Sambuc val = rump_sys_pathconf(".", _PC_NAME_MAX); 48411be35a1SLionel Sambuc if (val == -1) 48511be35a1SLionel Sambuc atf_tc_fail_errno("pathconf"); 48611be35a1SLionel Sambuc 48711be35a1SLionel Sambuc len = val + 1; 48811be35a1SLionel Sambuc name = malloc(len+1); 48911be35a1SLionel Sambuc if (name == NULL) 49011be35a1SLionel Sambuc atf_tc_fail_errno("malloc"); 49111be35a1SLionel Sambuc 49211be35a1SLionel Sambuc memset(name, 'a', len); 49311be35a1SLionel Sambuc *(name+len) = '\0'; 49411be35a1SLionel Sambuc 49511be35a1SLionel Sambuc fd = rump_sys_open("dummy", O_RDWR|O_CREAT, 0666); 49611be35a1SLionel Sambuc if (fd == -1) 49711be35a1SLionel Sambuc atf_tc_fail_errno("open"); 49811be35a1SLionel Sambuc if (rump_sys_close(fd) == -1) 49911be35a1SLionel Sambuc atf_tc_fail_errno("close"); 50011be35a1SLionel Sambuc 50111be35a1SLionel Sambuc val = rump_sys_pathconf(".", _PC_NO_TRUNC); 50211be35a1SLionel Sambuc if (val == -1) 50311be35a1SLionel Sambuc atf_tc_fail_errno("pathconf"); 50411be35a1SLionel Sambuc 50511be35a1SLionel Sambuc res = rump_sys_rename("dummy", name); 50611be35a1SLionel Sambuc if (val != 0 && (res != -1 || errno != ENAMETOOLONG)) 50711be35a1SLionel Sambuc atf_tc_fail_errno("rename"); 50811be35a1SLionel Sambuc 50911be35a1SLionel Sambuc if (val == 0 && rump_sys_unlink(name) == -1) 51011be35a1SLionel Sambuc atf_tc_fail_errno("unlink"); 51111be35a1SLionel Sambuc 51211be35a1SLionel Sambuc free(name); 51311be35a1SLionel Sambuc 51411be35a1SLionel Sambuc rump_sys_chdir("/"); 51511be35a1SLionel Sambuc } 51611be35a1SLionel Sambuc 51711be35a1SLionel Sambuc static void 51811be35a1SLionel Sambuc symlink_zerolen(const atf_tc_t *tc, const char *mp) 51911be35a1SLionel Sambuc { 52011be35a1SLionel Sambuc 52111be35a1SLionel Sambuc USES_SYMLINKS; 52211be35a1SLionel Sambuc 52311be35a1SLionel Sambuc RL(rump_sys_chdir(mp)); 52411be35a1SLionel Sambuc 52511be35a1SLionel Sambuc RL(rump_sys_symlink("", "afile")); 52611be35a1SLionel Sambuc RL(rump_sys_chdir("/")); 52711be35a1SLionel Sambuc } 52811be35a1SLionel Sambuc 52911be35a1SLionel Sambuc static void 53011be35a1SLionel Sambuc symlink_root(const atf_tc_t *tc, const char *mp) 53111be35a1SLionel Sambuc { 53211be35a1SLionel Sambuc 53311be35a1SLionel Sambuc USES_SYMLINKS; 53411be35a1SLionel Sambuc 53511be35a1SLionel Sambuc RL(rump_sys_chdir(mp)); 53611be35a1SLionel Sambuc RL(rump_sys_symlink("/", "foo")); 53711be35a1SLionel Sambuc RL(rump_sys_chdir("foo")); 53811be35a1SLionel Sambuc } 53911be35a1SLionel Sambuc 54011be35a1SLionel Sambuc static void 54111be35a1SLionel Sambuc attrs(const atf_tc_t *tc, const char *mp) 54211be35a1SLionel Sambuc { 54311be35a1SLionel Sambuc struct stat sb, sb2; 54411be35a1SLionel Sambuc struct timeval tv[2]; 54511be35a1SLionel Sambuc int fd; 54611be35a1SLionel Sambuc 54711be35a1SLionel Sambuc FSTEST_ENTER(); 54811be35a1SLionel Sambuc RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755)); 54911be35a1SLionel Sambuc RL(rump_sys_close(fd)); 55011be35a1SLionel Sambuc RL(rump_sys_stat(TESTFILE, &sb)); 55111be35a1SLionel Sambuc if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) { 55211be35a1SLionel Sambuc RL(rump_sys_chown(TESTFILE, 1, 2)); 55311be35a1SLionel Sambuc sb.st_uid = 1; 55411be35a1SLionel Sambuc sb.st_gid = 2; 55511be35a1SLionel Sambuc RL(rump_sys_chmod(TESTFILE, 0123)); 55611be35a1SLionel Sambuc sb.st_mode = (sb.st_mode & ~ACCESSPERMS) | 0123; 55711be35a1SLionel Sambuc } 55811be35a1SLionel Sambuc 55911be35a1SLionel Sambuc tv[0].tv_sec = 1000000000; /* need something >1980 for msdosfs */ 56011be35a1SLionel Sambuc tv[0].tv_usec = 1; 56111be35a1SLionel Sambuc tv[1].tv_sec = 1000000002; /* need even seconds for msdosfs */ 56211be35a1SLionel Sambuc tv[1].tv_usec = 3; 56311be35a1SLionel Sambuc RL(rump_sys_utimes(TESTFILE, tv)); 56411be35a1SLionel Sambuc RL(rump_sys_utimes(TESTFILE, tv)); /* XXX: utimes & birthtime */ 56511be35a1SLionel Sambuc sb.st_atimespec.tv_sec = 1000000000; 56611be35a1SLionel Sambuc sb.st_atimespec.tv_nsec = 1000; 56711be35a1SLionel Sambuc sb.st_mtimespec.tv_sec = 1000000002; 56811be35a1SLionel Sambuc sb.st_mtimespec.tv_nsec = 3000; 56911be35a1SLionel Sambuc 57011be35a1SLionel Sambuc RL(rump_sys_stat(TESTFILE, &sb2)); 57111be35a1SLionel Sambuc #define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a) 57211be35a1SLionel Sambuc if (FSTYPE_ZFS(tc)) 57311be35a1SLionel Sambuc atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 57411be35a1SLionel Sambuc if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) { 57511be35a1SLionel Sambuc CHECK(st_uid); 57611be35a1SLionel Sambuc CHECK(st_gid); 57711be35a1SLionel Sambuc CHECK(st_mode); 57811be35a1SLionel Sambuc } 57911be35a1SLionel Sambuc if (!FSTYPE_MSDOS(tc)) { 58011be35a1SLionel Sambuc /* msdosfs has only access date, not time */ 58111be35a1SLionel Sambuc CHECK(st_atimespec.tv_sec); 58211be35a1SLionel Sambuc } 58311be35a1SLionel Sambuc CHECK(st_mtimespec.tv_sec); 58411be35a1SLionel Sambuc if (!(FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc) || 58511be35a1SLionel Sambuc FSTYPE_SYSVBFS(tc) || FSTYPE_V7FS(tc))) { 58611be35a1SLionel Sambuc CHECK(st_atimespec.tv_nsec); 58711be35a1SLionel Sambuc CHECK(st_mtimespec.tv_nsec); 58811be35a1SLionel Sambuc } 58911be35a1SLionel Sambuc #undef CHECK 59011be35a1SLionel Sambuc 59111be35a1SLionel Sambuc FSTEST_EXIT(); 59211be35a1SLionel Sambuc } 59311be35a1SLionel Sambuc 59411be35a1SLionel Sambuc static void 59511be35a1SLionel Sambuc fcntl_lock(const atf_tc_t *tc, const char *mp) 59611be35a1SLionel Sambuc { 59711be35a1SLionel Sambuc int fd, fd2; 59811be35a1SLionel Sambuc struct flock l; 59911be35a1SLionel Sambuc struct lwp *lwp1, *lwp2; 60011be35a1SLionel Sambuc 60111be35a1SLionel Sambuc FSTEST_ENTER(); 60211be35a1SLionel Sambuc l.l_pid = 0; 60311be35a1SLionel Sambuc l.l_start = l.l_len = 1024; 60411be35a1SLionel Sambuc l.l_type = F_RDLCK | F_WRLCK; 60511be35a1SLionel Sambuc l.l_whence = SEEK_END; 60611be35a1SLionel Sambuc 60711be35a1SLionel Sambuc lwp1 = rump_pub_lwproc_curlwp(); 60811be35a1SLionel Sambuc RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755)); 60911be35a1SLionel Sambuc RL(rump_sys_ftruncate(fd, 8192)); 61011be35a1SLionel Sambuc 61111be35a1SLionel Sambuc /* PR kern/43321 */ 61211be35a1SLionel Sambuc if (FSTYPE_ZFS(tc)) 61311be35a1SLionel Sambuc atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 61411be35a1SLionel Sambuc RL(rump_sys_fcntl(fd, F_SETLK, &l)); 61511be35a1SLionel Sambuc 61611be35a1SLionel Sambuc /* Next, we fork and try to lock the same area */ 61711be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 61811be35a1SLionel Sambuc lwp2 = rump_pub_lwproc_curlwp(); 61911be35a1SLionel Sambuc RL(fd2 = rump_sys_open(TESTFILE, O_RDWR, 0)); 62011be35a1SLionel Sambuc ATF_REQUIRE_ERRNO(EAGAIN, rump_sys_fcntl(fd2, F_SETLK, &l)); 62111be35a1SLionel Sambuc 62211be35a1SLionel Sambuc /* Switch back and unlock... */ 62311be35a1SLionel Sambuc rump_pub_lwproc_switch(lwp1); 62411be35a1SLionel Sambuc l.l_type = F_UNLCK; 62511be35a1SLionel Sambuc RL(rump_sys_fcntl(fd, F_SETLK, &l)); 62611be35a1SLionel Sambuc 62711be35a1SLionel Sambuc /* ... and try to lock again */ 62811be35a1SLionel Sambuc rump_pub_lwproc_switch(lwp2); 62911be35a1SLionel Sambuc l.l_type = F_RDLCK | F_WRLCK; 63011be35a1SLionel Sambuc RL(rump_sys_fcntl(fd2, F_SETLK, &l)); 63111be35a1SLionel Sambuc 63211be35a1SLionel Sambuc RL(rump_sys_close(fd2)); 63311be35a1SLionel Sambuc rump_pub_lwproc_releaselwp(); 63411be35a1SLionel Sambuc 63511be35a1SLionel Sambuc RL(rump_sys_close(fd)); 63611be35a1SLionel Sambuc 63711be35a1SLionel Sambuc FSTEST_EXIT(); 63811be35a1SLionel Sambuc } 63911be35a1SLionel Sambuc 64011be35a1SLionel Sambuc static int 64111be35a1SLionel Sambuc flock_compare(const void *p, const void *q) 64211be35a1SLionel Sambuc { 64311be35a1SLionel Sambuc int a = ((const struct flock *)p)->l_start; 64411be35a1SLionel Sambuc int b = ((const struct flock *)q)->l_start; 64511be35a1SLionel Sambuc return a < b ? -1 : (a > b ? 1 : 0); 64611be35a1SLionel Sambuc } 64711be35a1SLionel Sambuc 64811be35a1SLionel Sambuc /* 64911be35a1SLionel Sambuc * Find all locks set by fcntl_getlock_pids test 65011be35a1SLionel Sambuc * using GETLK for a range [start, start+end], and, 65111be35a1SLionel Sambuc * if there is a blocking lock, recursively find 65211be35a1SLionel Sambuc * all locks to the left (toward the beginning of 65311be35a1SLionel Sambuc * a file) and to the right of the lock. 65411be35a1SLionel Sambuc * The function also understands "until end of file" 65511be35a1SLionel Sambuc * convention when len==0. 65611be35a1SLionel Sambuc */ 65711be35a1SLionel Sambuc static unsigned int 65811be35a1SLionel Sambuc fcntl_getlocks(int fildes, off_t start, off_t len, 65911be35a1SLionel Sambuc struct flock *lock, struct flock *end) 66011be35a1SLionel Sambuc { 66111be35a1SLionel Sambuc unsigned int rv = 0; 66211be35a1SLionel Sambuc const struct flock l = { start, len, 0, F_RDLCK, SEEK_SET }; 66311be35a1SLionel Sambuc 66411be35a1SLionel Sambuc if (lock == end) 66511be35a1SLionel Sambuc return rv; 66611be35a1SLionel Sambuc 66711be35a1SLionel Sambuc RL(rump_sys_fcntl(fildes, F_GETLK, &l)); 66811be35a1SLionel Sambuc 66911be35a1SLionel Sambuc if (l.l_type == F_UNLCK) 67011be35a1SLionel Sambuc return rv; 67111be35a1SLionel Sambuc 67211be35a1SLionel Sambuc *lock++ = l; 67311be35a1SLionel Sambuc rv += 1; 67411be35a1SLionel Sambuc 67511be35a1SLionel Sambuc ATF_REQUIRE(l.l_whence == SEEK_SET); 67611be35a1SLionel Sambuc 67711be35a1SLionel Sambuc if (l.l_start > start) { 67811be35a1SLionel Sambuc unsigned int n = 67911be35a1SLionel Sambuc fcntl_getlocks(fildes, start, l.l_start - start, lock, end); 68011be35a1SLionel Sambuc rv += n; 68111be35a1SLionel Sambuc lock += n; 68211be35a1SLionel Sambuc if (lock == end) 68311be35a1SLionel Sambuc return rv; 68411be35a1SLionel Sambuc } 68511be35a1SLionel Sambuc 68611be35a1SLionel Sambuc if (l.l_len == 0) /* does l spans until the end? */ 68711be35a1SLionel Sambuc return rv; 68811be35a1SLionel Sambuc 68911be35a1SLionel Sambuc if (len == 0) /* are we looking for locks until the end? */ { 69011be35a1SLionel Sambuc rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end); 69111be35a1SLionel Sambuc } else if (l.l_start + l.l_len < start + len) { 69211be35a1SLionel Sambuc len -= l.l_start + l.l_len - start; 69311be35a1SLionel Sambuc rv += fcntl_getlocks(fildes, l.l_start + l.l_len, len, lock, end); 69411be35a1SLionel Sambuc } 69511be35a1SLionel Sambuc 69611be35a1SLionel Sambuc return rv; 69711be35a1SLionel Sambuc } 69811be35a1SLionel Sambuc 69911be35a1SLionel Sambuc static void 70011be35a1SLionel Sambuc fcntl_getlock_pids(const atf_tc_t *tc, const char *mp) 70111be35a1SLionel Sambuc { 70211be35a1SLionel Sambuc /* test non-overlaping ranges */ 70311be35a1SLionel Sambuc struct flock expect[4]; 70411be35a1SLionel Sambuc const struct flock lock[4] = { 70511be35a1SLionel Sambuc { 0, 2, 0, F_WRLCK, SEEK_SET }, 70611be35a1SLionel Sambuc { 2, 1, 0, F_WRLCK, SEEK_SET }, 70711be35a1SLionel Sambuc { 7, 5, 0, F_WRLCK, SEEK_SET }, 70811be35a1SLionel Sambuc { 4, 3, 0, F_WRLCK, SEEK_SET }, 70911be35a1SLionel Sambuc }; 71011be35a1SLionel Sambuc 71111be35a1SLionel Sambuc /* Add extra element to make sure recursion does't stop at array end */ 71211be35a1SLionel Sambuc struct flock result[5]; 71311be35a1SLionel Sambuc 71411be35a1SLionel Sambuc /* Add 5th process */ 71511be35a1SLionel Sambuc int fd[5]; 71611be35a1SLionel Sambuc pid_t pid[5]; 71711be35a1SLionel Sambuc struct lwp *lwp[5]; 71811be35a1SLionel Sambuc 71911be35a1SLionel Sambuc unsigned int i, j; 72011be35a1SLionel Sambuc const off_t sz = 8192; 72111be35a1SLionel Sambuc int omode = 0755; 72211be35a1SLionel Sambuc int oflags = O_RDWR | O_CREAT; 72311be35a1SLionel Sambuc 72411be35a1SLionel Sambuc memcpy(expect, lock, sizeof(lock)); 72511be35a1SLionel Sambuc 72611be35a1SLionel Sambuc FSTEST_ENTER(); 72711be35a1SLionel Sambuc 72811be35a1SLionel Sambuc /* 72911be35a1SLionel Sambuc * First, we create 4 processes and let each lock a range of the 73011be35a1SLionel Sambuc * file. Note that the third and fourth processes lock in 73111be35a1SLionel Sambuc * "reverse" order, i.e. the greater pid locks a range before 73211be35a1SLionel Sambuc * the lesser pid. 73311be35a1SLionel Sambuc * Then, we create 5th process which doesn't lock anything. 73411be35a1SLionel Sambuc */ 73511be35a1SLionel Sambuc for (i = 0; i < __arraycount(lwp); i++) { 73611be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 73711be35a1SLionel Sambuc 73811be35a1SLionel Sambuc lwp[i] = rump_pub_lwproc_curlwp(); 73911be35a1SLionel Sambuc pid[i] = rump_sys_getpid(); 74011be35a1SLionel Sambuc 74111be35a1SLionel Sambuc RL(fd[i] = rump_sys_open(TESTFILE, oflags, omode)); 74211be35a1SLionel Sambuc oflags = O_RDWR; 74311be35a1SLionel Sambuc omode = 0; 74411be35a1SLionel Sambuc 74511be35a1SLionel Sambuc RL(rump_sys_ftruncate(fd[i], sz)); 74611be35a1SLionel Sambuc 74711be35a1SLionel Sambuc if (FSTYPE_ZFS(tc)) 74811be35a1SLionel Sambuc atf_tc_expect_fail("PR kern/47656: Test known to be " 74911be35a1SLionel Sambuc "broken"); 75011be35a1SLionel Sambuc if (i < __arraycount(lock)) { 75111be35a1SLionel Sambuc RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i])); 75211be35a1SLionel Sambuc expect[i].l_pid = pid[i]; 75311be35a1SLionel Sambuc } 75411be35a1SLionel Sambuc } 75511be35a1SLionel Sambuc 75611be35a1SLionel Sambuc qsort(expect, __arraycount(expect), sizeof(expect[0]), &flock_compare); 75711be35a1SLionel Sambuc 75811be35a1SLionel Sambuc /* 75911be35a1SLionel Sambuc * In the context of each process, recursively find all locks 76011be35a1SLionel Sambuc * that would block the current process. Processes 1-4 don't 76111be35a1SLionel Sambuc * see their own lock, we insert it to simplify checks. 76211be35a1SLionel Sambuc * Process 5 sees all 4 locks. 76311be35a1SLionel Sambuc */ 76411be35a1SLionel Sambuc for (i = 0; i < __arraycount(lwp); i++) { 76511be35a1SLionel Sambuc unsigned int nlocks; 76611be35a1SLionel Sambuc 76711be35a1SLionel Sambuc rump_pub_lwproc_switch(lwp[i]); 76811be35a1SLionel Sambuc 76911be35a1SLionel Sambuc memset(result, 0, sizeof(result)); 77011be35a1SLionel Sambuc nlocks = fcntl_getlocks(fd[i], 0, sz, 77111be35a1SLionel Sambuc result, result + __arraycount(result)); 77211be35a1SLionel Sambuc 77311be35a1SLionel Sambuc if (i < __arraycount(lock)) { 77411be35a1SLionel Sambuc ATF_REQUIRE(nlocks < __arraycount(result)); 77511be35a1SLionel Sambuc result[nlocks] = lock[i]; 77611be35a1SLionel Sambuc result[nlocks].l_pid = pid[i]; 77711be35a1SLionel Sambuc nlocks++; 77811be35a1SLionel Sambuc } 77911be35a1SLionel Sambuc 78011be35a1SLionel Sambuc ATF_CHECK_EQ(nlocks, __arraycount(expect)); 78111be35a1SLionel Sambuc 78211be35a1SLionel Sambuc qsort(result, nlocks, sizeof(result[0]), &flock_compare); 78311be35a1SLionel Sambuc 78411be35a1SLionel Sambuc for (j = 0; j < nlocks; j++) { 78511be35a1SLionel Sambuc ATF_CHECK_EQ(result[j].l_start, expect[j].l_start ); 78611be35a1SLionel Sambuc ATF_CHECK_EQ(result[j].l_len, expect[j].l_len ); 78711be35a1SLionel Sambuc ATF_CHECK_EQ(result[j].l_pid, expect[j].l_pid ); 78811be35a1SLionel Sambuc ATF_CHECK_EQ(result[j].l_type, expect[j].l_type ); 78911be35a1SLionel Sambuc ATF_CHECK_EQ(result[j].l_whence, expect[j].l_whence); 79011be35a1SLionel Sambuc } 79111be35a1SLionel Sambuc } 79211be35a1SLionel Sambuc 79311be35a1SLionel Sambuc /* 79411be35a1SLionel Sambuc * Release processes. This also releases the fds and locks 79511be35a1SLionel Sambuc * making fs unmount possible 79611be35a1SLionel Sambuc */ 79711be35a1SLionel Sambuc for (i = 0; i < __arraycount(lwp); i++) { 79811be35a1SLionel Sambuc rump_pub_lwproc_switch(lwp[i]); 79911be35a1SLionel Sambuc rump_pub_lwproc_releaselwp(); 80011be35a1SLionel Sambuc } 80111be35a1SLionel Sambuc 80211be35a1SLionel Sambuc FSTEST_EXIT(); 80311be35a1SLionel Sambuc } 80411be35a1SLionel Sambuc 80511be35a1SLionel Sambuc static void 80611be35a1SLionel Sambuc access_simple(const atf_tc_t *tc, const char *mp) 80711be35a1SLionel Sambuc { 80811be35a1SLionel Sambuc int fd; 80911be35a1SLionel Sambuc int tmode; 81011be35a1SLionel Sambuc 81111be35a1SLionel Sambuc FSTEST_ENTER(); 81211be35a1SLionel Sambuc RL(fd = rump_sys_open("tfile", O_CREAT | O_RDWR, 0777)); 81311be35a1SLionel Sambuc RL(rump_sys_close(fd)); 81411be35a1SLionel Sambuc 81511be35a1SLionel Sambuc #define ALLACC (F_OK | X_OK | W_OK | R_OK) 81611be35a1SLionel Sambuc if (FSTYPE_SYSVBFS(tc) || FSTYPE_MSDOS(tc)) 81711be35a1SLionel Sambuc tmode = F_OK; 81811be35a1SLionel Sambuc else 81911be35a1SLionel Sambuc tmode = ALLACC; 82011be35a1SLionel Sambuc 82111be35a1SLionel Sambuc RL(rump_sys_access("tfile", tmode)); 82211be35a1SLionel Sambuc 82311be35a1SLionel Sambuc /* PR kern/44648 */ 82411be35a1SLionel Sambuc ATF_REQUIRE_ERRNO(EINVAL, rump_sys_access("tfile", ALLACC+1) == -1); 82511be35a1SLionel Sambuc #undef ALLACC 82611be35a1SLionel Sambuc FSTEST_EXIT(); 82711be35a1SLionel Sambuc } 82811be35a1SLionel Sambuc 82911be35a1SLionel Sambuc static void 83011be35a1SLionel Sambuc read_directory(const atf_tc_t *tc, const char *mp) 83111be35a1SLionel Sambuc { 83211be35a1SLionel Sambuc char buf[1024]; 83311be35a1SLionel Sambuc int fd, res; 83411be35a1SLionel Sambuc ssize_t size; 83511be35a1SLionel Sambuc 83611be35a1SLionel Sambuc FSTEST_ENTER(); 83711be35a1SLionel Sambuc fd = rump_sys_open(".", O_DIRECTORY | O_RDONLY, 0777); 83811be35a1SLionel Sambuc ATF_REQUIRE(fd != -1); 83911be35a1SLionel Sambuc 84011be35a1SLionel Sambuc size = rump_sys_pread(fd, buf, sizeof(buf), 0); 84111be35a1SLionel Sambuc ATF_CHECK(size != -1 || errno == EISDIR); 84211be35a1SLionel Sambuc size = rump_sys_read(fd, buf, sizeof(buf)); 84311be35a1SLionel Sambuc ATF_CHECK(size != -1 || errno == EISDIR); 84411be35a1SLionel Sambuc 84511be35a1SLionel Sambuc res = rump_sys_close(fd); 84611be35a1SLionel Sambuc ATF_REQUIRE(res != -1); 84711be35a1SLionel Sambuc FSTEST_EXIT(); 84811be35a1SLionel Sambuc } 84911be35a1SLionel Sambuc 85011be35a1SLionel Sambuc ATF_TC_FSAPPLY(lookup_simple, "simple lookup (./.. on root)"); 85111be35a1SLionel Sambuc ATF_TC_FSAPPLY(lookup_complex, "lookup of non-dot entries"); 85211be35a1SLionel Sambuc ATF_TC_FSAPPLY(dir_simple, "mkdir/rmdir"); 85311be35a1SLionel Sambuc ATF_TC_FSAPPLY(dir_notempty, "non-empty directories cannot be removed"); 85411be35a1SLionel Sambuc ATF_TC_FSAPPLY(dir_rmdirdotdot, "remove .. and try to cd out (PR kern/44657)"); 85511be35a1SLionel Sambuc ATF_TC_FSAPPLY(rename_dir, "exercise various directory renaming ops " 85611be35a1SLionel Sambuc "(PR kern/44288)"); 85711be35a1SLionel Sambuc ATF_TC_FSAPPLY(rename_dotdot, "rename dir .. (PR kern/43617)"); 85811be35a1SLionel Sambuc ATF_TC_FSAPPLY(rename_reg_nodir, "rename regular files, no subdirectories"); 85911be35a1SLionel Sambuc ATF_TC_FSAPPLY(create_nametoolong, "create file with name too long"); 86011be35a1SLionel Sambuc ATF_TC_FSAPPLY(create_exist, "create with O_EXCL"); 86111be35a1SLionel Sambuc ATF_TC_FSAPPLY(rename_nametoolong, "rename to file with name too long"); 86211be35a1SLionel Sambuc ATF_TC_FSAPPLY(symlink_zerolen, "symlink with 0-len target"); 86311be35a1SLionel Sambuc ATF_TC_FSAPPLY(symlink_root, "symlink to root directory"); 86411be35a1SLionel Sambuc ATF_TC_FSAPPLY(attrs, "check setting attributes works"); 86511be35a1SLionel Sambuc ATF_TC_FSAPPLY(fcntl_lock, "check fcntl F_SETLK"); 86611be35a1SLionel Sambuc ATF_TC_FSAPPLY(fcntl_getlock_pids,"fcntl F_GETLK w/ many procs, PR kern/44494"); 86711be35a1SLionel Sambuc ATF_TC_FSAPPLY(access_simple, "access(2)"); 86811be35a1SLionel Sambuc ATF_TC_FSAPPLY(read_directory, "read(2) on directories"); 86911be35a1SLionel Sambuc 87011be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp) 87111be35a1SLionel Sambuc { 87211be35a1SLionel Sambuc 87311be35a1SLionel Sambuc ATF_TP_FSAPPLY(lookup_simple); 87411be35a1SLionel Sambuc ATF_TP_FSAPPLY(lookup_complex); 87511be35a1SLionel Sambuc ATF_TP_FSAPPLY(dir_simple); 87611be35a1SLionel Sambuc ATF_TP_FSAPPLY(dir_notempty); 87711be35a1SLionel Sambuc ATF_TP_FSAPPLY(dir_rmdirdotdot); 87811be35a1SLionel Sambuc ATF_TP_FSAPPLY(rename_dir); 87911be35a1SLionel Sambuc ATF_TP_FSAPPLY(rename_dotdot); 88011be35a1SLionel Sambuc ATF_TP_FSAPPLY(rename_reg_nodir); 88111be35a1SLionel Sambuc ATF_TP_FSAPPLY(create_nametoolong); 88211be35a1SLionel Sambuc ATF_TP_FSAPPLY(create_exist); 88311be35a1SLionel Sambuc ATF_TP_FSAPPLY(rename_nametoolong); 88411be35a1SLionel Sambuc ATF_TP_FSAPPLY(symlink_zerolen); 88511be35a1SLionel Sambuc ATF_TP_FSAPPLY(symlink_root); 88611be35a1SLionel Sambuc ATF_TP_FSAPPLY(attrs); 88711be35a1SLionel Sambuc ATF_TP_FSAPPLY(fcntl_lock); 88811be35a1SLionel Sambuc ATF_TP_FSAPPLY(fcntl_getlock_pids); 88911be35a1SLionel Sambuc ATF_TP_FSAPPLY(access_simple); 89011be35a1SLionel Sambuc ATF_TP_FSAPPLY(read_directory); 89111be35a1SLionel Sambuc 89211be35a1SLionel Sambuc return atf_no_error(); 89311be35a1SLionel Sambuc } 894