diff options
| -rw-r--r-- | internal/fusefrontend_reverse/rpath.go | 17 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/rpath_cache.go | 41 | 
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 | 
