diff options
| author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:44 +0200 |
|---|---|---|
| committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:44 +0200 |
| commit | 9464a0c36318f8a801c07d6874bd0cea40f12504 (patch) | |
| tree | f0178491c19d4f1ebc7b92eede86690998466480 /src/pkg/syscall/sockcmsg_unix.go | |
| parent | ba9fda6068cfadd42db0b152fdca7e8b67aaf77d (diff) | |
| parent | 5ff4c17907d5b19510a62e08fd8d3b11e62b431d (diff) | |
| download | golang-9464a0c36318f8a801c07d6874bd0cea40f12504.tar.gz | |
Merge commit 'upstream/60' into debian-sid
Diffstat (limited to 'src/pkg/syscall/sockcmsg_unix.go')
| -rw-r--r-- | src/pkg/syscall/sockcmsg_unix.go | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/src/pkg/syscall/sockcmsg_unix.go b/src/pkg/syscall/sockcmsg_unix.go index f0c05eaf3..b437560e7 100644 --- a/src/pkg/syscall/sockcmsg_unix.go +++ b/src/pkg/syscall/sockcmsg_unix.go @@ -24,10 +24,22 @@ func cmsgAlignOf(salen int) int { return (salen + salign - 1) & ^(salign - 1) } -func cmsgLen(datalen int) int { +// CmsgLen returns the value to store in the Len field of the Cmsghdr +// structure, taking into account any necessary alignment. +func CmsgLen(datalen int) int { return cmsgAlignOf(SizeofCmsghdr) + datalen } +// CmsgSpace returns the number of bytes an ancillary element with +// payload of the passed data length occupies. +func CmsgSpace(datalen int) int { + return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen) +} + +func cmsgData(cmsg *Cmsghdr) unsafe.Pointer { + return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + SizeofCmsghdr) +} + type SocketControlMessage struct { Header Cmsghdr Data []byte @@ -41,7 +53,7 @@ func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) { cmsgs []SocketControlMessage ) - for len(buf) >= cmsgLen(0) { + for len(buf) >= CmsgLen(0) { h, dbuf, e = socketControlMessageHeaderAndData(buf) if e != 0 { break @@ -63,3 +75,39 @@ func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, int) { } return h, buf[cmsgAlignOf(SizeofCmsghdr):], 0 } + +// UnixRights encodes a set of open file descriptors into a socket +// control message for sending to another process. +func UnixRights(fds ...int) []byte { + datalen := len(fds) * 4 + buf := make([]byte, CmsgSpace(datalen)) + cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0])) + cmsg.Level = SOL_SOCKET + cmsg.Type = SCM_RIGHTS + cmsg.SetLen(CmsgLen(datalen)) + + data := uintptr(cmsgData(cmsg)) + for _, fd := range fds { + *(*int32)(unsafe.Pointer(data)) = int32(fd) + data += 4 + } + + return buf +} + +// ParseUnixRights decodes a socket control message that contains an +// integer array of open file descriptors from another process. +func ParseUnixRights(msg *SocketControlMessage) ([]int, int) { + if msg.Header.Level != SOL_SOCKET { + return nil, EINVAL + } + if msg.Header.Type != SCM_RIGHTS { + return nil, EINVAL + } + fds := make([]int, len(msg.Data)>>2) + for i, j := 0, 0; i < len(msg.Data); i += 4 { + fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i]))) + j++ + } + return fds, 0 +} |
