| | |
| | |
| | |
| |
|
| | package main |
| |
|
| | import ( |
| | "bytes" |
| | "fmt" |
| | "internal/testenv" |
| | "io" |
| | "os" |
| | "syscall" |
| | ) |
| |
|
| | func gettid() int { |
| | return syscall.Gettid() |
| | } |
| |
|
| | func tidExists(tid int) (exists, supported bool, err error) { |
| | |
| | |
| | statusFile := fmt.Sprintf("/proc/self/task/%d/status", tid) |
| | fd, err := syscall.Open(statusFile, syscall.O_RDONLY, 0) |
| | if errno, ok := err.(syscall.Errno); ok { |
| | if errno == syscall.ENOENT || errno == syscall.ESRCH { |
| | return false, true, nil |
| | } |
| | } |
| | if err != nil { |
| | return false, false, err |
| | } |
| | status, err := io.ReadAll(os.NewFile(uintptr(fd), statusFile)) |
| | if err != nil { |
| | return false, false, err |
| | } |
| | lines := bytes.Split(status, []byte{'\n'}) |
| | |
| | stateLineIdx := -1 |
| | for i, line := range lines { |
| | if bytes.HasPrefix(line, []byte("State:")) { |
| | stateLineIdx = i |
| | break |
| | } |
| | } |
| | if stateLineIdx < 0 { |
| | |
| | return false, false, fmt.Errorf("unexpected status file format: %s:\n%s", statusFile, status) |
| | } |
| | stateLine := bytes.SplitN(lines[stateLineIdx], []byte{':'}, 2) |
| | if len(stateLine) != 2 { |
| | |
| | return false, false, fmt.Errorf("unexpected status file format: %s:\n%s", statusFile, status) |
| | } |
| | |
| | return !bytes.Contains(stateLine[1], []byte{'Z'}), true, nil |
| | } |
| |
|
| | func getcwd() (string, error) { |
| | if !syscall.ImplementsGetwd { |
| | return "", nil |
| | } |
| | |
| | |
| | |
| | |
| | var buf [4096]byte |
| | n, err := syscall.Getcwd(buf[:]) |
| | if err != nil { |
| | return "", err |
| | } |
| | |
| | return string(buf[:n-1]), nil |
| | } |
| |
|
| | func unshareFs() error { |
| | err := syscall.Unshare(syscall.CLONE_FS) |
| | if testenv.SyscallIsNotSupported(err) { |
| | return errNotPermitted |
| | } |
| | return err |
| | } |
| |
|
| | func chdir(path string) error { |
| | return syscall.Chdir(path) |
| | } |
| |
|