summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorJakob Unterwurzacher2018-10-14 21:55:37 +0200
committerJakob Unterwurzacher2019-01-01 16:24:09 +0100
commit0c1ceed1fa55e2a9174050c324f679821a5fca8d (patch)
tree284819706e7bf81ad0d140c61e1788d3fcb2303c /internal
parent932efbd4593fe6be6c86f0dafeaea32910b7c246 (diff)
fusefrontend: make GetAttr() symlink-safe
Use openBackingDir() and Fstatat(). High performance impact, though part of it should be mitigated by adding DirIV caching to the new code paths. $ ./benchmark.bash Testing gocryptfs at /tmp/benchmark.bash.Eou: gocryptfs v1.6-37-ge3914b3-dirty; go-fuse v20170619-66-g6df8ddc; 2018-10-14 go1.11 WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.2289 s, 213 MB/s READ: 262144000 bytes (262 MB, 250 MiB) copied, 1.02616 s, 255 MB/s UNTAR: 24.490 MD5: 13.120 LS: 3.368 RM: 9.232
Diffstat (limited to 'internal')
-rw-r--r--internal/fusefrontend/fs.go26
1 files changed, 16 insertions, 10 deletions
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index 8e443b7..a301231 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -73,30 +73,36 @@ func NewFS(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform)
}
// GetAttr implements pathfs.Filesystem.
-func (fs *FS) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
- tlog.Debug.Printf("FS.GetAttr('%s')", name)
- if fs.isFiltered(name) {
+//
+// GetAttr is symlink-safe through use of openBackingDir() and Fstatat().
+func (fs *FS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
+ tlog.Debug.Printf("FS.GetAttr(%q)", relPath)
+ if fs.isFiltered(relPath) {
return nil, fuse.EPERM
}
- cName, err := fs.encryptPath(name)
+ dirfd, cName, err := fs.openBackingDir(relPath)
if err != nil {
return nil, fuse.ToStatus(err)
}
- a, status := fs.FileSystem.GetAttr(cName, context)
- if a == nil {
- tlog.Debug.Printf("FS.GetAttr failed: %s", status.String())
- return a, status
+ var st unix.Stat_t
+ err = syscallcompat.Fstatat(dirfd, cName, &st, unix.AT_SYMLINK_NOFOLLOW)
+ syscall.Close(dirfd)
+ if err != nil {
+ return nil, fuse.ToStatus(err)
}
+ a := &fuse.Attr{}
+ st2 := syscallcompat.Unix2syscall(st)
+ a.FromStat(&st2)
if a.IsRegular() {
a.Size = fs.contentEnc.CipherSizeToPlainSize(a.Size)
} else if a.IsSymlink() {
- target, _ := fs.Readlink(name, context)
+ target, _ := fs.Readlink(relPath, context)
a.Size = uint64(len(target))
}
if fs.args.ForceOwner != nil {
a.Owner = *fs.args.ForceOwner
}
- return a, status
+ return a, fuse.OK
}
// mangleOpenFlags is used by Create() and Open() to convert the open flags the user