diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/defaults/acl_test.go | 3 | ||||
| -rw-r--r-- | tests/matrix/symlink_darwin_test.go | 39 | ||||
| -rw-r--r-- | tests/matrix/symlink_linux_test.go | 47 | ||||
| -rw-r--r-- | tests/plaintextnames/file_holes_test.go | 2 | ||||
| -rw-r--r-- | tests/reverse/xattr_test.go | 30 | ||||
| -rw-r--r-- | tests/root_test/btrfs_test.go | 65 | ||||
| -rw-r--r-- | tests/root_test/root_test.go | 3 |
7 files changed, 166 insertions, 23 deletions
diff --git a/tests/defaults/acl_test.go b/tests/defaults/acl_test.go index 0dae018..bddb5e5 100644 --- a/tests/defaults/acl_test.go +++ b/tests/defaults/acl_test.go @@ -7,7 +7,6 @@ import ( "path/filepath" "syscall" "testing" - "time" "golang.org/x/sys/unix" @@ -21,8 +20,6 @@ func TestCpA(t *testing.T) { fn1 := filepath.Join(test_helpers.TmpDir, t.Name()) fn2 := filepath.Join(test_helpers.DefaultPlainDir, t.Name()) - rand.Seed(int64(time.Now().Nanosecond())) - { // Need unrestricted umask old := syscall.Umask(000) diff --git a/tests/matrix/symlink_darwin_test.go b/tests/matrix/symlink_darwin_test.go new file mode 100644 index 0000000..be28d9d --- /dev/null +++ b/tests/matrix/symlink_darwin_test.go @@ -0,0 +1,39 @@ +package matrix + +import ( + "os" + "testing" + + "golang.org/x/sys/unix" + + "github.com/rfjakob/gocryptfs/v2/tests/test_helpers" +) + +// TestOpenSymlinkDarwin checks that a symlink can be opened +// using O_SYMLINK. +func TestOpenSymlinkDarwin(t *testing.T) { + path := test_helpers.DefaultPlainDir + "/TestOpenSymlink" + target := "/target/does/not/exist" + err := os.Symlink(target, path) + if err != nil { + t.Fatal(err) + } + fd, err := unix.Open(path, unix.O_RDONLY|unix.O_SYMLINK, 0) + if err != nil { + t.Fatal(err) + } + defer unix.Close(fd) + var st unix.Stat_t + if err := unix.Fstat(fd, &st); err != nil { + t.Fatal(err) + } + if st.Size != int64(len(target)) { + t.Errorf("wrong size: have=%d want=%d", st.Size, len(target)) + } + if err := unix.Unlink(path); err != nil { + t.Fatal(err) + } + if err := unix.Fstat(fd, &st); err != nil { + t.Error(err) + } +} diff --git a/tests/matrix/symlink_linux_test.go b/tests/matrix/symlink_linux_test.go new file mode 100644 index 0000000..fdb7051 --- /dev/null +++ b/tests/matrix/symlink_linux_test.go @@ -0,0 +1,47 @@ +package matrix + +import ( + "os" + "testing" + + "golang.org/x/sys/unix" + + "github.com/rfjakob/gocryptfs/v2/tests/test_helpers" +) + +// TestOpenSymlinkLinux checks that a symlink can be opened +// using O_PATH. +// Only works on Linux because is uses O_PATH and AT_EMPTY_PATH. +// MacOS has O_SYMLINK instead (see TestOpenSymlinkDarwin). +func TestOpenSymlinkLinux(t *testing.T) { + path := test_helpers.DefaultPlainDir + "/TestOpenSymlink" + target := "/target/does/not/exist" + err := os.Symlink(target, path) + if err != nil { + t.Fatal(err) + } + how := unix.OpenHow{ + Flags: unix.O_PATH | unix.O_NOFOLLOW, + } + fd, err := unix.Openat2(unix.AT_FDCWD, path, &how) + if err != nil { + t.Fatal(err) + } + defer unix.Close(fd) + var st unix.Stat_t + if err := unix.Fstatat(fd, "", &st, unix.AT_EMPTY_PATH); err != nil { + t.Fatal(err) + } + if st.Size != int64(len(target)) { + t.Errorf("wrong size: have=%d want=%d", st.Size, len(target)) + } + if err := unix.Unlink(path); err != nil { + t.Fatal(err) + } + if err = unix.Fstatat(fd, "", &st, unix.AT_EMPTY_PATH); err != nil { + // That's a bug, but I have never heard of a use case that would break because of this. + // Also I don't see how to fix it, as gocryptfs does not get informed about the earlier + // Openat2(). + t.Logf("posix compliance issue: deleted symlink cannot be accessed: Fstatat: %v", err) + } +} diff --git a/tests/plaintextnames/file_holes_test.go b/tests/plaintextnames/file_holes_test.go index ea47113..7a356c0 100644 --- a/tests/plaintextnames/file_holes_test.go +++ b/tests/plaintextnames/file_holes_test.go @@ -7,7 +7,6 @@ import ( "os/exec" "syscall" "testing" - "time" "github.com/rfjakob/gocryptfs/v2/tests/test_helpers" @@ -140,7 +139,6 @@ func TestFileHoleCopy(t *testing.T) { return } - rand.Seed(time.Now().UnixNano()) for k := 0; k < 100; k++ { c1 := make([]int64, 10) for i := range c1 { diff --git a/tests/reverse/xattr_test.go b/tests/reverse/xattr_test.go index c70f623..b6a7b34 100644 --- a/tests/reverse/xattr_test.go +++ b/tests/reverse/xattr_test.go @@ -4,10 +4,12 @@ import ( "fmt" "os" "path/filepath" + "strings" "syscall" "testing" "github.com/pkg/xattr" + "golang.org/x/sys/unix" ) func xattrSupported(path string) bool { @@ -20,8 +22,6 @@ func xattrSupported(path string) bool { } func TestXattrList(t *testing.T) { - t.Skip("TODO: not implemented yet in reverse mode") - if !xattrSupported(dirA) { t.Skip() } @@ -32,7 +32,7 @@ func TestXattrList(t *testing.T) { } val := []byte("xxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzz") num := 20 - var namesA map[string]string + namesA := map[string]string{} for i := 1; i <= num; i++ { attr := fmt.Sprintf("user.TestXattrList.%02d", i) err = xattr.LSet(fnA, attr, val) @@ -46,9 +46,14 @@ func TestXattrList(t *testing.T) { if err != nil { t.Fatal(err) } - var namesC map[string]string + namesC := map[string]string{} for _, n := range tmp { - namesC[n] = string(val) + if strings.HasPrefix(n, "security.") { + t.Logf("Ignoring xattr %q", n) + continue + } + v, _ := xattr.LGet(fnC, n) + namesC[n] = string(v) } if len(namesA) != len(namesC) { t.Errorf("wrong number of names, want=%d have=%d", len(namesA), len(namesC)) @@ -61,3 +66,18 @@ func TestXattrList(t *testing.T) { } } } + +// Shouldn't get EINVAL when querying the mountpoint. +func TestXattrGetMountpoint(t *testing.T) { + _, err := xattr.LGet(dirB, "user.foo453465324") + if err == nil { + return + } + e2 := err.(*xattr.Error) + if e2.Unwrap() == unix.EINVAL { + t.Errorf("LGet: %v", err) + } + // Let's see what LList says + _, err = xattr.LList(dirB) + t.Logf("LList: err=%v", err) +} diff --git a/tests/root_test/btrfs_test.go b/tests/root_test/btrfs_test.go index 4f2527a..898cd39 100644 --- a/tests/root_test/btrfs_test.go +++ b/tests/root_test/btrfs_test.go @@ -12,12 +12,20 @@ import ( "github.com/rfjakob/gocryptfs/v2/tests/test_helpers" ) -// TestBtrfsQuirks needs root permissions because it creates a loop disk -func TestBtrfsQuirks(t *testing.T) { +// createBtrfsImage creates a btrfs image file, formats it, and mounts it. +// Returns the mount path and a cleanup function. +func createBtrfsImage(t *testing.T) (mnt string, cleanup func()) { + t.Helper() + if os.Getuid() != 0 { t.Skip("must run as root") } + _, err := exec.LookPath("mkfs.btrfs") + if err != nil { + t.Skip("mkfs.btrfs not found, skipping test") + } + img := filepath.Join(test_helpers.TmpDir, t.Name()+".img") f, err := os.Create(img) if err != nil { @@ -31,10 +39,6 @@ func TestBtrfsQuirks(t *testing.T) { } // Format as Btrfs - _, err = exec.LookPath("mkfs.btrfs") - if err != nil { - t.Skip("mkfs.btrfs not found, skipping test") - } cmd := exec.Command("mkfs.btrfs", img) out, err := cmd.CombinedOutput() if err != nil { @@ -44,7 +48,7 @@ func TestBtrfsQuirks(t *testing.T) { } // Mount - mnt := img + ".mnt" + mnt = img + ".mnt" err = os.Mkdir(mnt, 0600) if err != nil { t.Fatal(err) @@ -55,11 +59,52 @@ func TestBtrfsQuirks(t *testing.T) { t.Log(string(out)) t.Fatal(err) } - defer syscall.Unlink(img) - defer syscall.Unmount(mnt, 0) + + cleanup = func() { + syscall.Unmount(mnt, 0) + syscall.Unlink(img) + } + return mnt, cleanup +} + +// TestBtrfsQuirks needs root permissions because it creates a loop disk +func TestBtrfsQuirks(t *testing.T) { + mnt, cleanup := createBtrfsImage(t) + defer cleanup() quirk := syscallcompat.DetectQuirks(mnt) - if quirk != syscallcompat.QuirkBrokenFalloc { + if quirk != syscallcompat.QuirkBtrfsBrokenFalloc { t.Errorf("wrong quirk: %v", quirk) } } + +// TestBtrfsQuirksNoCow verifies that when the backing directory has +// the NOCOW attribute (chattr +C), the QuirkBtrfsBrokenFalloc quirk +// is NOT set, because fallocate works correctly with NOCOW. +func TestBtrfsQuirksNoCow(t *testing.T) { + mnt, cleanup := createBtrfsImage(t) + defer cleanup() + + _, err := exec.LookPath("chattr") + if err != nil { + t.Skip("chattr not found, skipping test") + } + + // Create a subdirectory with NOCOW attribute + nocowDir := filepath.Join(mnt, "nocow") + err = os.Mkdir(nocowDir, 0700) + if err != nil { + t.Fatal(err) + } + cmd := exec.Command("chattr", "+C", nocowDir) + out, err := cmd.CombinedOutput() + if err != nil { + t.Log(string(out)) + t.Fatal(err) + } + + quirk := syscallcompat.DetectQuirks(nocowDir) + if quirk&syscallcompat.QuirkBtrfsBrokenFalloc != 0 { + t.Errorf("QuirkBtrfsBrokenFalloc should not be set on NOCOW directory, got quirks: %v", quirk) + } +} diff --git a/tests/root_test/root_test.go b/tests/root_test/root_test.go index c531ebb..650d802 100644 --- a/tests/root_test/root_test.go +++ b/tests/root_test/root_test.go @@ -305,9 +305,6 @@ func TestOverlay(t *testing.T) { t.Skip("must run as root") } cDir := test_helpers.InitFS(t) - if syscallcompat.DetectQuirks(cDir)&syscallcompat.QuirkNoUserXattr != 0 { - t.Logf("No user xattrs! overlay mount will likely fail.") - } os.Chmod(cDir, 0755) pDir := cDir + ".mnt" test_helpers.MountOrFatal(t, cDir, pDir, "-allow_other", "-extpass=echo test") |
