Skip to content

Commit

Permalink
Report inode number for the root node
Browse files Browse the repository at this point in the history
Now that hanwen/go-fuse#399 has
landed we can report an inode number for the root node.

Fixes #580
  • Loading branch information
rfjakob committed Nov 11, 2024
1 parent 12c0f3a commit 8689105
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 4 deletions.
15 changes: 13 additions & 2 deletions internal/fusefrontend/root_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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
}

Expand Down Expand Up @@ -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
}
15 changes: 13 additions & 2 deletions internal/fusefrontend_reverse/root_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand All @@ -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)
}
Expand Down Expand Up @@ -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
}
7 changes: 7 additions & 0 deletions mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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{
Expand Down
10 changes: 10 additions & 0 deletions tests/matrix/matrix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}
10 changes: 10 additions & 0 deletions tests/plaintextnames/plaintextnames_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}

0 comments on commit 8689105

Please sign in to comment.