diff options
Diffstat (limited to 'internal/fusefrontend_reverse/reverse_longnames.go')
-rw-r--r-- | internal/fusefrontend_reverse/reverse_longnames.go | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/internal/fusefrontend_reverse/reverse_longnames.go b/internal/fusefrontend_reverse/reverse_longnames.go index 46e1791..487802f 100644 --- a/internal/fusefrontend_reverse/reverse_longnames.go +++ b/internal/fusefrontend_reverse/reverse_longnames.go @@ -3,7 +3,9 @@ package fusefrontend_reverse import ( "os" "path/filepath" + "sync" "syscall" + "time" "github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse/nodefs" @@ -15,7 +17,37 @@ const ( shortNameMax = 176 ) -func (rfs *reverseFS) findLongnameParent(dir string, dirIV []byte, longname string) (string, error) { +type dirIVNameStruct struct { + dirIV [nametransform.DirIVLen]byte + name string +} + +var longnameParentCache map[string]string +var longnameCacheLock sync.Mutex + +// Very simple cache cleaner: Nuke it every hour +func longnameCacheCleaner() { + for { + time.Sleep(time.Hour) + longnameCacheLock.Lock() + longnameParentCache = map[string]string{} + longnameCacheLock.Unlock() + } +} + +func init() { + longnameParentCache = map[string]string{} + go longnameCacheCleaner() +} + +// findLongnameParent converts "gocryptfs.longname.XYZ" to the plaintext name +func (rfs *reverseFS) findLongnameParent(dir string, dirIV []byte, longname string) (plaintextName string, err error) { + longnameCacheLock.Lock() + hit := longnameParentCache[longname] + longnameCacheLock.Unlock() + if hit != "" { + return hit, nil + } absDir := filepath.Join(rfs.args.Cipherdir, dir) dirfd, err := os.Open(absDir) if err != nil { @@ -25,20 +57,27 @@ func (rfs *reverseFS) findLongnameParent(dir string, dirIV []byte, longname stri if err != nil { return "", err } - for _, e := range dirEntries { - if len(e) <= shortNameMax { + longnameCacheLock.Lock() + defer longnameCacheLock.Unlock() + for _, plaintextName = range dirEntries { + if len(plaintextName) <= shortNameMax { continue } - cName := rfs.nameTransform.EncryptName(e, dirIV) + cName := rfs.nameTransform.EncryptName(plaintextName, dirIV) if len(cName) <= syscall.NAME_MAX { panic("logic error or wrong shortNameMax constant?") } hName := nametransform.HashLongName(cName) + longnameParentCache[hName] = plaintextName if longname == hName { - return e, nil + hit = plaintextName } } - return "", syscall.ENOENT + if hit == "" { + return "", syscall.ENOENT + } else { + return hit, nil + } } func (rfs *reverseFS) newNameFile(relPath string) (nodefs.File, fuse.Status) { |