mirror of
https://github.com/restic/restic.git
synced 2025-01-20 14:28:34 +00:00
2a5bbf170d
The implementations are 90% copy&paste from the go standard library as the existing code does not offer any way to read the symlink target based on a filehandle. Fall back to a standard readlink on platforms other than Linux and Windows as those either don't even provide the necessary syscall or in case of macOS are not yet available in Go.
47 lines
947 B
Go
47 lines
947 B
Go
package fs
|
|
|
|
import (
|
|
"os"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// based on readlink from go/src/os/file_unix.go Go 1.23.2
|
|
// modified to use Readlinkat syscall instead of readlink
|
|
|
|
// Many functions in package syscall return a count of -1 instead of 0.
|
|
// Using fixCount(call()) instead of call() corrects the count.
|
|
func fixCount(n int, err error) (int, error) {
|
|
if n < 0 {
|
|
n = 0
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
func Freadlink(fd uintptr, name string) (string, error) {
|
|
for namelen := 128; ; namelen *= 2 {
|
|
b := make([]byte, namelen)
|
|
var (
|
|
n int
|
|
e error
|
|
)
|
|
for {
|
|
n, e = fixCount(freadlink(int(fd), b))
|
|
if e != syscall.EINTR {
|
|
break
|
|
}
|
|
}
|
|
if e != nil {
|
|
return "", &os.PathError{Op: "readlink", Path: name, Err: e}
|
|
}
|
|
if n < namelen {
|
|
return string(b[0:n]), nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func freadlink(fd int, buf []byte) (n int, err error) {
|
|
// pass empty path to process the link itself
|
|
return unix.Readlinkat(fd, "", buf)
|
|
}
|