Skip to content

Commit 8689105

Browse files
committed
Report inode number for the root node
Now that hanwen/go-fuse#399 has landed we can report an inode number for the root node. Fixes #580
1 parent 12c0f3a commit 8689105

File tree

5 files changed

+53
-4
lines changed

5 files changed

+53
-4
lines changed

internal/fusefrontend/root_node.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,16 @@ type RootNode struct {
5959
// quirks is a bitmap that enables workaround for quirks in the filesystem
6060
// backing the cipherdir
6161
quirks uint64
62+
// rootIno is the inode number that we report for the root node on mount
63+
rootIno uint64
6264
}
6365

6466
func NewRootNode(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {
6567
var rootDev uint64
6668
var st syscall.Stat_t
67-
if err := syscall.Stat(args.Cipherdir, &st); err != nil {
68-
tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err)
69+
var statErr error
70+
if statErr = syscall.Stat(args.Cipherdir, &st); statErr != nil {
71+
tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, statErr)
6972
} else {
7073
rootDev = uint64(st.Dev)
7174
}
@@ -87,6 +90,10 @@ func NewRootNode(args Args, c *contentenc.ContentEnc, n *nametransform.NameTrans
8790
dirCache: dirCache{ivLen: ivLen},
8891
quirks: syscallcompat.DetectQuirks(args.Cipherdir),
8992
}
93+
if statErr == nil {
94+
rn.inoMap.TranslateStat(&st)
95+
rn.rootIno = st.Ino
96+
}
9097
return rn
9198
}
9299

@@ -288,3 +295,7 @@ func (rn *RootNode) decryptXattrName(cAttr string) (attr string, err error) {
288295
}
289296
return attr, nil
290297
}
298+
299+
func (rn *RootNode) RootIno() uint64 {
300+
return rn.rootIno
301+
}

internal/fusefrontend_reverse/root_node.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ type RootNode struct {
5151
// bizarre problems when inode numbers are reused behind our back,
5252
// like this one: https://github.com/rfjakob/gocryptfs/issues/802
5353
gen uint64
54+
// rootIno is the inode number that we report for the root node on mount
55+
rootIno uint64
5456
}
5557

5658
// NewRootNode returns an encrypted FUSE overlay filesystem.
@@ -59,9 +61,10 @@ type RootNode struct {
5961
func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {
6062
var rootDev uint64
6163
var st syscall.Stat_t
64+
var statErr error
6265
var shortNameMax int
63-
if err := syscall.Stat(args.Cipherdir, &st); err != nil {
64-
tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err)
66+
if statErr = syscall.Stat(args.Cipherdir, &st); statErr != nil {
67+
tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, statErr)
6568
if args.OneFileSystem {
6669
tlog.Fatal.Printf("This is a fatal error in combination with -one-file-system")
6770
os.Exit(exitcodes.CipherDir)
@@ -81,6 +84,10 @@ func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransf
8184
rootDev: rootDev,
8285
shortNameMax: shortNameMax,
8386
}
87+
if statErr == nil {
88+
rn.inoMap.TranslateStat(&st)
89+
rn.rootIno = st.Ino
90+
}
8491
if len(args.Exclude) > 0 || len(args.ExcludeWildcard) > 0 || len(args.ExcludeFrom) > 0 {
8592
rn.excluder = prepareExcluder(args)
8693
}
@@ -171,3 +178,7 @@ func (rn *RootNode) uniqueStableAttr(mode uint32, ino uint64) fs.StableAttr {
171178
Gen: atomic.AddUint64(&rn.gen, 1),
172179
}
173180
}
181+
182+
func (rn *RootNode) RootIno() uint64 {
183+
return rn.rootIno
184+
}

mount.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f
351351
return rootNode, func() { cCore.Wipe() }
352352
}
353353

354+
type RootInoer interface {
355+
RootIno() uint64
356+
}
357+
354358
// initGoFuse calls into go-fuse to mount `rootNode` on `args.mountpoint`.
355359
// The mountpoint is ready to use when the functions returns.
356360
// On error, it calls os.Exit and does not return.
@@ -375,6 +379,9 @@ func initGoFuse(rootNode fs.InodeEmbedder, args *argContainer) *fuse.Server {
375379
}
376380
}
377381
fuseOpts.NullPermissions = true
382+
// The inode number for the root node must be manually set on mount
383+
// https://github.com/hanwen/go-fuse/issues/399
384+
fuseOpts.RootStableAttr = &fs.StableAttr{Ino: rootNode.(RootInoer).RootIno()}
378385
// Enable go-fuse warnings
379386
fuseOpts.Logger = log.New(os.Stderr, "go-fuse: ", log.Lmicroseconds)
380387
fuseOpts.MountOptions = fuse.MountOptions{

tests/matrix/matrix_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,3 +972,13 @@ func TestPwd(t *testing.T) {
972972
os.Mkdir(dir, 0700)
973973
}
974974
}
975+
976+
// TestRootIno checks that inode number of the root dir is set
977+
// https://github.com/hanwen/go-fuse/issues/399
978+
func TestRootIno(t *testing.T) {
979+
var st syscall.Stat_t
980+
syscall.Stat(test_helpers.DefaultPlainDir, &st)
981+
if st.Ino == 0 {
982+
t.Errorf("inode number of root dir is zero")
983+
}
984+
}

tests/plaintextnames/plaintextnames_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,13 @@ func TestInoReuseEvil(t *testing.T) {
125125
t.Logf("file ino = %d", st.Ino)
126126
}
127127
}
128+
129+
// TestRootIno checks that inode number of the root dir is set
130+
// https://github.com/hanwen/go-fuse/issues/399
131+
func TestRootIno(t *testing.T) {
132+
var st syscall.Stat_t
133+
syscall.Stat(cDir, &st)
134+
if st.Ino == 0 {
135+
t.Errorf("inode number of root dir is zero")
136+
}
137+
}

0 commit comments

Comments
 (0)