aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAnkush Patel2026-02-14 03:41:23 +1300
committerAnkush Patel2026-02-14 03:41:23 +1300
commit8d8fb15f0b3680add1f3b28c062b573a92221ab0 (patch)
treefbd54302af652c38eb292167919125a8b57f5d2a /tests
parent903fc9d077a81d9224de4207d1672c0b1127cf42 (diff)
parent5f5c34ac78cb9d1765ce9cabe87420c32f9d867e (diff)
Merge branch 'master' into freebsd-support
Diffstat (limited to 'tests')
-rw-r--r--tests/matrix/symlink_darwin_test.go39
-rw-r--r--tests/matrix/symlink_linux_test.go47
-rw-r--r--tests/reverse/xattr_test.go16
-rw-r--r--tests/root_test/btrfs_test.go63
4 files changed, 156 insertions, 9 deletions
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/reverse/xattr_test.go b/tests/reverse/xattr_test.go
index 406d055..b6a7b34 100644
--- a/tests/reverse/xattr_test.go
+++ b/tests/reverse/xattr_test.go
@@ -9,6 +9,7 @@ import (
"testing"
"github.com/pkg/xattr"
+ "golang.org/x/sys/unix"
)
func xattrSupported(path string) bool {
@@ -65,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 72b7751..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.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)
+ }
+}