diff options
| author | Jakob Unterwurzacher | 2020-07-26 19:49:26 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2020-07-26 19:49:26 +0200 | 
| commit | 4572cd2103ea702d27d8d608edf6abcddc2bda29 (patch) | |
| tree | 90a802af6bbe5ecb9c6859b3ab82dc3df0212672 /internal | |
| parent | 777b95f82ffea8a25b95089343b07b29378110da (diff) | |
v2api: fix missing size translation in Lookup
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/fusefrontend/node.go | 32 | ||||
| -rw-r--r-- | internal/fusefrontend/node_helpers.go | 34 | 
2 files changed, 44 insertions, 22 deletions
| diff --git a/internal/fusefrontend/node.go b/internal/fusefrontend/node.go index 9d49add..7505f92 100644 --- a/internal/fusefrontend/node.go +++ b/internal/fusefrontend/node.go @@ -69,7 +69,13 @@ func (n *Node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (ch  	if err != nil {  		return nil, fs.ToErrno(err)  	} + +	// Create new inode and fill `out`  	ch = n.newChild(ctx, st, out) + +	// Translate ciphertext size in `out.Attr.Size` to plaintext size +	n.translateSize(dirfd, cName, &out.Attr) +  	return ch, 0  } @@ -98,13 +104,9 @@ func (n *Node) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut)  	rn.inoMap.TranslateStat(st)  	out.Attr.FromStat(st) -	// Fix size -	if out.IsRegular() { -		out.Size = rn.contentEnc.CipherSizeToPlainSize(out.Size) -	} else if out.IsSymlink() { -		target, _ := n.Readlink(ctx) -		out.Size = uint64(len(target)) -	} +	// Translate ciphertext size in `out.Attr.Size` to plaintext size +	n.translateSize(dirfd, cName, &out.Attr) +  	if rn.args.ForceOwner != nil {  		out.Owner = *rn.args.ForceOwner  	} @@ -221,21 +223,7 @@ func (n *Node) Readlink(ctx context.Context) (out []byte, errno syscall.Errno) {  	}  	defer syscall.Close(dirfd) -	cTarget, err := syscallcompat.Readlinkat(dirfd, cName) -	if err != nil { -		return nil, fs.ToErrno(err) -	} -	rn := n.rootNode() -	if rn.args.PlaintextNames { -		return []byte(cTarget), 0 -	} -	// Symlinks are encrypted like file contents (GCM) and base64-encoded -	target, err := rn.decryptSymlinkTarget(cTarget) -	if err != nil { -		tlog.Warn.Printf("Readlink %q: decrypting target failed: %v", cName, err) -		return nil, syscall.EIO -	} -	return []byte(target), 0 +	return n.readlink(dirfd, cName)  }  // Open - FUSE call. Open already-existing file. diff --git a/internal/fusefrontend/node_helpers.go b/internal/fusefrontend/node_helpers.go index a7a32af..a31a41d 100644 --- a/internal/fusefrontend/node_helpers.go +++ b/internal/fusefrontend/node_helpers.go @@ -2,10 +2,14 @@ package fusefrontend  import (  	"context" +	"syscall"  	"github.com/hanwen/go-fuse/v2/fs"  	"github.com/hanwen/go-fuse/v2/fuse" + +	"github.com/rfjakob/gocryptfs/internal/syscallcompat" +	"github.com/rfjakob/gocryptfs/internal/tlog"  )  // toFuseCtx tries to extract a fuse.Context from a generic context.Context. @@ -29,3 +33,33 @@ func toNode(op fs.InodeEmbedder) *Node {  	}  	return op.(*Node)  } + +// readlink reads and decrypts a symlink. Used by Readlink, Getattr, Lookup. +func (n *Node) readlink(dirfd int, cName string) (out []byte, errno syscall.Errno) { +	cTarget, err := syscallcompat.Readlinkat(dirfd, cName) +	if err != nil { +		return nil, fs.ToErrno(err) +	} +	rn := n.rootNode() +	if rn.args.PlaintextNames { +		return []byte(cTarget), 0 +	} +	// Symlinks are encrypted like file contents (GCM) and base64-encoded +	target, err := rn.decryptSymlinkTarget(cTarget) +	if err != nil { +		tlog.Warn.Printf("Readlink %q: decrypting target failed: %v", cName, err) +		return nil, syscall.EIO +	} +	return []byte(target), 0 +} + +// translateSize translates the ciphertext size in `out` into plaintext size. +func (n *Node) translateSize(dirfd int, cName string, out *fuse.Attr) { +	if out.IsRegular() { +		rn := n.rootNode() +		out.Size = rn.contentEnc.CipherSizeToPlainSize(out.Size) +	} else if out.IsSymlink() { +		target, _ := n.readlink(dirfd, cName) +		out.Size = uint64(len(target)) +	} +} | 
