summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/fusefrontend_reverse/rpath.go17
-rw-r--r--internal/fusefrontend_reverse/rpath_cache.go41
2 files changed, 56 insertions, 2 deletions
diff --git a/internal/fusefrontend_reverse/rpath.go b/internal/fusefrontend_reverse/rpath.go
index af49776..9f52b28 100644
--- a/internal/fusefrontend_reverse/rpath.go
+++ b/internal/fusefrontend_reverse/rpath.go
@@ -82,18 +82,31 @@ func (rfs *ReverseFS) decryptPath(relPath string) (string, error) {
if rfs.args.PlaintextNames || relPath == "" {
return relPath, nil
}
+ // Check if the parent dir is in the cache
+ cDir := saneDir(relPath)
+ dirIV, pDir := rPathCache.lookup(cDir)
+ if dirIV != nil {
+ cName := filepath.Base(relPath)
+ pName, err := rfs.rDecryptName(cName, dirIV, pDir)
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(pDir, pName), nil
+ }
parts := strings.Split(relPath, "/")
var transformedParts []string
for i := range parts {
// Start at the top and recurse
currentCipherDir := filepath.Join(parts[:i]...)
currentPlainDir := filepath.Join(transformedParts[:i]...)
- dirIV := derivePathIV(currentCipherDir, ivPurposeDirIV)
+ dirIV = derivePathIV(currentCipherDir, ivPurposeDirIV)
transformedPart, err := rfs.rDecryptName(parts[i], dirIV, currentPlainDir)
if err != nil {
return "", err
}
transformedParts = append(transformedParts, transformedPart)
}
- return filepath.Join(transformedParts...), nil
+ pRelPath := filepath.Join(transformedParts...)
+ rPathCache.store(cDir, dirIV, saneDir(pRelPath))
+ return pRelPath, nil
}
diff --git a/internal/fusefrontend_reverse/rpath_cache.go b/internal/fusefrontend_reverse/rpath_cache.go
new file mode 100644
index 0000000..81e945b
--- /dev/null
+++ b/internal/fusefrontend_reverse/rpath_cache.go
@@ -0,0 +1,41 @@
+package fusefrontend_reverse
+
+import (
+ "sync"
+)
+
+// rPathCacheContainer is a simple one entry path cache. Because the dirIV
+// is generated deterministically from the directory path, there is no need
+// to ever invalidate entries.
+type rPathCacheContainer struct {
+ sync.Mutex
+ // Relative ciphertext path to the directory
+ cPath string
+ // Relative plaintext path
+ pPath string
+ // Directory IV of the directory
+ dirIV []byte
+}
+
+func (c *rPathCacheContainer) lookup(cPath string) ([]byte, string) {
+ c.Lock()
+ defer c.Unlock()
+ if cPath == c.cPath {
+ //fmt.Printf("HIT %q\n", cPath)
+ return c.dirIV, c.pPath
+ }
+ //fmt.Printf("MISS %q\n", cPath)
+ return nil, ""
+}
+
+// store - write entry for "cPath" into the cache
+func (c *rPathCacheContainer) store(cPath string, dirIV []byte, pPath string) {
+ //fmt.Printf("STORE %q\n", cPath)
+ c.Lock()
+ defer c.Unlock()
+ c.cPath = cPath
+ c.dirIV = dirIV
+ c.pPath = pPath
+}
+
+var rPathCache rPathCacheContainer