vendor/golang.org/x/sys/unix/syscall_solaris.go
changeset 260 445e01aede7e
parent 256 6d9efbef00a9
child 262 8d3354485fc3
equal deleted inserted replaced
259:db4911b0c721 260:445e01aede7e
    11 // syscall_solaris.go or syscall_unix.go.
    11 // syscall_solaris.go or syscall_unix.go.
    12 
    12 
    13 package unix
    13 package unix
    14 
    14 
    15 import (
    15 import (
       
    16 	"fmt"
       
    17 	"os"
    16 	"runtime"
    18 	"runtime"
       
    19 	"sync"
    17 	"syscall"
    20 	"syscall"
    18 	"unsafe"
    21 	"unsafe"
    19 )
    22 )
    20 
    23 
    21 // Implemented in runtime/syscall_solaris.go.
    24 // Implemented in runtime/syscall_solaris.go.
    61 	var pp [2]_C_int
    64 	var pp [2]_C_int
    62 	n, err := pipe(&pp)
    65 	n, err := pipe(&pp)
    63 	if n != 0 {
    66 	if n != 0 {
    64 		return err
    67 		return err
    65 	}
    68 	}
    66 	p[0] = int(pp[0])
    69 	if err == nil {
    67 	p[1] = int(pp[1])
    70 		p[0] = int(pp[0])
       
    71 		p[1] = int(pp[1])
       
    72 	}
    68 	return nil
    73 	return nil
    69 }
    74 }
    70 
    75 
    71 //sysnb	pipe2(p *[2]_C_int, flags int) (err error)
    76 //sysnb	pipe2(p *[2]_C_int, flags int) (err error)
    72 
    77 
    74 	if len(p) != 2 {
    79 	if len(p) != 2 {
    75 		return EINVAL
    80 		return EINVAL
    76 	}
    81 	}
    77 	var pp [2]_C_int
    82 	var pp [2]_C_int
    78 	err := pipe2(&pp, flags)
    83 	err := pipe2(&pp, flags)
    79 	p[0] = int(pp[0])
    84 	if err == nil {
    80 	p[1] = int(pp[1])
    85 		p[0] = int(pp[0])
       
    86 		p[1] = int(pp[1])
       
    87 	}
    81 	return err
    88 	return err
    82 }
    89 }
    83 
    90 
    84 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
    91 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
    85 	if sa.Port < 0 || sa.Port > 0xFFFF {
    92 	if sa.Port < 0 || sa.Port > 0xFFFF {
    87 	}
    94 	}
    88 	sa.raw.Family = AF_INET
    95 	sa.raw.Family = AF_INET
    89 	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
    96 	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
    90 	p[0] = byte(sa.Port >> 8)
    97 	p[0] = byte(sa.Port >> 8)
    91 	p[1] = byte(sa.Port)
    98 	p[1] = byte(sa.Port)
    92 	for i := 0; i < len(sa.Addr); i++ {
    99 	sa.raw.Addr = sa.Addr
    93 		sa.raw.Addr[i] = sa.Addr[i]
       
    94 	}
       
    95 	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
   100 	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
    96 }
   101 }
    97 
   102 
    98 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
   103 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
    99 	if sa.Port < 0 || sa.Port > 0xFFFF {
   104 	if sa.Port < 0 || sa.Port > 0xFFFF {
   102 	sa.raw.Family = AF_INET6
   107 	sa.raw.Family = AF_INET6
   103 	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
   108 	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
   104 	p[0] = byte(sa.Port >> 8)
   109 	p[0] = byte(sa.Port >> 8)
   105 	p[1] = byte(sa.Port)
   110 	p[1] = byte(sa.Port)
   106 	sa.raw.Scope_id = sa.ZoneId
   111 	sa.raw.Scope_id = sa.ZoneId
   107 	for i := 0; i < len(sa.Addr); i++ {
   112 	sa.raw.Addr = sa.Addr
   108 		sa.raw.Addr[i] = sa.Addr[i]
       
   109 	}
       
   110 	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
   113 	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
   111 }
   114 }
   112 
   115 
   113 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
   116 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
   114 	name := sa.Name
   117 	name := sa.Name
   412 	case AF_INET:
   415 	case AF_INET:
   413 		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
   416 		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
   414 		sa := new(SockaddrInet4)
   417 		sa := new(SockaddrInet4)
   415 		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   418 		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   416 		sa.Port = int(p[0])<<8 + int(p[1])
   419 		sa.Port = int(p[0])<<8 + int(p[1])
   417 		for i := 0; i < len(sa.Addr); i++ {
   420 		sa.Addr = pp.Addr
   418 			sa.Addr[i] = pp.Addr[i]
       
   419 		}
       
   420 		return sa, nil
   421 		return sa, nil
   421 
   422 
   422 	case AF_INET6:
   423 	case AF_INET6:
   423 		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
   424 		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
   424 		sa := new(SockaddrInet6)
   425 		sa := new(SockaddrInet6)
   425 		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   426 		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   426 		sa.Port = int(p[0])<<8 + int(p[1])
   427 		sa.Port = int(p[0])<<8 + int(p[1])
   427 		sa.ZoneId = pp.Scope_id
   428 		sa.ZoneId = pp.Scope_id
   428 		for i := 0; i < len(sa.Addr); i++ {
   429 		sa.Addr = pp.Addr
   429 			sa.Addr[i] = pp.Addr[i]
       
   430 		}
       
   431 		return sa, nil
   430 		return sa, nil
   432 	}
   431 	}
   433 	return nil, EAFNOSUPPORT
   432 	return nil, EAFNOSUPPORT
   434 }
   433 }
   435 
   434 
   450 	return
   449 	return
   451 }
   450 }
   452 
   451 
   453 //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
   452 //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
   454 
   453 
   455 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
   454 func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
   456 	var msg Msghdr
   455 	var msg Msghdr
   457 	var rsa RawSockaddrAny
   456 	msg.Name = (*byte)(unsafe.Pointer(rsa))
   458 	msg.Name = (*byte)(unsafe.Pointer(&rsa))
       
   459 	msg.Namelen = uint32(SizeofSockaddrAny)
   457 	msg.Namelen = uint32(SizeofSockaddrAny)
   460 	var iov Iovec
   458 	var dummy byte
   461 	if len(p) > 0 {
       
   462 		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
       
   463 		iov.SetLen(len(p))
       
   464 	}
       
   465 	var dummy int8
       
   466 	if len(oob) > 0 {
   459 	if len(oob) > 0 {
   467 		// receive at least one normal byte
   460 		// receive at least one normal byte
   468 		if len(p) == 0 {
   461 		if emptyIovecs(iov) {
   469 			iov.Base = &dummy
   462 			var iova [1]Iovec
   470 			iov.SetLen(1)
   463 			iova[0].Base = &dummy
       
   464 			iova[0].SetLen(1)
       
   465 			iov = iova[:]
   471 		}
   466 		}
   472 		msg.Accrightslen = int32(len(oob))
   467 		msg.Accrightslen = int32(len(oob))
   473 	}
   468 	}
   474 	msg.Iov = &iov
   469 	if len(iov) > 0 {
   475 	msg.Iovlen = 1
   470 		msg.Iov = &iov[0]
       
   471 		msg.SetIovlen(len(iov))
       
   472 	}
   476 	if n, err = recvmsg(fd, &msg, flags); n == -1 {
   473 	if n, err = recvmsg(fd, &msg, flags); n == -1 {
   477 		return
   474 		return
   478 	}
   475 	}
   479 	oobn = int(msg.Accrightslen)
   476 	oobn = int(msg.Accrightslen)
   480 	// source address is only specified if the socket is unconnected
       
   481 	if rsa.Addr.Family != AF_UNSPEC {
       
   482 		from, err = anyToSockaddr(fd, &rsa)
       
   483 	}
       
   484 	return
   477 	return
   485 }
   478 }
   486 
   479 
   487 func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
       
   488 	_, err = SendmsgN(fd, p, oob, to, flags)
       
   489 	return
       
   490 }
       
   491 
       
   492 //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
   480 //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
   493 
   481 
   494 func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
   482 func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
   495 	var ptr unsafe.Pointer
       
   496 	var salen _Socklen
       
   497 	if to != nil {
       
   498 		ptr, salen, err = to.sockaddr()
       
   499 		if err != nil {
       
   500 			return 0, err
       
   501 		}
       
   502 	}
       
   503 	var msg Msghdr
   483 	var msg Msghdr
   504 	msg.Name = (*byte)(unsafe.Pointer(ptr))
   484 	msg.Name = (*byte)(unsafe.Pointer(ptr))
   505 	msg.Namelen = uint32(salen)
   485 	msg.Namelen = uint32(salen)
   506 	var iov Iovec
   486 	var dummy byte
   507 	if len(p) > 0 {
   487 	var empty bool
   508 		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
       
   509 		iov.SetLen(len(p))
       
   510 	}
       
   511 	var dummy int8
       
   512 	if len(oob) > 0 {
   488 	if len(oob) > 0 {
   513 		// send at least one normal byte
   489 		// send at least one normal byte
   514 		if len(p) == 0 {
   490 		empty = emptyIovecs(iov)
   515 			iov.Base = &dummy
   491 		if empty {
   516 			iov.SetLen(1)
   492 			var iova [1]Iovec
       
   493 			iova[0].Base = &dummy
       
   494 			iova[0].SetLen(1)
       
   495 			iov = iova[:]
   517 		}
   496 		}
   518 		msg.Accrightslen = int32(len(oob))
   497 		msg.Accrightslen = int32(len(oob))
   519 	}
   498 	}
   520 	msg.Iov = &iov
   499 	if len(iov) > 0 {
   521 	msg.Iovlen = 1
   500 		msg.Iov = &iov[0]
       
   501 		msg.SetIovlen(len(iov))
       
   502 	}
   522 	if n, err = sendmsg(fd, &msg, flags); err != nil {
   503 	if n, err = sendmsg(fd, &msg, flags); err != nil {
   523 		return 0, err
   504 		return 0, err
   524 	}
   505 	}
   525 	if len(oob) > 0 && len(p) == 0 {
   506 	if len(oob) > 0 && empty {
   526 		n = 0
   507 		n = 0
   527 	}
   508 	}
   528 	return n, nil
   509 	return n, nil
   529 }
   510 }
   530 
   511 
   635 //sys	Getegid() (egid int)
   616 //sys	Getegid() (egid int)
   636 //sys	Getppid() (ppid int)
   617 //sys	Getppid() (ppid int)
   637 //sys	Getpriority(which int, who int) (n int, err error)
   618 //sys	Getpriority(which int, who int) (n int, err error)
   638 //sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   619 //sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   639 //sysnb	Getrusage(who int, rusage *Rusage) (err error)
   620 //sysnb	Getrusage(who int, rusage *Rusage) (err error)
       
   621 //sysnb	Getsid(pid int) (sid int, err error)
   640 //sysnb	Gettimeofday(tv *Timeval) (err error)
   622 //sysnb	Gettimeofday(tv *Timeval) (err error)
   641 //sysnb	Getuid() (uid int)
   623 //sysnb	Getuid() (uid int)
   642 //sys	Kill(pid int, signum syscall.Signal) (err error)
   624 //sys	Kill(pid int, signum syscall.Signal) (err error)
   643 //sys	Lchown(path string, uid int, gid int) (err error)
   625 //sys	Lchown(path string, uid int, gid int) (err error)
   644 //sys	Link(path string, link string) (err error)
   626 //sys	Link(path string, link string) (err error)
   660 //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   642 //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   661 //sys	Open(path string, mode int, perm uint32) (fd int, err error)
   643 //sys	Open(path string, mode int, perm uint32) (fd int, err error)
   662 //sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
   644 //sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
   663 //sys	Pathconf(path string, name int) (val int, err error)
   645 //sys	Pathconf(path string, name int) (val int, err error)
   664 //sys	Pause() (err error)
   646 //sys	Pause() (err error)
   665 //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
   647 //sys	pread(fd int, p []byte, offset int64) (n int, err error)
   666 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
   648 //sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
   667 //sys	read(fd int, p []byte) (n int, err error)
   649 //sys	read(fd int, p []byte) (n int, err error)
   668 //sys	Readlink(path string, buf []byte) (n int, err error)
   650 //sys	Readlink(path string, buf []byte) (n int, err error)
   669 //sys	Rename(from string, to string) (err error)
   651 //sys	Rename(from string, to string) (err error)
   670 //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
   652 //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
   671 //sys	Rmdir(path string) (err error)
   653 //sys	Rmdir(path string) (err error)
   742 }
   724 }
   743 
   725 
   744 func Munmap(b []byte) (err error) {
   726 func Munmap(b []byte) (err error) {
   745 	return mapper.Munmap(b)
   727 	return mapper.Munmap(b)
   746 }
   728 }
       
   729 
       
   730 // Event Ports
       
   731 
       
   732 type fileObjCookie struct {
       
   733 	fobj   *fileObj
       
   734 	cookie interface{}
       
   735 }
       
   736 
       
   737 // EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
       
   738 type EventPort struct {
       
   739 	port  int
       
   740 	mu    sync.Mutex
       
   741 	fds   map[uintptr]*fileObjCookie
       
   742 	paths map[string]*fileObjCookie
       
   743 	// The user cookie presents an interesting challenge from a memory management perspective.
       
   744 	// There are two paths by which we can discover that it is no longer in use:
       
   745 	// 1. The user calls port_dissociate before any events fire
       
   746 	// 2. An event fires and we return it to the user
       
   747 	// The tricky situation is if the event has fired in the kernel but
       
   748 	// the user hasn't requested/received it yet.
       
   749 	// If the user wants to port_dissociate before the event has been processed,
       
   750 	// we should handle things gracefully. To do so, we need to keep an extra
       
   751 	// reference to the cookie around until the event is processed
       
   752 	// thus the otherwise seemingly extraneous "cookies" map
       
   753 	// The key of this map is a pointer to the corresponding &fCookie.cookie
       
   754 	cookies map[*interface{}]*fileObjCookie
       
   755 }
       
   756 
       
   757 // PortEvent is an abstraction of the port_event C struct.
       
   758 // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
       
   759 // to see if Path or Fd was the event source. The other will be
       
   760 // uninitialized.
       
   761 type PortEvent struct {
       
   762 	Cookie interface{}
       
   763 	Events int32
       
   764 	Fd     uintptr
       
   765 	Path   string
       
   766 	Source uint16
       
   767 	fobj   *fileObj
       
   768 }
       
   769 
       
   770 // NewEventPort creates a new EventPort including the
       
   771 // underlying call to port_create(3c).
       
   772 func NewEventPort() (*EventPort, error) {
       
   773 	port, err := port_create()
       
   774 	if err != nil {
       
   775 		return nil, err
       
   776 	}
       
   777 	e := &EventPort{
       
   778 		port:    port,
       
   779 		fds:     make(map[uintptr]*fileObjCookie),
       
   780 		paths:   make(map[string]*fileObjCookie),
       
   781 		cookies: make(map[*interface{}]*fileObjCookie),
       
   782 	}
       
   783 	return e, nil
       
   784 }
       
   785 
       
   786 //sys	port_create() (n int, err error)
       
   787 //sys	port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
       
   788 //sys	port_dissociate(port int, source int, object uintptr) (n int, err error)
       
   789 //sys	port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
       
   790 //sys	port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
       
   791 
       
   792 // Close closes the event port.
       
   793 func (e *EventPort) Close() error {
       
   794 	e.mu.Lock()
       
   795 	defer e.mu.Unlock()
       
   796 	err := Close(e.port)
       
   797 	if err != nil {
       
   798 		return err
       
   799 	}
       
   800 	e.fds = nil
       
   801 	e.paths = nil
       
   802 	return nil
       
   803 }
       
   804 
       
   805 // PathIsWatched checks to see if path is associated with this EventPort.
       
   806 func (e *EventPort) PathIsWatched(path string) bool {
       
   807 	e.mu.Lock()
       
   808 	defer e.mu.Unlock()
       
   809 	_, found := e.paths[path]
       
   810 	return found
       
   811 }
       
   812 
       
   813 // FdIsWatched checks to see if fd is associated with this EventPort.
       
   814 func (e *EventPort) FdIsWatched(fd uintptr) bool {
       
   815 	e.mu.Lock()
       
   816 	defer e.mu.Unlock()
       
   817 	_, found := e.fds[fd]
       
   818 	return found
       
   819 }
       
   820 
       
   821 // AssociatePath wraps port_associate(3c) for a filesystem path including
       
   822 // creating the necessary file_obj from the provided stat information.
       
   823 func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
       
   824 	e.mu.Lock()
       
   825 	defer e.mu.Unlock()
       
   826 	if _, found := e.paths[path]; found {
       
   827 		return fmt.Errorf("%v is already associated with this Event Port", path)
       
   828 	}
       
   829 	fobj, err := createFileObj(path, stat)
       
   830 	if err != nil {
       
   831 		return err
       
   832 	}
       
   833 	fCookie := &fileObjCookie{fobj, cookie}
       
   834 	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
       
   835 	if err != nil {
       
   836 		return err
       
   837 	}
       
   838 	e.paths[path] = fCookie
       
   839 	e.cookies[&fCookie.cookie] = fCookie
       
   840 	return nil
       
   841 }
       
   842 
       
   843 // DissociatePath wraps port_dissociate(3c) for a filesystem path.
       
   844 func (e *EventPort) DissociatePath(path string) error {
       
   845 	e.mu.Lock()
       
   846 	defer e.mu.Unlock()
       
   847 	f, ok := e.paths[path]
       
   848 	if !ok {
       
   849 		return fmt.Errorf("%v is not associated with this Event Port", path)
       
   850 	}
       
   851 	_, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
       
   852 	// If the path is no longer associated with this event port (ENOENT)
       
   853 	// we should delete it from our map. We can still return ENOENT to the caller.
       
   854 	// But we need to save the cookie
       
   855 	if err != nil && err != ENOENT {
       
   856 		return err
       
   857 	}
       
   858 	if err == nil {
       
   859 		// dissociate was successful, safe to delete the cookie
       
   860 		fCookie := e.paths[path]
       
   861 		delete(e.cookies, &fCookie.cookie)
       
   862 	}
       
   863 	delete(e.paths, path)
       
   864 	return err
       
   865 }
       
   866 
       
   867 // AssociateFd wraps calls to port_associate(3c) on file descriptors.
       
   868 func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
       
   869 	e.mu.Lock()
       
   870 	defer e.mu.Unlock()
       
   871 	if _, found := e.fds[fd]; found {
       
   872 		return fmt.Errorf("%v is already associated with this Event Port", fd)
       
   873 	}
       
   874 	fCookie := &fileObjCookie{nil, cookie}
       
   875 	_, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
       
   876 	if err != nil {
       
   877 		return err
       
   878 	}
       
   879 	e.fds[fd] = fCookie
       
   880 	e.cookies[&fCookie.cookie] = fCookie
       
   881 	return nil
       
   882 }
       
   883 
       
   884 // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
       
   885 func (e *EventPort) DissociateFd(fd uintptr) error {
       
   886 	e.mu.Lock()
       
   887 	defer e.mu.Unlock()
       
   888 	_, ok := e.fds[fd]
       
   889 	if !ok {
       
   890 		return fmt.Errorf("%v is not associated with this Event Port", fd)
       
   891 	}
       
   892 	_, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
       
   893 	if err != nil && err != ENOENT {
       
   894 		return err
       
   895 	}
       
   896 	if err == nil {
       
   897 		// dissociate was successful, safe to delete the cookie
       
   898 		fCookie := e.fds[fd]
       
   899 		delete(e.cookies, &fCookie.cookie)
       
   900 	}
       
   901 	delete(e.fds, fd)
       
   902 	return err
       
   903 }
       
   904 
       
   905 func createFileObj(name string, stat os.FileInfo) (*fileObj, error) {
       
   906 	fobj := new(fileObj)
       
   907 	bs, err := ByteSliceFromString(name)
       
   908 	if err != nil {
       
   909 		return nil, err
       
   910 	}
       
   911 	fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
       
   912 	s := stat.Sys().(*syscall.Stat_t)
       
   913 	fobj.Atim.Sec = s.Atim.Sec
       
   914 	fobj.Atim.Nsec = s.Atim.Nsec
       
   915 	fobj.Mtim.Sec = s.Mtim.Sec
       
   916 	fobj.Mtim.Nsec = s.Mtim.Nsec
       
   917 	fobj.Ctim.Sec = s.Ctim.Sec
       
   918 	fobj.Ctim.Nsec = s.Ctim.Nsec
       
   919 	return fobj, nil
       
   920 }
       
   921 
       
   922 // GetOne wraps port_get(3c) and returns a single PortEvent.
       
   923 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
       
   924 	pe := new(portEvent)
       
   925 	_, err := port_get(e.port, pe, t)
       
   926 	if err != nil {
       
   927 		return nil, err
       
   928 	}
       
   929 	p := new(PortEvent)
       
   930 	e.mu.Lock()
       
   931 	defer e.mu.Unlock()
       
   932 	e.peIntToExt(pe, p)
       
   933 	return p, nil
       
   934 }
       
   935 
       
   936 // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
       
   937 // NOTE: Always call this function while holding the e.mu mutex
       
   938 func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) {
       
   939 	peExt.Events = peInt.Events
       
   940 	peExt.Source = peInt.Source
       
   941 	cookie := (*interface{})(unsafe.Pointer(peInt.User))
       
   942 	peExt.Cookie = *cookie
       
   943 	switch peInt.Source {
       
   944 	case PORT_SOURCE_FD:
       
   945 		delete(e.cookies, cookie)
       
   946 		peExt.Fd = uintptr(peInt.Object)
       
   947 		// Only remove the fds entry if it exists and this cookie matches
       
   948 		if fobj, ok := e.fds[peExt.Fd]; ok {
       
   949 			if &fobj.cookie == cookie {
       
   950 				delete(e.fds, peExt.Fd)
       
   951 			}
       
   952 		}
       
   953 	case PORT_SOURCE_FILE:
       
   954 		if fCookie, ok := e.cookies[cookie]; ok && uintptr(unsafe.Pointer(fCookie.fobj)) == uintptr(peInt.Object) {
       
   955 			// Use our stashed reference rather than using unsafe on what we got back
       
   956 			// the unsafe version would be (*fileObj)(unsafe.Pointer(uintptr(peInt.Object)))
       
   957 			peExt.fobj = fCookie.fobj
       
   958 		} else {
       
   959 			panic("mismanaged memory")
       
   960 		}
       
   961 		delete(e.cookies, cookie)
       
   962 		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
       
   963 		// Only remove the paths entry if it exists and this cookie matches
       
   964 		if fobj, ok := e.paths[peExt.Path]; ok {
       
   965 			if &fobj.cookie == cookie {
       
   966 				delete(e.paths, peExt.Path)
       
   967 			}
       
   968 		}
       
   969 	}
       
   970 }
       
   971 
       
   972 // Pending wraps port_getn(3c) and returns how many events are pending.
       
   973 func (e *EventPort) Pending() (int, error) {
       
   974 	var n uint32 = 0
       
   975 	_, err := port_getn(e.port, nil, 0, &n, nil)
       
   976 	return int(n), err
       
   977 }
       
   978 
       
   979 // Get wraps port_getn(3c) and fills a slice of PortEvent.
       
   980 // It will block until either min events have been received
       
   981 // or the timeout has been exceeded. It will return how many
       
   982 // events were actually received along with any error information.
       
   983 func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
       
   984 	if min == 0 {
       
   985 		return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
       
   986 	}
       
   987 	if len(s) < min {
       
   988 		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
       
   989 	}
       
   990 	got := uint32(min)
       
   991 	max := uint32(len(s))
       
   992 	var err error
       
   993 	ps := make([]portEvent, max, max)
       
   994 	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
       
   995 	// got will be trustworthy with ETIME, but not any other error.
       
   996 	if err != nil && err != ETIME {
       
   997 		return 0, err
       
   998 	}
       
   999 	e.mu.Lock()
       
  1000 	defer e.mu.Unlock()
       
  1001 	for i := 0; i < int(got); i++ {
       
  1002 		e.peIntToExt(&ps[i], &s[i])
       
  1003 	}
       
  1004 	return int(got), err
       
  1005 }