aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend/node_helpers.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/fusefrontend/node_helpers.go')
-rw-r--r--internal/fusefrontend/node_helpers.go34
1 files changed, 34 insertions, 0 deletions
diff --git a/internal/fusefrontend/node_helpers.go b/internal/fusefrontend/node_helpers.go
index a7a32af..a31a41d 100644
--- a/internal/fusefrontend/node_helpers.go
+++ b/internal/fusefrontend/node_helpers.go
@@ -2,10 +2,14 @@ package fusefrontend
import (
"context"
+ "syscall"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
+
+ "github.com/rfjakob/gocryptfs/internal/syscallcompat"
+ "github.com/rfjakob/gocryptfs/internal/tlog"
)
// toFuseCtx tries to extract a fuse.Context from a generic context.Context.
@@ -29,3 +33,33 @@ func toNode(op fs.InodeEmbedder) *Node {
}
return op.(*Node)
}
+
+// readlink reads and decrypts a symlink. Used by Readlink, Getattr, Lookup.
+func (n *Node) readlink(dirfd int, cName string) (out []byte, errno syscall.Errno) {
+ cTarget, err := syscallcompat.Readlinkat(dirfd, cName)
+ if err != nil {
+ return nil, fs.ToErrno(err)
+ }
+ rn := n.rootNode()
+ if rn.args.PlaintextNames {
+ return []byte(cTarget), 0
+ }
+ // Symlinks are encrypted like file contents (GCM) and base64-encoded
+ target, err := rn.decryptSymlinkTarget(cTarget)
+ if err != nil {
+ tlog.Warn.Printf("Readlink %q: decrypting target failed: %v", cName, err)
+ return nil, syscall.EIO
+ }
+ return []byte(target), 0
+}
+
+// translateSize translates the ciphertext size in `out` into plaintext size.
+func (n *Node) translateSize(dirfd int, cName string, out *fuse.Attr) {
+ if out.IsRegular() {
+ rn := n.rootNode()
+ out.Size = rn.contentEnc.CipherSizeToPlainSize(out.Size)
+ } else if out.IsSymlink() {
+ target, _ := n.readlink(dirfd, cName)
+ out.Size = uint64(len(target))
+ }
+}