2020-08-01 20:48:32 +02:00
|
|
|
package fusefrontend_reverse
|
|
|
|
|
|
|
|
import (
|
2020-08-01 21:13:00 +02:00
|
|
|
"context"
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
"golang.org/x/sys/unix"
|
|
|
|
|
2020-08-01 20:48:32 +02:00
|
|
|
"github.com/hanwen/go-fuse/v2/fs"
|
2020-08-01 21:13:00 +02:00
|
|
|
"github.com/hanwen/go-fuse/v2/fuse"
|
|
|
|
|
|
|
|
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
2020-08-01 20:48:32 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// Node is a file or directory in the filesystem tree
|
|
|
|
// in a `gocryptfs -reverse` mount.
|
|
|
|
type Node struct {
|
|
|
|
fs.Inode
|
|
|
|
}
|
2020-08-01 21:13:00 +02:00
|
|
|
|
|
|
|
// 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) {
|
2020-08-01 23:06:35 +02:00
|
|
|
dirfd, pName, errno := n.prepareAtSyscall(name)
|
2020-08-01 21:13:00 +02:00
|
|
|
if errno != 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer syscall.Close(dirfd)
|
|
|
|
|
|
|
|
// Get device number and inode number into `st`
|
2020-08-01 23:06:35 +02:00
|
|
|
st, err := syscallcompat.Fstatat2(dirfd, pName, unix.AT_SYMLINK_NOFOLLOW)
|
2020-08-01 21:13:00 +02:00
|
|
|
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
|
2020-08-01 23:06:35 +02:00
|
|
|
n.translateSize(dirfd, pName, &out.Attr)
|
2020-08-01 21:13:00 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2020-08-01 23:06:35 +02:00
|
|
|
dirfd, pName, errno := n.prepareAtSyscall("")
|
2020-08-01 21:13:00 +02:00
|
|
|
if errno != 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer syscall.Close(dirfd)
|
|
|
|
|
2020-08-01 23:06:35 +02:00
|
|
|
st, err := syscallcompat.Fstatat2(dirfd, pName, unix.AT_SYMLINK_NOFOLLOW)
|
2020-08-01 21:13:00 +02:00
|
|
|
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
|
2020-08-01 23:06:35 +02:00
|
|
|
n.translateSize(dirfd, pName, &out.Attr)
|
2020-08-01 21:13:00 +02:00
|
|
|
|
|
|
|
if rn.args.ForceOwner != nil {
|
|
|
|
out.Owner = *rn.args.ForceOwner
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
}
|