aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/fusefrontend/root_node.go15
-rw-r--r--internal/fusefrontend_reverse/root_node.go15
-rw-r--r--mount.go7
-rw-r--r--tests/matrix/matrix_test.go10
-rw-r--r--tests/plaintextnames/plaintextnames_test.go10
5 files changed, 53 insertions, 4 deletions
diff --git a/internal/fusefrontend/root_node.go b/internal/fusefrontend/root_node.go
index 39cdef7..ac814ad 100644
--- a/internal/fusefrontend/root_node.go
+++ b/internal/fusefrontend/root_node.go
@@ -59,13 +59,16 @@ type RootNode struct {
// quirks is a bitmap that enables workaround for quirks in the filesystem
// backing the cipherdir
quirks uint64
+ // rootIno is the inode number that we report for the root node on mount
+ rootIno uint64
}
func NewRootNode(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {
var rootDev uint64
var st syscall.Stat_t
- if err := syscall.Stat(args.Cipherdir, &st); err != nil {
- tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err)
+ var statErr error
+ if statErr = syscall.Stat(args.Cipherdir, &st); statErr != nil {
+ tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, statErr)
} else {
rootDev = uint64(st.Dev)
}
@@ -87,6 +90,10 @@ func NewRootNode(args Args, c *contentenc.ContentEnc, n *nametransform.NameTrans
dirCache: dirCache{ivLen: ivLen},
quirks: syscallcompat.DetectQuirks(args.Cipherdir),
}
+ if statErr == nil {
+ rn.inoMap.TranslateStat(&st)
+ rn.rootIno = st.Ino
+ }
return rn
}
@@ -288,3 +295,7 @@ func (rn *RootNode) decryptXattrName(cAttr string) (attr string, err error) {
}
return attr, nil
}
+
+func (rn *RootNode) RootIno() uint64 {
+ return rn.rootIno
+}
diff --git a/internal/fusefrontend_reverse/root_node.go b/internal/fusefrontend_reverse/root_node.go
index 9de81b5..cb04151 100644
--- a/internal/fusefrontend_reverse/root_node.go
+++ b/internal/fusefrontend_reverse/root_node.go
@@ -51,6 +51,8 @@ type RootNode struct {
// bizarre problems when inode numbers are reused behind our back,
// like this one: https://github.com/rfjakob/gocryptfs/issues/802
gen uint64
+ // rootIno is the inode number that we report for the root node on mount
+ rootIno uint64
}
// NewRootNode returns an encrypted FUSE overlay filesystem.
@@ -59,9 +61,10 @@ type RootNode struct {
func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {
var rootDev uint64
var st syscall.Stat_t
+ var statErr error
var shortNameMax int
- if err := syscall.Stat(args.Cipherdir, &st); err != nil {
- tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err)
+ if statErr = syscall.Stat(args.Cipherdir, &st); statErr != nil {
+ tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, statErr)
if args.OneFileSystem {
tlog.Fatal.Printf("This is a fatal error in combination with -one-file-system")
os.Exit(exitcodes.CipherDir)
@@ -81,6 +84,10 @@ func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransf
rootDev: rootDev,
shortNameMax: shortNameMax,
}
+ if statErr == nil {
+ rn.inoMap.TranslateStat(&st)
+ rn.rootIno = st.Ino
+ }
if len(args.Exclude) > 0 || len(args.ExcludeWildcard) > 0 || len(args.ExcludeFrom) > 0 {
rn.excluder = prepareExcluder(args)
}
@@ -171,3 +178,7 @@ func (rn *RootNode) uniqueStableAttr(mode uint32, ino uint64) fs.StableAttr {
Gen: atomic.AddUint64(&rn.gen, 1),
}
}
+
+func (rn *RootNode) RootIno() uint64 {
+ return rn.rootIno
+}
diff --git a/mount.go b/mount.go
index 61079a9..0eaa3dd 100644
--- a/mount.go
+++ b/mount.go
@@ -351,6 +351,10 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f
return rootNode, func() { cCore.Wipe() }
}
+type RootInoer interface {
+ RootIno() uint64
+}
+
// initGoFuse calls into go-fuse to mount `rootNode` on `args.mountpoint`.
// The mountpoint is ready to use when the functions returns.
// On error, it calls os.Exit and does not return.
@@ -375,6 +379,9 @@ func initGoFuse(rootNode fs.InodeEmbedder, args *argContainer) *fuse.Server {
}
}
fuseOpts.NullPermissions = true
+ // The inode number for the root node must be manually set on mount
+ // https://github.com/hanwen/go-fuse/issues/399
+ fuseOpts.RootStableAttr = &fs.StableAttr{Ino: rootNode.(RootInoer).RootIno()}
// Enable go-fuse warnings
fuseOpts.Logger = log.New(os.Stderr, "go-fuse: ", log.Lmicroseconds)
fuseOpts.MountOptions = fuse.MountOptions{
diff --git a/tests/matrix/matrix_test.go b/tests/matrix/matrix_test.go
index 0d9c22c..417e126 100644
--- a/tests/matrix/matrix_test.go
+++ b/tests/matrix/matrix_test.go
@@ -972,3 +972,13 @@ func TestPwd(t *testing.T) {
os.Mkdir(dir, 0700)
}
}
+
+// TestRootIno checks that inode number of the root dir is set
+// https://github.com/hanwen/go-fuse/issues/399
+func TestRootIno(t *testing.T) {
+ var st syscall.Stat_t
+ syscall.Stat(test_helpers.DefaultPlainDir, &st)
+ if st.Ino == 0 {
+ t.Errorf("inode number of root dir is zero")
+ }
+}
diff --git a/tests/plaintextnames/plaintextnames_test.go b/tests/plaintextnames/plaintextnames_test.go
index 8892c39..4de0730 100644
--- a/tests/plaintextnames/plaintextnames_test.go
+++ b/tests/plaintextnames/plaintextnames_test.go
@@ -125,3 +125,13 @@ func TestInoReuseEvil(t *testing.T) {
t.Logf("file ino = %d", st.Ino)
}
}
+
+// TestRootIno checks that inode number of the root dir is set
+// https://github.com/hanwen/go-fuse/issues/399
+func TestRootIno(t *testing.T) {
+ var st syscall.Stat_t
+ syscall.Stat(cDir, &st)
+ if st.Ino == 0 {
+ t.Errorf("inode number of root dir is zero")
+ }
+}