1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
package linux
import (
"os"
"golang.org/x/sys/unix"
)
// Readlinkat wraps [unix.Readlinkat].
func Readlinkat(dir *os.File, path string) (string, error) {
size := 4096
for {
linkBuf := make([]byte, size)
n, err := unix.Readlinkat(int(dir.Fd()), path, linkBuf)
if err != nil {
return "", &os.PathError{Op: "readlinkat", Path: dir.Name() + "/" + path, Err: err}
}
if n != size {
return string(linkBuf[:n]), nil
}
// Possible truncation, resize the buffer.
size *= 2
}
}
// GetPtyPeer is a wrapper for ioctl(TIOCGPTPEER).
func GetPtyPeer(ptyFd uintptr, unsafePeerPath string, flags int) (*os.File, error) {
// Make sure O_NOCTTY is always set -- otherwise runc might accidentally
// gain it as a controlling terminal. O_CLOEXEC also needs to be set to
// make sure we don't leak the handle either.
flags |= unix.O_NOCTTY | unix.O_CLOEXEC
// There is no nice wrapper for this kind of ioctl in unix.
peerFd, _, errno := unix.Syscall(
unix.SYS_IOCTL,
ptyFd,
uintptr(unix.TIOCGPTPEER),
uintptr(flags),
)
if errno != 0 {
return nil, os.NewSyscallError("ioctl TIOCGPTPEER", errno)
}
return os.NewFile(peerFd, unsafePeerPath), nil
}
|