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 }