aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/defaults/overlayfs_test.go109
1 files changed, 109 insertions, 0 deletions
diff --git a/tests/defaults/overlayfs_test.go b/tests/defaults/overlayfs_test.go
new file mode 100644
index 0000000..1a3298d
--- /dev/null
+++ b/tests/defaults/overlayfs_test.go
@@ -0,0 +1,109 @@
+// +build linux
+
+package defaults
+
+import (
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+
+ "golang.org/x/sys/unix"
+
+ "github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
+ "github.com/rfjakob/gocryptfs/v2/tests/test_helpers"
+)
+
+// https://github.com/rfjakob/gocryptfs/issues/641
+//
+// I was trying to run the Docker daemon with the recommended overlay2 storage driver, and encrypt its `/var/lib/docker` directory using gocryptfs. overlay2 was giving me the following errors:
+// ```
+// Jan 21 19:09:43 friedhelm.rankenste.in kernel: overlayfs: upper fs does not support tmpfile.
+// Jan 21 19:09:43 friedhelm.rankenste.in kernel: overlayfs: upper fs does not support RENAME_WHITEOUT.
+// Jan 21 19:09:43 friedhelm.rankenste.in kernel: overlayfs: upper fs missing required features.
+// ```
+
+func TestRenameWhiteout(t *testing.T) {
+ short := t.Name() + ".short"
+ long := t.Name() + strings.Repeat(".long", 200/len(".long"))
+
+ names := [][]string{
+ // short to short
+ {short + "s2s", short + "s2s2"},
+ // short to long
+ {short + "s2l", long + "s2l2"},
+ // long to short
+ {long + "l2s", short + "l2s2"},
+ // long to long
+ {long + "l2l", short + "l2l2"},
+ }
+
+ for _, flags := range []uint{syscallcompat.RENAME_WHITEOUT, syscallcompat.RENAME_WHITEOUT | syscallcompat.RENAME_NOREPLACE} {
+ for _, n := range names {
+ pSrc := test_helpers.DefaultPlainDir + "/" + n[0]
+ pDst := test_helpers.DefaultPlainDir + "/" + n[1]
+ if err := ioutil.WriteFile(pSrc, nil, 0200); err != nil {
+ t.Fatalf("creating empty file failed: %v", err)
+ }
+ err := unix.Renameat2(-1, pSrc, -1, pDst, flags)
+ if err != nil {
+ t.Error(err)
+ }
+ // readdir should not choke on leftover or missing .name files
+ _, err = os.ReadDir(test_helpers.DefaultPlainDir)
+ if err != nil {
+ t.Error(err)
+ }
+ // pSrc should now be a character device 0 file
+ var st unix.Stat_t
+ err = unix.Stat(pSrc, &st)
+ if err != nil {
+ t.Error(err)
+ }
+ if !(st.Mode&unix.S_IFMT == unix.S_IFCHR) {
+ t.Error("not a device file")
+ }
+ if st.Rdev != 0 {
+ t.Errorf("want device 0, have %d", st.Rdev)
+ }
+ unix.Unlink(pSrc)
+ unix.Unlink(pDst)
+ }
+ }
+}
+
+func TestRenameExchange(t *testing.T) {
+ short := t.Name() + ".short"
+ long := t.Name() + strings.Repeat(".long", 200/len(".long"))
+
+ names := [][]string{
+ // short to short
+ {short + "s2s", short + "s2s2"},
+ // short to long
+ {short + "s2l", long + "s2l2"},
+ // long to short
+ {long + "l2s", short + "l2s2"},
+ // long to long
+ {long + "l2l", short + "l2l2"},
+ }
+
+ for _, n := range names {
+ pSrc := test_helpers.DefaultPlainDir + "/" + n[0]
+ pDst := test_helpers.DefaultPlainDir + "/" + n[1]
+ if err := ioutil.WriteFile(pSrc, nil, 0200); err != nil {
+ t.Fatalf("creating empty file failed: %v", err)
+ }
+ if err := ioutil.WriteFile(pDst, nil, 0200); err != nil {
+ t.Fatalf("creating empty file failed: %v", err)
+ }
+ err := unix.Renameat2(-1, pSrc, -1, pDst, unix.RENAME_EXCHANGE)
+ if err != nil {
+ t.Error(err)
+ }
+ // readdir should not choke on leftover or missing .name files
+ _, err = os.ReadDir(test_helpers.DefaultPlainDir)
+ if err != nil {
+ t.Error(err)
+ }
+ }
+}