1  
     2  
     3  
     4  
     5  
     6  
     7  
     8  
     9  
    10  
    11  
    12  
    13  package unix
    14  
    15  import (
    16  	"fmt"
    17  	"os"
    18  	"runtime"
    19  	"sync"
    20  	"syscall"
    21  	"unsafe"
    22  )
    23  
    24  
    25  type syscallFunc uintptr
    26  
    27  func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
    28  func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
    29  
    30  
    31  type SockaddrDatalink struct {
    32  	Family uint16
    33  	Index  uint16
    34  	Type   uint8
    35  	Nlen   uint8
    36  	Alen   uint8
    37  	Slen   uint8
    38  	Data   [244]int8
    39  	raw    RawSockaddrDatalink
    40  }
    41  
    42  func direntIno(buf []byte) (uint64, bool) {
    43  	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
    44  }
    45  
    46  func direntReclen(buf []byte) (uint64, bool) {
    47  	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
    48  }
    49  
    50  func direntNamlen(buf []byte) (uint64, bool) {
    51  	reclen, ok := direntReclen(buf)
    52  	if !ok {
    53  		return 0, false
    54  	}
    55  	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
    56  }
    57  
    58  
    59  
    60  func Pipe(p []int) (err error) {
    61  	if len(p) != 2 {
    62  		return EINVAL
    63  	}
    64  	var pp [2]_C_int
    65  	n, err := pipe(&pp)
    66  	if n != 0 {
    67  		return err
    68  	}
    69  	p[0] = int(pp[0])
    70  	p[1] = int(pp[1])
    71  	return nil
    72  }
    73  
    74  
    75  
    76  func Pipe2(p []int, flags int) error {
    77  	if len(p) != 2 {
    78  		return EINVAL
    79  	}
    80  	var pp [2]_C_int
    81  	err := pipe2(&pp, flags)
    82  	p[0] = int(pp[0])
    83  	p[1] = int(pp[1])
    84  	return err
    85  }
    86  
    87  func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
    88  	if sa.Port < 0 || sa.Port > 0xFFFF {
    89  		return nil, 0, EINVAL
    90  	}
    91  	sa.raw.Family = AF_INET
    92  	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
    93  	p[0] = byte(sa.Port >> 8)
    94  	p[1] = byte(sa.Port)
    95  	sa.raw.Addr = sa.Addr
    96  	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
    97  }
    98  
    99  func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
   100  	if sa.Port < 0 || sa.Port > 0xFFFF {
   101  		return nil, 0, EINVAL
   102  	}
   103  	sa.raw.Family = AF_INET6
   104  	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
   105  	p[0] = byte(sa.Port >> 8)
   106  	p[1] = byte(sa.Port)
   107  	sa.raw.Scope_id = sa.ZoneId
   108  	sa.raw.Addr = sa.Addr
   109  	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
   110  }
   111  
   112  func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
   113  	name := sa.Name
   114  	n := len(name)
   115  	if n >= len(sa.raw.Path) {
   116  		return nil, 0, EINVAL
   117  	}
   118  	sa.raw.Family = AF_UNIX
   119  	for i := 0; i < n; i++ {
   120  		sa.raw.Path[i] = int8(name[i])
   121  	}
   122  	
   123  	sl := _Socklen(2)
   124  	if n > 0 {
   125  		sl += _Socklen(n) + 1
   126  	}
   127  	if sa.raw.Path[0] == '@' {
   128  		sa.raw.Path[0] = 0
   129  		
   130  		sl--
   131  	}
   132  
   133  	return unsafe.Pointer(&sa.raw), sl, nil
   134  }
   135  
   136  
   137  
   138  func Getsockname(fd int) (sa Sockaddr, err error) {
   139  	var rsa RawSockaddrAny
   140  	var len _Socklen = SizeofSockaddrAny
   141  	if err = getsockname(fd, &rsa, &len); err != nil {
   142  		return
   143  	}
   144  	return anyToSockaddr(fd, &rsa)
   145  }
   146  
   147  
   148  
   149  func GetsockoptString(fd, level, opt int) (string, error) {
   150  	buf := make([]byte, 256)
   151  	vallen := _Socklen(len(buf))
   152  	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
   153  	if err != nil {
   154  		return "", err
   155  	}
   156  	return string(buf[:vallen-1]), nil
   157  }
   158  
   159  const ImplementsGetwd = true
   160  
   161  
   162  
   163  func Getwd() (wd string, err error) {
   164  	var buf [PathMax]byte
   165  	
   166  	_, err = Getcwd(buf[0:])
   167  	if err != nil {
   168  		return "", err
   169  	}
   170  	n := clen(buf[:])
   171  	if n < 1 {
   172  		return "", EINVAL
   173  	}
   174  	return string(buf[:n]), nil
   175  }
   176  
   177  
   180  
   181  
   182  
   183  
   184  func Getgroups() (gids []int, err error) {
   185  	n, err := getgroups(0, nil)
   186  	
   187  	
   188  	if n < 0 || n > 1024 {
   189  		if err != nil {
   190  			return nil, err
   191  		}
   192  		return nil, EINVAL
   193  	} else if n == 0 {
   194  		return nil, nil
   195  	}
   196  
   197  	a := make([]_Gid_t, n)
   198  	n, err = getgroups(n, &a[0])
   199  	if n == -1 {
   200  		return nil, err
   201  	}
   202  	gids = make([]int, n)
   203  	for i, v := range a[0:n] {
   204  		gids[i] = int(v)
   205  	}
   206  	return
   207  }
   208  
   209  func Setgroups(gids []int) (err error) {
   210  	if len(gids) == 0 {
   211  		return setgroups(0, nil)
   212  	}
   213  
   214  	a := make([]_Gid_t, len(gids))
   215  	for i, v := range gids {
   216  		a[i] = _Gid_t(v)
   217  	}
   218  	return setgroups(len(a), &a[0])
   219  }
   220  
   221  
   222  func ReadDirent(fd int, buf []byte) (n int, err error) {
   223  	
   224  	
   225  	return Getdents(fd, buf, new(uintptr))
   226  }
   227  
   228  
   229  
   230  
   231  
   232  
   233  
   234  type WaitStatus uint32
   235  
   236  const (
   237  	mask  = 0x7F
   238  	core  = 0x80
   239  	shift = 8
   240  
   241  	exited  = 0
   242  	stopped = 0x7F
   243  )
   244  
   245  func (w WaitStatus) Exited() bool { return w&mask == exited }
   246  
   247  func (w WaitStatus) ExitStatus() int {
   248  	if w&mask != exited {
   249  		return -1
   250  	}
   251  	return int(w >> shift)
   252  }
   253  
   254  func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
   255  
   256  func (w WaitStatus) Signal() syscall.Signal {
   257  	sig := syscall.Signal(w & mask)
   258  	if sig == stopped || sig == 0 {
   259  		return -1
   260  	}
   261  	return sig
   262  }
   263  
   264  func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
   265  
   266  func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
   267  
   268  func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
   269  
   270  func (w WaitStatus) StopSignal() syscall.Signal {
   271  	if !w.Stopped() {
   272  		return -1
   273  	}
   274  	return syscall.Signal(w>>shift) & 0xFF
   275  }
   276  
   277  func (w WaitStatus) TrapCause() int { return -1 }
   278  
   279  
   280  
   281  func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
   282  	var status _C_int
   283  	rpid, err := wait4(int32(pid), &status, options, rusage)
   284  	wpid := int(rpid)
   285  	if wpid == -1 {
   286  		return wpid, err
   287  	}
   288  	if wstatus != nil {
   289  		*wstatus = WaitStatus(status)
   290  	}
   291  	return wpid, nil
   292  }
   293  
   294  
   295  
   296  func Gethostname() (name string, err error) {
   297  	var buf [MaxHostNameLen]byte
   298  	n, err := gethostname(buf[:])
   299  	if n != 0 {
   300  		return "", err
   301  	}
   302  	n = clen(buf[:])
   303  	if n < 1 {
   304  		return "", EFAULT
   305  	}
   306  	return string(buf[:n]), nil
   307  }
   308  
   309  
   310  
   311  func Utimes(path string, tv []Timeval) (err error) {
   312  	if tv == nil {
   313  		return utimes(path, nil)
   314  	}
   315  	if len(tv) != 2 {
   316  		return EINVAL
   317  	}
   318  	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   319  }
   320  
   321  
   322  
   323  func UtimesNano(path string, ts []Timespec) error {
   324  	if ts == nil {
   325  		return utimensat(AT_FDCWD, path, nil, 0)
   326  	}
   327  	if len(ts) != 2 {
   328  		return EINVAL
   329  	}
   330  	return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
   331  }
   332  
   333  func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
   334  	if ts == nil {
   335  		return utimensat(dirfd, path, nil, flags)
   336  	}
   337  	if len(ts) != 2 {
   338  		return EINVAL
   339  	}
   340  	return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
   341  }
   342  
   343  
   344  
   345  
   346  func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
   347  	valptr, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
   348  	var err error
   349  	if errno != 0 {
   350  		err = errno
   351  	}
   352  	return int(valptr), err
   353  }
   354  
   355  
   356  func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
   357  	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
   358  	if e1 != 0 {
   359  		return e1
   360  	}
   361  	return nil
   362  }
   363  
   364  
   365  
   366  func Futimesat(dirfd int, path string, tv []Timeval) error {
   367  	pathp, err := BytePtrFromString(path)
   368  	if err != nil {
   369  		return err
   370  	}
   371  	if tv == nil {
   372  		return futimesat(dirfd, pathp, nil)
   373  	}
   374  	if len(tv) != 2 {
   375  		return EINVAL
   376  	}
   377  	return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   378  }
   379  
   380  
   381  
   382  
   383  func Futimes(fd int, tv []Timeval) error {
   384  	if tv == nil {
   385  		return futimesat(fd, nil, nil)
   386  	}
   387  	if len(tv) != 2 {
   388  		return EINVAL
   389  	}
   390  	return futimesat(fd, nil, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   391  }
   392  
   393  func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
   394  	switch rsa.Addr.Family {
   395  	case AF_UNIX:
   396  		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
   397  		sa := new(SockaddrUnix)
   398  		
   399  		
   400  		
   401  		
   402  		
   403  		n := 0
   404  		for n < len(pp.Path) && pp.Path[n] != 0 {
   405  			n++
   406  		}
   407  		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
   408  		sa.Name = string(bytes)
   409  		return sa, nil
   410  
   411  	case AF_INET:
   412  		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
   413  		sa := new(SockaddrInet4)
   414  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   415  		sa.Port = int(p[0])<<8 + int(p[1])
   416  		sa.Addr = pp.Addr
   417  		return sa, nil
   418  
   419  	case AF_INET6:
   420  		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
   421  		sa := new(SockaddrInet6)
   422  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   423  		sa.Port = int(p[0])<<8 + int(p[1])
   424  		sa.ZoneId = pp.Scope_id
   425  		sa.Addr = pp.Addr
   426  		return sa, nil
   427  	}
   428  	return nil, EAFNOSUPPORT
   429  }
   430  
   431  
   432  
   433  func Accept(fd int) (nfd int, sa Sockaddr, err error) {
   434  	var rsa RawSockaddrAny
   435  	var len _Socklen = SizeofSockaddrAny
   436  	nfd, err = accept(fd, &rsa, &len)
   437  	if nfd == -1 {
   438  		return
   439  	}
   440  	sa, err = anyToSockaddr(fd, &rsa)
   441  	if err != nil {
   442  		Close(nfd)
   443  		nfd = 0
   444  	}
   445  	return
   446  }
   447  
   448  
   449  
   450  func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
   451  	var msg Msghdr
   452  	var rsa RawSockaddrAny
   453  	msg.Name = (*byte)(unsafe.Pointer(&rsa))
   454  	msg.Namelen = uint32(SizeofSockaddrAny)
   455  	var iov Iovec
   456  	if len(p) > 0 {
   457  		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
   458  		iov.SetLen(len(p))
   459  	}
   460  	var dummy int8
   461  	if len(oob) > 0 {
   462  		
   463  		if len(p) == 0 {
   464  			iov.Base = &dummy
   465  			iov.SetLen(1)
   466  		}
   467  		msg.Accrightslen = int32(len(oob))
   468  	}
   469  	msg.Iov = &iov
   470  	msg.Iovlen = 1
   471  	if n, err = recvmsg(fd, &msg, flags); n == -1 {
   472  		return
   473  	}
   474  	oobn = int(msg.Accrightslen)
   475  	
   476  	if rsa.Addr.Family != AF_UNSPEC {
   477  		from, err = anyToSockaddr(fd, &rsa)
   478  	}
   479  	return
   480  }
   481  
   482  func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
   483  	_, err = SendmsgN(fd, p, oob, to, flags)
   484  	return
   485  }
   486  
   487  
   488  
   489  func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
   490  	var ptr unsafe.Pointer
   491  	var salen _Socklen
   492  	if to != nil {
   493  		ptr, salen, err = to.sockaddr()
   494  		if err != nil {
   495  			return 0, err
   496  		}
   497  	}
   498  	var msg Msghdr
   499  	msg.Name = (*byte)(unsafe.Pointer(ptr))
   500  	msg.Namelen = uint32(salen)
   501  	var iov Iovec
   502  	if len(p) > 0 {
   503  		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
   504  		iov.SetLen(len(p))
   505  	}
   506  	var dummy int8
   507  	if len(oob) > 0 {
   508  		
   509  		if len(p) == 0 {
   510  			iov.Base = &dummy
   511  			iov.SetLen(1)
   512  		}
   513  		msg.Accrightslen = int32(len(oob))
   514  	}
   515  	msg.Iov = &iov
   516  	msg.Iovlen = 1
   517  	if n, err = sendmsg(fd, &msg, flags); err != nil {
   518  		return 0, err
   519  	}
   520  	if len(oob) > 0 && len(p) == 0 {
   521  		n = 0
   522  	}
   523  	return n, nil
   524  }
   525  
   526  
   527  
   528  func Acct(path string) (err error) {
   529  	if len(path) == 0 {
   530  		
   531  		return acct(nil)
   532  	}
   533  
   534  	pathp, err := BytePtrFromString(path)
   535  	if err != nil {
   536  		return err
   537  	}
   538  	return acct(pathp)
   539  }
   540  
   541  
   542  
   543  func Mkdev(major, minor uint32) uint64 {
   544  	return __makedev(NEWDEV, uint(major), uint(minor))
   545  }
   546  
   547  
   548  
   549  func Major(dev uint64) uint32 {
   550  	return uint32(__major(NEWDEV, dev))
   551  }
   552  
   553  
   554  
   555  func Minor(dev uint64) uint32 {
   556  	return uint32(__minor(NEWDEV, dev))
   557  }
   558  
   559  
   562  
   563  
   564  
   565  func ioctl(fd int, req uint, arg uintptr) (err error) {
   566  	_, err = ioctlRet(fd, req, arg)
   567  	return err
   568  }
   569  
   570  func IoctlSetTermio(fd int, req uint, value *Termio) error {
   571  	err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
   572  	runtime.KeepAlive(value)
   573  	return err
   574  }
   575  
   576  func IoctlGetTermio(fd int, req uint) (*Termio, error) {
   577  	var value Termio
   578  	err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
   579  	return &value, err
   580  }
   581  
   582  
   583  
   584  func Poll(fds []PollFd, timeout int) (n int, err error) {
   585  	if len(fds) == 0 {
   586  		return poll(nil, 0, timeout)
   587  	}
   588  	return poll(&fds[0], len(fds), timeout)
   589  }
   590  
   591  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
   592  	if raceenabled {
   593  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   594  	}
   595  	return sendfile(outfd, infd, offset, count)
   596  }
   597  
   598  
   601  
   602  
   603  
   604  
   605  
   606  
   607  
   608  
   609  
   610  
   611  
   612  
   613  
   614  
   615  
   616  
   617  
   618  
   619  
   620  
   621  
   622  
   623  
   624  
   625  
   626  
   627  
   628  
   629  
   630  
   631  
   632  
   633  
   634  
   635  
   636  
   637  
   638  
   639  
   640  
   641  
   642  
   643  
   644  
   645  
   646  
   647  
   648  
   649  
   650  
   651  
   652  
   653  
   654  
   655  
   656  
   657  
   658  
   659  
   660  
   661  
   662  
   663  
   664  
   665  
   666  
   667  
   668  
   669  
   670  
   671  
   672  
   673  
   674  
   675  
   676  
   677  
   678  
   679  
   680  
   681  
   682  
   683  
   684  
   685  
   686  
   687  
   688  
   689  
   690  
   691  
   692  
   693  
   694  
   695  
   696  
   697  
   698  
   699  
   700  
   701  
   702  
   703  
   704  
   705  
   706  
   707  
   708  
   709  
   710  
   711  func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
   712  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   713  	n = int(r0)
   714  	if e1 != 0 {
   715  		err = e1
   716  	}
   717  	return
   718  }
   719  
   720  func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
   721  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   722  	n = int(r0)
   723  	if e1 != 0 {
   724  		err = e1
   725  	}
   726  	return
   727  }
   728  
   729  var mapper = &mmapper{
   730  	active: make(map[*byte][]byte),
   731  	mmap:   mmap,
   732  	munmap: munmap,
   733  }
   734  
   735  func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
   736  	return mapper.Mmap(fd, offset, length, prot, flags)
   737  }
   738  
   739  func Munmap(b []byte) (err error) {
   740  	return mapper.Munmap(b)
   741  }
   742  
   743  
   744  
   745  type fileObjCookie struct {
   746  	fobj   *fileObj
   747  	cookie interface{}
   748  }
   749  
   750  
   751  type EventPort struct {
   752  	port  int
   753  	mu    sync.Mutex
   754  	fds   map[uintptr]interface{}
   755  	paths map[string]*fileObjCookie
   756  }
   757  
   758  
   759  
   760  
   761  
   762  type PortEvent struct {
   763  	Cookie interface{}
   764  	Events int32
   765  	Fd     uintptr
   766  	Path   string
   767  	Source uint16
   768  	fobj   *fileObj
   769  }
   770  
   771  
   772  
   773  func NewEventPort() (*EventPort, error) {
   774  	port, err := port_create()
   775  	if err != nil {
   776  		return nil, err
   777  	}
   778  	e := &EventPort{
   779  		port:  port,
   780  		fds:   make(map[uintptr]interface{}),
   781  		paths: make(map[string]*fileObjCookie),
   782  	}
   783  	return e, nil
   784  }
   785  
   786  
   787  
   788  
   789  
   790  
   791  
   792  
   793  func (e *EventPort) Close() error {
   794  	e.mu.Lock()
   795  	defer e.mu.Unlock()
   796  	e.fds = nil
   797  	e.paths = nil
   798  	return Close(e.port)
   799  }
   800  
   801  
   802  func (e *EventPort) PathIsWatched(path string) bool {
   803  	e.mu.Lock()
   804  	defer e.mu.Unlock()
   805  	_, found := e.paths[path]
   806  	return found
   807  }
   808  
   809  
   810  func (e *EventPort) FdIsWatched(fd uintptr) bool {
   811  	e.mu.Lock()
   812  	defer e.mu.Unlock()
   813  	_, found := e.fds[fd]
   814  	return found
   815  }
   816  
   817  
   818  
   819  func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
   820  	e.mu.Lock()
   821  	defer e.mu.Unlock()
   822  	if _, found := e.paths[path]; found {
   823  		return fmt.Errorf("%v is already associated with this Event Port", path)
   824  	}
   825  	fobj, err := createFileObj(path, stat)
   826  	if err != nil {
   827  		return err
   828  	}
   829  	fCookie := &fileObjCookie{fobj, cookie}
   830  	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
   831  	if err != nil {
   832  		return err
   833  	}
   834  	e.paths[path] = fCookie
   835  	return nil
   836  }
   837  
   838  
   839  func (e *EventPort) DissociatePath(path string) error {
   840  	e.mu.Lock()
   841  	defer e.mu.Unlock()
   842  	f, ok := e.paths[path]
   843  	if !ok {
   844  		return fmt.Errorf("%v is not associated with this Event Port", path)
   845  	}
   846  	_, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
   847  	if err != nil {
   848  		return err
   849  	}
   850  	delete(e.paths, path)
   851  	return nil
   852  }
   853  
   854  
   855  func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
   856  	e.mu.Lock()
   857  	defer e.mu.Unlock()
   858  	if _, found := e.fds[fd]; found {
   859  		return fmt.Errorf("%v is already associated with this Event Port", fd)
   860  	}
   861  	pcookie := &cookie
   862  	_, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(pcookie)))
   863  	if err != nil {
   864  		return err
   865  	}
   866  	e.fds[fd] = pcookie
   867  	return nil
   868  }
   869  
   870  
   871  func (e *EventPort) DissociateFd(fd uintptr) error {
   872  	e.mu.Lock()
   873  	defer e.mu.Unlock()
   874  	_, ok := e.fds[fd]
   875  	if !ok {
   876  		return fmt.Errorf("%v is not associated with this Event Port", fd)
   877  	}
   878  	_, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
   879  	if err != nil {
   880  		return err
   881  	}
   882  	delete(e.fds, fd)
   883  	return nil
   884  }
   885  
   886  func createFileObj(name string, stat os.FileInfo) (*fileObj, error) {
   887  	fobj := new(fileObj)
   888  	bs, err := ByteSliceFromString(name)
   889  	if err != nil {
   890  		return nil, err
   891  	}
   892  	fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
   893  	s := stat.Sys().(*syscall.Stat_t)
   894  	fobj.Atim.Sec = s.Atim.Sec
   895  	fobj.Atim.Nsec = s.Atim.Nsec
   896  	fobj.Mtim.Sec = s.Mtim.Sec
   897  	fobj.Mtim.Nsec = s.Mtim.Nsec
   898  	fobj.Ctim.Sec = s.Ctim.Sec
   899  	fobj.Ctim.Nsec = s.Ctim.Nsec
   900  	return fobj, nil
   901  }
   902  
   903  
   904  func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
   905  	pe := new(portEvent)
   906  	_, err := port_get(e.port, pe, t)
   907  	if err != nil {
   908  		return nil, err
   909  	}
   910  	p := new(PortEvent)
   911  	p.Events = pe.Events
   912  	p.Source = pe.Source
   913  	e.mu.Lock()
   914  	defer e.mu.Unlock()
   915  	switch pe.Source {
   916  	case PORT_SOURCE_FD:
   917  		p.Fd = uintptr(pe.Object)
   918  		cookie := (*interface{})(unsafe.Pointer(pe.User))
   919  		p.Cookie = *cookie
   920  		delete(e.fds, p.Fd)
   921  	case PORT_SOURCE_FILE:
   922  		p.fobj = (*fileObj)(unsafe.Pointer(uintptr(pe.Object)))
   923  		p.Path = BytePtrToString((*byte)(unsafe.Pointer(p.fobj.Name)))
   924  		cookie := (*interface{})(unsafe.Pointer(pe.User))
   925  		p.Cookie = *cookie
   926  		delete(e.paths, p.Path)
   927  	}
   928  	return p, nil
   929  }
   930  
   931  
   932  func (e *EventPort) Pending() (int, error) {
   933  	var n uint32 = 0
   934  	_, err := port_getn(e.port, nil, 0, &n, nil)
   935  	return int(n), err
   936  }
   937  
   938  
   939  
   940  
   941  
   942  func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
   943  	if min == 0 {
   944  		return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
   945  	}
   946  	if len(s) < min {
   947  		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
   948  	}
   949  	got := uint32(min)
   950  	max := uint32(len(s))
   951  	var err error
   952  	ps := make([]portEvent, max, max)
   953  	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
   954  	
   955  	if err != nil && err != ETIME {
   956  		return 0, err
   957  	}
   958  	e.mu.Lock()
   959  	defer e.mu.Unlock()
   960  	for i := 0; i < int(got); i++ {
   961  		s[i].Events = ps[i].Events
   962  		s[i].Source = ps[i].Source
   963  		switch ps[i].Source {
   964  		case PORT_SOURCE_FD:
   965  			s[i].Fd = uintptr(ps[i].Object)
   966  			cookie := (*interface{})(unsafe.Pointer(ps[i].User))
   967  			s[i].Cookie = *cookie
   968  			delete(e.fds, s[i].Fd)
   969  		case PORT_SOURCE_FILE:
   970  			s[i].fobj = (*fileObj)(unsafe.Pointer(uintptr(ps[i].Object)))
   971  			s[i].Path = BytePtrToString((*byte)(unsafe.Pointer(s[i].fobj.Name)))
   972  			cookie := (*interface{})(unsafe.Pointer(ps[i].User))
   973  			s[i].Cookie = *cookie
   974  			delete(e.paths, s[i].Path)
   975  		}
   976  	}
   977  	return int(got), err
   978  }
   979  
View as plain text