v2api: implement Readlink
This commit is contained in:
parent
1618fbbac5
commit
23180794fe
@ -178,3 +178,34 @@ func (n *Node) Unlink(ctx context.Context, name string) syscall.Errno {
|
||||
}
|
||||
return fs.ToErrno(err)
|
||||
}
|
||||
|
||||
// Readlink - FUSE call.
|
||||
//
|
||||
// Symlink-safe through openBackingDir() + Readlinkat().
|
||||
func (n *Node) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
|
||||
rn := n.rootNode()
|
||||
p := n.path()
|
||||
if rn.isFiltered(p) {
|
||||
return nil, syscall.EPERM
|
||||
}
|
||||
dirfd, cName, err := rn.openBackingDir(p)
|
||||
if err != nil {
|
||||
return nil, fs.ToErrno(err)
|
||||
}
|
||||
defer syscall.Close(dirfd)
|
||||
|
||||
cTarget, err := syscallcompat.Readlinkat(dirfd, cName)
|
||||
if err != nil {
|
||||
return nil, fs.ToErrno(err)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -12,3 +12,4 @@ var _ = (fs.NodeCreater)((*Node)(nil))
|
||||
var _ = (fs.NodeMkdirer)((*Node)(nil))
|
||||
var _ = (fs.NodeRmdirer)((*Node)(nil))
|
||||
var _ = (fs.NodeUnlinker)((*Node)(nil))
|
||||
var _ = (fs.NodeReadlinker)((*Node)(nil))
|
||||
|
@ -117,3 +117,23 @@ func (rn *RootNode) isFiltered(path string) bool {
|
||||
// are exclusive
|
||||
return false
|
||||
}
|
||||
|
||||
// decryptSymlinkTarget: "cData64" is base64-decoded and decrypted
|
||||
// like file contents (GCM).
|
||||
// The empty string decrypts to the empty string.
|
||||
//
|
||||
// This function does not do any I/O and is hence symlink-safe.
|
||||
func (rn *RootNode) decryptSymlinkTarget(cData64 string) (string, error) {
|
||||
if cData64 == "" {
|
||||
return "", nil
|
||||
}
|
||||
cData, err := rn.nameTransform.B64DecodeString(cData64)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
data, err := rn.contentEnc.DecryptBlock([]byte(cData), 0, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user