summaryrefslogtreecommitdiff
path: root/internal/fusefrontend/openbackingdir.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/fusefrontend/openbackingdir.go')
-rw-r--r--internal/fusefrontend/openbackingdir.go15
1 files changed, 12 insertions, 3 deletions
diff --git a/internal/fusefrontend/openbackingdir.go b/internal/fusefrontend/openbackingdir.go
index 849a486..4da7fd6 100644
--- a/internal/fusefrontend/openbackingdir.go
+++ b/internal/fusefrontend/openbackingdir.go
@@ -10,7 +10,8 @@ import (
)
// openBackingDir opens the parent ciphertext directory of plaintext path
-// "relPath" and returns the dirfd and the encrypted basename.
+// "relPath". It returns the dirfd (opened with O_PATH) and the encrypted
+// basename.
//
// The caller should then use Openat(dirfd, cName, ...) and friends.
// For convenience, if relPath is "", cName is going to be ".".
@@ -18,10 +19,10 @@ import (
// openBackingDir is secure against symlink races by using Openat and
// ReadDirIVAt.
func (fs *FS) openBackingDir(relPath string) (dirfd int, cName string, err error) {
+ dirRelPath := nametransform.Dir(relPath)
// With PlaintextNames, we don't need to read DirIVs. Easy.
if fs.args.PlaintextNames {
- dir := nametransform.Dir(relPath)
- dirfd, err = syscallcompat.OpenDirNofollow(fs.args.Cipherdir, dir)
+ dirfd, err = syscallcompat.OpenDirNofollow(fs.args.Cipherdir, dirRelPath)
if err != nil {
return -1, "", err
}
@@ -29,6 +30,13 @@ func (fs *FS) openBackingDir(relPath string) (dirfd int, cName string, err error
cName = filepath.Base(relPath)
return dirfd, cName, nil
}
+ // Cache lookup
+ dirfd, iv := fs.dirCache.Lookup(dirRelPath)
+ if dirfd > 0 {
+ name := filepath.Base(relPath)
+ cName = fs.nameTransform.EncryptAndHashName(name, iv)
+ return dirfd, cName, nil
+ }
// Open cipherdir (following symlinks)
dirfd, err = syscall.Open(fs.args.Cipherdir, syscall.O_RDONLY|syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
if err != nil {
@@ -49,6 +57,7 @@ func (fs *FS) openBackingDir(relPath string) (dirfd int, cName string, err error
cName = fs.nameTransform.EncryptAndHashName(name, iv)
// Last part? We are done.
if i == len(parts)-1 {
+ fs.dirCache.Store(dirRelPath, dirfd, iv)
break
}
// Not the last part? Descend into next directory.