utils_unix.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // +build !windows
  2. package utils
  3. import (
  4. "fmt"
  5. "os"
  6. "strconv"
  7. "golang.org/x/sys/unix"
  8. )
  9. // EnsureProcHandle returns whether or not the given file handle is on procfs.
  10. func EnsureProcHandle(fh *os.File) error {
  11. var buf unix.Statfs_t
  12. if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
  13. return fmt.Errorf("ensure %s is on procfs: %v", fh.Name(), err)
  14. }
  15. if buf.Type != unix.PROC_SUPER_MAGIC {
  16. return fmt.Errorf("%s is not on procfs", fh.Name())
  17. }
  18. return nil
  19. }
  20. // CloseExecFrom applies O_CLOEXEC to all file descriptors currently open for
  21. // the process (except for those below the given fd value).
  22. func CloseExecFrom(minFd int) error {
  23. fdDir, err := os.Open("/proc/self/fd")
  24. if err != nil {
  25. return err
  26. }
  27. defer fdDir.Close()
  28. if err := EnsureProcHandle(fdDir); err != nil {
  29. return err
  30. }
  31. fdList, err := fdDir.Readdirnames(-1)
  32. if err != nil {
  33. return err
  34. }
  35. for _, fdStr := range fdList {
  36. fd, err := strconv.Atoi(fdStr)
  37. // Ignore non-numeric file names.
  38. if err != nil {
  39. continue
  40. }
  41. // Ignore descriptors lower than our specified minimum.
  42. if fd < minFd {
  43. continue
  44. }
  45. // Intentionally ignore errors from unix.CloseOnExec -- the cases where
  46. // this might fail are basically file descriptors that have already
  47. // been closed (including and especially the one that was created when
  48. // ioutil.ReadDir did the "opendir" syscall).
  49. unix.CloseOnExec(fd)
  50. }
  51. return nil
  52. }
  53. // NewSockPair returns a new unix socket pair
  54. func NewSockPair(name string) (parent *os.File, child *os.File, err error) {
  55. fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
  56. if err != nil {
  57. return nil, nil, err
  58. }
  59. return os.NewFile(uintptr(fds[1]), name+"-p"), os.NewFile(uintptr(fds[0]), name+"-c"), nil
  60. }