RecvFile waits for a file descriptor to be sent over the given AF_UNIX socket. The file name of the remote file descriptor will be recreated locally (it is sent as non-auxiliary data in the same payload).
(socket *os.File)
| 42 | // socket. The file name of the remote file descriptor will be recreated |
| 43 | // locally (it is sent as non-auxiliary data in the same payload). |
| 44 | func RecvFile(socket *os.File) (_ *os.File, Err error) { |
| 45 | name := make([]byte, MaxNameLen) |
| 46 | oob := make([]byte, oobSpace) |
| 47 | |
| 48 | sockfd := socket.Fd() |
| 49 | var ( |
| 50 | n, oobn int |
| 51 | err error |
| 52 | ) |
| 53 | |
| 54 | for { |
| 55 | n, oobn, _, _, err = unix.Recvmsg(int(sockfd), name, oob, unix.MSG_CMSG_CLOEXEC) |
| 56 | if err != unix.EINTR { |
| 57 | break |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | if err != nil { |
| 62 | return nil, os.NewSyscallError("recvmsg", err) |
| 63 | } |
| 64 | if n >= MaxNameLen || oobn != oobSpace { |
| 65 | return nil, fmt.Errorf("recvfile: incorrect number of bytes read (n=%d oobn=%d)", n, oobn) |
| 66 | } |
| 67 | // Truncate. |
| 68 | name = name[:n] |
| 69 | oob = oob[:oobn] |
| 70 | |
| 71 | scms, err := unix.ParseSocketControlMessage(oob) |
| 72 | if err != nil { |
| 73 | return nil, err |
| 74 | } |
| 75 | |
| 76 | // We cannot control how many SCM_RIGHTS we receive, and upon receiving |
| 77 | // them all of the descriptors are installed in our fd table, so we need to |
| 78 | // parse all of the SCM_RIGHTS we received in order to close all of the |
| 79 | // descriptors on error. |
| 80 | var fds []int |
| 81 | defer func() { |
| 82 | for i, fd := range fds { |
| 83 | if i == 0 && Err == nil { |
| 84 | // Only close the first one on error. |
| 85 | continue |
| 86 | } |
| 87 | // Always close extra ones. |
| 88 | _ = unix.Close(fd) |
| 89 | } |
| 90 | }() |
| 91 | var lastErr error |
| 92 | for _, scm := range scms { |
| 93 | if scm.Header.Type == unix.SCM_RIGHTS { |
| 94 | scmFds, err := unix.ParseUnixRights(&scm) |
| 95 | if err != nil { |
| 96 | lastErr = err |
| 97 | } else { |
| 98 | fds = append(fds, scmFds...) |
| 99 | } |
| 100 | } |
| 101 | } |
searching dependent graphs…