v2api/reverse: implement Readdir
This commit is contained in:
parent
f54d21c384
commit
6c26cda531
81
internal/fusefrontend_reverse/node_dir_ops.go
Normal file
81
internal/fusefrontend_reverse/node_dir_ops.go
Normal file
@ -0,0 +1,81 @@
|
||||
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/configfile"
|
||||
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
||||
"github.com/rfjakob/gocryptfs/internal/pathiv"
|
||||
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
||||
)
|
||||
|
||||
// Readdir - FUSE call.
|
||||
//
|
||||
// This function is symlink-safe through use of openBackingDir() and
|
||||
// ReadDirIVAt().
|
||||
func (n *Node) Readdir(ctx context.Context) (stream fs.DirStream, errno syscall.Errno) {
|
||||
dirfd, cName, errno := n.prepareAtSyscall("")
|
||||
if errno != 0 {
|
||||
return
|
||||
}
|
||||
defer syscall.Close(dirfd)
|
||||
|
||||
// Read plaintext directory
|
||||
var entries []fuse.DirEntry
|
||||
fd, err := syscallcompat.Openat(dirfd, cName, syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0)
|
||||
if err != nil {
|
||||
return nil, fs.ToErrno(err)
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
entries, err = syscallcompat.Getdents(fd)
|
||||
if err != nil {
|
||||
return nil, fs.ToErrno(err)
|
||||
}
|
||||
|
||||
rn := n.rootNode()
|
||||
if rn.args.PlaintextNames {
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
// Filter out excluded entries
|
||||
//TODO
|
||||
//entries = rfs.excludeDirEntries(relPath, entries)
|
||||
|
||||
// Virtual files: at least one gocryptfs.diriv file
|
||||
virtualFiles := []fuse.DirEntry{
|
||||
{Mode: virtualFileMode, Name: nametransform.DirIVFilename},
|
||||
}
|
||||
|
||||
cipherPath := n.Path()
|
||||
dirIV := pathiv.Derive(cipherPath, pathiv.PurposeDirIV)
|
||||
// Encrypt names
|
||||
for i := range entries {
|
||||
var cName string
|
||||
// ".gocryptfs.reverse.conf" in the root directory is mapped to "gocryptfs.conf"
|
||||
if n.isRoot() && entries[i].Name == configfile.ConfReverseName &&
|
||||
!rn.args.ConfigCustom {
|
||||
cName = configfile.ConfDefaultName
|
||||
} else {
|
||||
cName = rn.nameTransform.EncryptName(entries[i].Name, dirIV)
|
||||
if len(cName) > unix.NAME_MAX {
|
||||
cName = rn.nameTransform.HashLongName(cName)
|
||||
dotNameFile := fuse.DirEntry{
|
||||
Mode: virtualFileMode,
|
||||
Name: cName + nametransform.LongNameSuffix,
|
||||
}
|
||||
virtualFiles = append(virtualFiles, dotNameFile)
|
||||
}
|
||||
}
|
||||
entries[i].Name = cName
|
||||
}
|
||||
|
||||
// Add virtual files
|
||||
entries = append(entries, virtualFiles...)
|
||||
return fs.NewListDirStream(entries), 0
|
||||
}
|
@ -65,3 +65,9 @@ func (n *Node) newChild(ctx context.Context, st *syscall.Stat_t, out *fuse.Entry
|
||||
node := &Node{}
|
||||
return n.NewInode(ctx, node, id)
|
||||
}
|
||||
|
||||
// isRoot returns true if this node is the root node
|
||||
func (n *Node) isRoot() bool {
|
||||
rn := n.rootNode()
|
||||
return &rn.Node == n
|
||||
}
|
||||
|
15
internal/fusefrontend_reverse/virtualfile.go
Normal file
15
internal/fusefrontend_reverse/virtualfile.go
Normal file
@ -0,0 +1,15 @@
|
||||
package fusefrontend_reverse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
// virtualFileMode is the mode to use for virtual files (gocryptfs.diriv and
|
||||
// *.name). They are always readable, as stated in func Access
|
||||
virtualFileMode = syscall.S_IFREG | 0444
|
||||
// We use inomap's `Tag` feature to generate unique inode numbers for
|
||||
// virtual files. These are the tags we use.
|
||||
inoTagDirIV = 1
|
||||
inoTagNameFile = 2
|
||||
)
|
Loading…
Reference in New Issue
Block a user