//go:build linux && cgo package shared import ( "fmt" "os" // Used by cgo _ "github.com/lxc/lxd/lxd/include" "golang.org/x/sys/unix" ) /* #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../lxd/include/process_utils.h" #include "../lxd/include/syscall_wrappers.h" #define ABSTRACT_UNIX_SOCK_LEN sizeof(((struct sockaddr_un *)0)->sun_path) static int read_pid(int fd) { ssize_t ret; pid_t n = -1; again: ret = read(fd, &n, sizeof(n)); if (ret < 0 && errno == EINTR) goto again; if (ret < 0) return -1; return n; } */ import "C" const ABSTRACT_UNIX_SOCK_LEN int = C.ABSTRACT_UNIX_SOCK_LEN func ReadPid(r *os.File) int { return int(C.read_pid(C.int(r.Fd()))) } func unCloexec(fd int) error { var err error = nil flags, _, errno := unix.Syscall(unix.SYS_FCNTL, uintptr(fd), unix.F_GETFD, 0) if errno != 0 { err = errno return err } flags &^= unix.FD_CLOEXEC _, _, errno = unix.Syscall(unix.SYS_FCNTL, uintptr(fd), unix.F_SETFD, flags) if errno != 0 { err = errno } return err } func PidFdOpen(Pid int, Flags uint32) (*os.File, error) { pidFd, errno := C.pidfd_open(C.int(Pid), C.uint32_t(Flags)) if errno != nil { return nil, errno } errno = unCloexec(int(pidFd)) if errno != nil { return nil, errno } return os.NewFile(uintptr(pidFd), fmt.Sprintf("%d", Pid)), nil } func PidfdSendSignal(Pidfd int, Signal int, Flags uint32) error { ret, errno := C.pidfd_send_signal(C.int(Pidfd), C.int(Signal), nil, C.uint32_t(Flags)) if ret != 0 { return errno } return nil } const CLOSE_RANGE_UNSHARE uint32 = C.CLOSE_RANGE_UNSHARE const CLOSE_RANGE_CLOEXEC uint32 = C.CLOSE_RANGE_CLOEXEC func CloseRange(FirstFd uint32, LastFd uint32, Flags uint32) error { ret, errno := C.lxd_close_range(C.uint32_t(FirstFd), C.uint32_t(LastFd), C.uint32_t(Flags)) if ret != 0 { if errno != unix.ENOSYS && errno != unix.EINVAL { return errno } } return nil }