aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse
diff options
context:
space:
mode:
Diffstat (limited to 'internal/fusefrontend_reverse')
-rw-r--r--internal/fusefrontend_reverse/rfs.go21
-rw-r--r--internal/fusefrontend_reverse/rpath.go6
2 files changed, 27 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go
index 6089d41..cfe23b6 100644
--- a/internal/fusefrontend_reverse/rfs.go
+++ b/internal/fusefrontend_reverse/rfs.go
@@ -1,6 +1,7 @@
package fusefrontend_reverse
import (
+ "encoding/base64"
"fmt"
"os"
"path/filepath"
@@ -275,3 +276,23 @@ func (rfs *reverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.
func (rfs *reverseFS) StatFs(name string) *fuse.StatfsOut {
return rfs.loopbackfs.StatFs(name)
}
+
+// Readlink - FUSE call
+func (rfs *reverseFS) Readlink(cipherPath string, context *fuse.Context) (string, fuse.Status) {
+ absPath, err := rfs.abs(rfs.decryptPath(cipherPath))
+ if err != nil {
+ return "", fuse.ToStatus(err)
+ }
+ plainTarget, err := os.Readlink(absPath)
+ if err != nil {
+ return "", fuse.ToStatus(err)
+ }
+ if rfs.args.PlaintextNames {
+ return plainTarget, fuse.OK
+ }
+ nonce := derivePathIV(cipherPath)
+ // Symlinks are encrypted like file contents and base64-encoded
+ cBinTarget := rfs.contentEnc.EncryptBlock([]byte(plainTarget), 0, nil, contentenc.ExternalNonce, nonce)
+ cTarget := base64.URLEncoding.EncodeToString(cBinTarget)
+ return cTarget, fuse.OK
+}
diff --git a/internal/fusefrontend_reverse/rpath.go b/internal/fusefrontend_reverse/rpath.go
index c603cad..6d418e0 100644
--- a/internal/fusefrontend_reverse/rpath.go
+++ b/internal/fusefrontend_reverse/rpath.go
@@ -47,6 +47,12 @@ func (rfs *reverseFS) decryptPath(relPath string) (string, error) {
if _, ok := err.(base64.CorruptInputError); ok {
return "", syscall.ENOENT
}
+ // Stat attempts on the link target of encrypted symlinks.
+ // These are always valid base64 but the length is not a
+ // multiple of 16.
+ if err == syscall.EINVAL {
+ return "", syscall.ENOENT
+ }
return "", err
}
} else if nameType == nametransform.LongNameContent {