OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [syscall/] [sockcmsg_unix.go] - Rev 747

Compare with Previous | Blame | View Log

// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin freebsd linux netbsd openbsd

// Socket control messages

package syscall

import (
        "unsafe"
)

// Round the length of a raw sockaddr up to align it propery.
func cmsgAlignOf(salen int) int {
        salign := int(sizeofPtr)
        // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
        // aligned access to BSD subsystem.
        if darwinAMD64 {
                salign = 4
        }
        if salen == 0 {
                return salign
        }
        return (salen + salign - 1) & ^(salign - 1)
}

// 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)) + uintptr(SizeofCmsghdr))
}

type SocketControlMessage struct {
        Header Cmsghdr
        Data   []byte
}

func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, error) {
        var (
                h     *Cmsghdr
                dbuf  []byte
                e     error
                cmsgs []SocketControlMessage
        )

        for len(buf) >= CmsgLen(0) {
                h, dbuf, e = socketControlMessageHeaderAndData(buf)
                if e != nil {
                        break
                }
                m := SocketControlMessage{}
                m.Header = *h
                m.Data = dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)]
                cmsgs = append(cmsgs, m)
                buf = buf[cmsgAlignOf(int(h.Len)):]
        }

        return cmsgs, e
}

func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, error) {
        h := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
        if int(h.Len) < SizeofCmsghdr || int(h.Len) > len(buf) {
                return nil, nil, EINVAL
        }
        return h, buf[cmsgAlignOf(SizeofCmsghdr):], nil
}

// 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, error) {
        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, nil
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.