summaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse/node_dir_ops.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2020-08-01 22:28:25 +0200
committerJakob Unterwurzacher2020-08-01 22:28:25 +0200
commit6c26cda53122df871befd0c1e08b892e0d56d31e (patch)
treec3c31f747cd695e0961ecb36d7710a759c408816 /internal/fusefrontend_reverse/node_dir_ops.go
parentf54d21c38427e68b598546c1c870a289cb5e99bb (diff)
v2api/reverse: implement Readdir
Diffstat (limited to 'internal/fusefrontend_reverse/node_dir_ops.go')
-rw-r--r--internal/fusefrontend_reverse/node_dir_ops.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/node_dir_ops.go b/internal/fusefrontend_reverse/node_dir_ops.go
new file mode 100644
index 0000000..c48d884
--- /dev/null
+++ b/internal/fusefrontend_reverse/node_dir_ops.go
@@ -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
+}