diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/fusefrontend/node_helpers.go | 42 | ||||
| -rw-r--r-- | internal/fusefrontend/root_node.go | 3 | 
2 files changed, 34 insertions, 11 deletions
| diff --git a/internal/fusefrontend/node_helpers.go b/internal/fusefrontend/node_helpers.go index c44a559..6c30523 100644 --- a/internal/fusefrontend/node_helpers.go +++ b/internal/fusefrontend/node_helpers.go @@ -2,7 +2,9 @@ package fusefrontend  import (  	"context" +	"log"  	"path/filepath" +	"sync/atomic"  	"syscall"  	"github.com/hanwen/go-fuse/v2/fs" @@ -82,13 +84,37 @@ func (n *Node) rootNode() *RootNode {  //  // If you pass a `child` file name, the (dirfd, cName) pair will refer to  // a child of this node. -// If `child` is empty, the (dirfd, cName) pair refers to this node itself. +// If `child` is empty, the (dirfd, cName) pair refers to this node itself. For +// the root node, that means (dirfd, ".").  func (n *Node) prepareAtSyscall(child string) (dirfd int, cName string, errno syscall.Errno) {  	rn := n.rootNode() +	// all filesystem operations go through prepareAtSyscall(), so this is a +	// good place to reset the idle marker. +	atomic.StoreUint32(&rn.IsIdle, 0) + +	// root node itself is special +	if child == "" && n.IsRoot() { +		var err error +		dirfd, cName, err = rn.openBackingDir("") +		if err != nil { +			errno = fs.ToErrno(err) +		} +		return +	} + +	// normal node itself can be converted to child of parent node +	if child == "" { +		name, p1 := n.Parent() +		if p1 == nil || name == "" { +			return -1, "", syscall.ENOENT +		} +		p2 := toNode(p1.Operations()) +		return p2.prepareAtSyscall(name) +	}  	// Cache lookup -	// TODO: also handle caching for root node & plaintextnames -	cacheable := (child != "" && !rn.args.PlaintextNames) +	// TODO make it work for plaintextnames as well? +	cacheable := (!rn.args.PlaintextNames)  	if cacheable {  		var iv []byte  		dirfd, iv = rn.dirCache.Lookup(n) @@ -102,10 +128,10 @@ func (n *Node) prepareAtSyscall(child string) (dirfd int, cName string, errno sy  	}  	// Slowpath -	p := n.Path() -	if child != "" { -		p = filepath.Join(p, child) +	if child == "" { +		log.Panicf("BUG: child name is empty - this cannot happen")  	} +	p := filepath.Join(n.Path(), child)  	if rn.isFiltered(p) {  		errno = syscall.EPERM  		return @@ -113,12 +139,12 @@ func (n *Node) prepareAtSyscall(child string) (dirfd int, cName string, errno sy  	dirfd, cName, err := rn.openBackingDir(p)  	if err != nil {  		errno = fs.ToErrno(err) +		return  	}  	// Cache store -	// TODO: also handle caching for root node & plaintextnames  	if cacheable { -		// TODO: openBackingDir already calls ReadDirIVAt(). Get the data out. +		// TODO: openBackingDir already calls ReadDirIVAt(). Avoid duplicate work?  		iv, err := nametransform.ReadDirIVAt(dirfd)  		if err != nil {  			syscall.Close(dirfd) diff --git a/internal/fusefrontend/root_node.go b/internal/fusefrontend/root_node.go index 3a2ecf3..e998e9d 100644 --- a/internal/fusefrontend/root_node.go +++ b/internal/fusefrontend/root_node.go @@ -5,7 +5,6 @@ import (  	"path/filepath"  	"strings"  	"sync" -	"sync/atomic"  	"syscall"  	"time" @@ -127,8 +126,6 @@ func (rn *RootNode) reportMitigatedCorruption(item string) {  //  // Prevents name clashes with internal files when file names are not encrypted  func (rn *RootNode) isFiltered(path string) bool { -	atomic.StoreUint32(&rn.IsIdle, 0) -  	if !rn.args.PlaintextNames {  		return false  	} | 
