1
0
Fork 0
mirror of https://github.com/restic/restic.git synced 2025-01-20 14:28:34 +00:00
restic/internal/fs/freadlink_linux.go
Michael Eischer 2a5bbf170d fs: implement and use filehandle based readlink
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.
2024-11-30 19:17:25 +01:00

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)
}