aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/defaults/acl_test.go3
-rw-r--r--tests/matrix/symlink_darwin_test.go39
-rw-r--r--tests/matrix/symlink_linux_test.go47
-rw-r--r--tests/plaintextnames/file_holes_test.go2
-rw-r--r--tests/reverse/xattr_test.go30
-rw-r--r--tests/root_test/btrfs_test.go65
-rw-r--r--tests/root_test/root_test.go3
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")