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)
|
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.NodeMkdirer)((*Node)(nil))
|
||||||
var _ = (fs.NodeRmdirer)((*Node)(nil))
|
var _ = (fs.NodeRmdirer)((*Node)(nil))
|
||||||
var _ = (fs.NodeUnlinker)((*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
|
// are exclusive
|
||||||
return false
|
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…
x
Reference in New Issue
Block a user