diff options
author | Jakob Unterwurzacher | 2020-08-01 21:13:00 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2020-08-01 21:14:33 +0200 |
commit | f54d21c38427e68b598546c1c870a289cb5e99bb (patch) | |
tree | eeb3a55f70a3cb105a0da8e46ad6423f98da0401 /internal/fusefrontend_reverse/node.go | |
parent | 18b3bdb1584fd8e3dde89a95c0dfff910dd95ae1 (diff) |
v2api/reverse: implement Lookup & Getattr
Diffstat (limited to 'internal/fusefrontend_reverse/node.go')
-rw-r--r-- | internal/fusefrontend_reverse/node.go | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/node.go b/internal/fusefrontend_reverse/node.go index 6a1294a..a102a66 100644 --- a/internal/fusefrontend_reverse/node.go +++ b/internal/fusefrontend_reverse/node.go @@ -1,7 +1,15 @@ package fusefrontend_reverse import ( + "context" + "syscall" + + "golang.org/x/sys/unix" + "github.com/hanwen/go-fuse/v2/fs" + "github.com/hanwen/go-fuse/v2/fuse" + + "github.com/rfjakob/gocryptfs/internal/syscallcompat" ) // Node is a file or directory in the filesystem tree @@ -9,3 +17,61 @@ import ( type Node struct { fs.Inode } + +// Lookup - FUSE call for discovering a file. +// TODO handle virtual files +func (n *Node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (ch *fs.Inode, errno syscall.Errno) { + dirfd, cName, errno := n.prepareAtSyscall(name) + if errno != 0 { + return + } + defer syscall.Close(dirfd) + + // Get device number and inode number into `st` + st, err := syscallcompat.Fstatat2(dirfd, cName, unix.AT_SYMLINK_NOFOLLOW) + if err != nil { + return nil, fs.ToErrno(err) + } + + // Create new inode and fill `out` + ch = n.newChild(ctx, st, out) + + // Translate ciphertext size in `out.Attr.Size` to plaintext size + n.translateSize(dirfd, cName, &out.Attr) + + return ch, 0 +} + +// GetAttr - FUSE call for stat()ing a file. +// +// GetAttr is symlink-safe through use of openBackingDir() and Fstatat(). +func (n *Node) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut) (errno syscall.Errno) { + // If the kernel gives us a file handle, use it. + if f != nil { + return f.(fs.FileGetattrer).Getattr(ctx, out) + } + + dirfd, cName, errno := n.prepareAtSyscall("") + if errno != 0 { + return + } + defer syscall.Close(dirfd) + + st, err := syscallcompat.Fstatat2(dirfd, cName, unix.AT_SYMLINK_NOFOLLOW) + if err != nil { + return fs.ToErrno(err) + } + + // Fix inode number + rn := n.rootNode() + rn.inoMap.TranslateStat(st) + out.Attr.FromStat(st) + + // Translate ciphertext size in `out.Attr.Size` to plaintext size + n.translateSize(dirfd, cName, &out.Attr) + + if rn.args.ForceOwner != nil { + out.Owner = *rn.args.ForceOwner + } + return 0 +} |