package cmsg //#include "cmsg.c" import "C" import ( "net" "os" "syscall" "unsafe" ) func BuildScmRights(file *os.File) []byte { fd := file.Fd() length := unsafe.Sizeof(fd) buf := make([]byte, CMSG_SPACE(length)) cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&buf[0])) cmsg.Level = syscall.SOL_SOCKET cmsg.Type = syscall.SCM_RIGHTS cmsg.SetLen(CMSG_LEN(length)) data := CMSG_DATA(cmsg) *((*int)(unsafe.Pointer(data))) = fd return buf } func WriteScmRights(c *net.UnixConn, file *os.File) os.Error { buf := BuildScmRights(file) _, _, err := c.WriteMsgUnix(nil, buf, nil) return err } func ReadScmRights(oob []byte) (*os.File, os.Error) { cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[0])) if cmsg.Level != syscall.SOL_SOCKET { return nil, os.NewError("Level != SOL_SOCKET") } if cmsg.Type != syscall.SCM_RIGHTS { return nil, os.NewError("Type != SCM_RIGHTS") } fd := *(*int)(unsafe.Pointer(CMSG_DATA(cmsg))) file := os.NewFile(fd, "") return file, nil } func NewShmRightsBuffer() []byte { var fd int return make([]byte, CMSG_LEN(unsafe.Sizeof(fd))) } //#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) func CMSG_SPACE(length int) int { //#define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr))) return int(C.CMSG_SPACE_(C.size_t(length))) } func CMSG_LEN(length int) int { //#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) return int(C.CMSG_LEN_(C.size_t(length))) } func CMSG_DATA(cmsg *syscall.Cmsghdr) *byte { //# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) cCmsg := (*C.cmsghdr_t)(unsafe.Pointer(cmsg)) return (*byte)(unsafe.Pointer(C.CMSG_DATA_(cCmsg))) }