Source file src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Solaris system calls.
     6  // This file is compiled as ordinary Go code,
     7  // but it is also input to mksyscall,
     8  // which parses the //sys lines and generates system call stubs.
     9  // Note that sometimes we use a lowercase //sys name and wrap
    10  // it in our own nicer implementation, either here or in
    11  // syscall_solaris.go or syscall_unix.go.
    12  
    13  package unix
    14  
    15  import (
    16  	"fmt"
    17  	"os"
    18  	"runtime"
    19  	"sync"
    20  	"syscall"
    21  	"unsafe"
    22  )
    23  
    24  // Implemented in runtime/syscall_solaris.go.
    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  // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
    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  //sysnb	pipe(p *[2]_C_int) (n int, err error)
    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  //sysnb	pipe2(p *[2]_C_int, flags int) (err error)
    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  	// length is family (uint16), name, NUL.
   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  		// Don't count trailing NUL for abstract address.
   130  		sl--
   131  	}
   132  
   133  	return unsafe.Pointer(&sa.raw), sl, nil
   134  }
   135  
   136  //sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
   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  // GetsockoptString returns the string value of the socket option opt for the
   148  // socket associated with fd at the given socket level.
   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  //sys	Getcwd(buf []byte) (n int, err error)
   162  
   163  func Getwd() (wd string, err error) {
   164  	var buf [PathMax]byte
   165  	// Getcwd will return an error if it failed for any reason.
   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  /*
   178   * Wrapped
   179   */
   180  
   181  //sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
   182  //sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
   183  
   184  func Getgroups() (gids []int, err error) {
   185  	n, err := getgroups(0, nil)
   186  	// Check for error and sanity check group count. Newer versions of
   187  	// Solaris allow up to 1024 (NGROUPS_MAX).
   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  // ReadDirent reads directory entries from fd and writes them into buf.
   222  func ReadDirent(fd int, buf []byte) (n int, err error) {
   223  	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
   224  	// TODO(rsc): Can we use a single global basep for all calls?
   225  	return Getdents(fd, buf, new(uintptr))
   226  }
   227  
   228  // Wait status is 7 bits at bottom, either 0 (exited),
   229  // 0x7F (stopped), or a signal number that caused an exit.
   230  // The 0x80 bit is whether there was a core dump.
   231  // An extra number (exit code, signal causing a stop)
   232  // is in the high bits.
   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  //sys	wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
   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  //sys	gethostname(buf []byte) (n int, err error)
   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  //sys	utimes(path string, times *[2]Timeval) (err error)
   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  //sys	utimensat(fd int, path string, times *[2]Timespec, flag int) (err error)
   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  //sys	fcntl(fd int, cmd int, arg int) (val int, err error)
   344  
   345  // FcntlInt performs a fcntl syscall on fd with the provided command and argument.
   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  // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
   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  //sys	futimesat(fildes int, path *byte, times *[2]Timeval) (err error)
   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  // Solaris doesn't have an futimes function because it allows NULL to be
   381  // specified as the path for futimesat. However, Go doesn't like
   382  // NULL-style string interfaces, so this simple wrapper is provided.
   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  		// Assume path ends at NUL.
   399  		// This is not technically the Solaris semantics for
   400  		// abstract Unix domain sockets -- they are supposed
   401  		// to be uninterpreted fixed-size binary blobs -- but
   402  		// everyone uses this convention.
   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  //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
   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  //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
   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  		// receive at least one normal byte
   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  	// source address is only specified if the socket is unconnected
   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  //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
   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  		// send at least one normal byte
   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  //sys	acct(path *byte) (err error)
   527  
   528  func Acct(path string) (err error) {
   529  	if len(path) == 0 {
   530  		// Assume caller wants to disable accounting.
   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  //sys	__makedev(version int, major uint, minor uint) (val uint64)
   542  
   543  func Mkdev(major, minor uint32) uint64 {
   544  	return __makedev(NEWDEV, uint(major), uint(minor))
   545  }
   546  
   547  //sys	__major(version int, dev uint64) (val uint)
   548  
   549  func Major(dev uint64) uint32 {
   550  	return uint32(__major(NEWDEV, dev))
   551  }
   552  
   553  //sys	__minor(version int, dev uint64) (val uint)
   554  
   555  func Minor(dev uint64) uint32 {
   556  	return uint32(__minor(NEWDEV, dev))
   557  }
   558  
   559  /*
   560   * Expose the ioctl function
   561   */
   562  
   563  //sys	ioctlRet(fd int, req uint, arg uintptr) (ret int, err error) = libc.ioctl
   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  //sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)
   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  /*
   599   * Exposed directly
   600   */
   601  //sys	Access(path string, mode uint32) (err error)
   602  //sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
   603  //sys	Chdir(path string) (err error)
   604  //sys	Chmod(path string, mode uint32) (err error)
   605  //sys	Chown(path string, uid int, gid int) (err error)
   606  //sys	Chroot(path string) (err error)
   607  //sys	Close(fd int) (err error)
   608  //sys	Creat(path string, mode uint32) (fd int, err error)
   609  //sys	Dup(fd int) (nfd int, err error)
   610  //sys	Dup2(oldfd int, newfd int) (err error)
   611  //sys	Exit(code int)
   612  //sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
   613  //sys	Fchdir(fd int) (err error)
   614  //sys	Fchmod(fd int, mode uint32) (err error)
   615  //sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
   616  //sys	Fchown(fd int, uid int, gid int) (err error)
   617  //sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
   618  //sys	Fdatasync(fd int) (err error)
   619  //sys	Flock(fd int, how int) (err error)
   620  //sys	Fpathconf(fd int, name int) (val int, err error)
   621  //sys	Fstat(fd int, stat *Stat_t) (err error)
   622  //sys	Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
   623  //sys	Fstatvfs(fd int, vfsstat *Statvfs_t) (err error)
   624  //sys	Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
   625  //sysnb	Getgid() (gid int)
   626  //sysnb	Getpid() (pid int)
   627  //sysnb	Getpgid(pid int) (pgid int, err error)
   628  //sysnb	Getpgrp() (pgid int, err error)
   629  //sys	Geteuid() (euid int)
   630  //sys	Getegid() (egid int)
   631  //sys	Getppid() (ppid int)
   632  //sys	Getpriority(which int, who int) (n int, err error)
   633  //sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   634  //sysnb	Getrusage(who int, rusage *Rusage) (err error)
   635  //sysnb	Gettimeofday(tv *Timeval) (err error)
   636  //sysnb	Getuid() (uid int)
   637  //sys	Kill(pid int, signum syscall.Signal) (err error)
   638  //sys	Lchown(path string, uid int, gid int) (err error)
   639  //sys	Link(path string, link string) (err error)
   640  //sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten
   641  //sys	Lstat(path string, stat *Stat_t) (err error)
   642  //sys	Madvise(b []byte, advice int) (err error)
   643  //sys	Mkdir(path string, mode uint32) (err error)
   644  //sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
   645  //sys	Mkfifo(path string, mode uint32) (err error)
   646  //sys	Mkfifoat(dirfd int, path string, mode uint32) (err error)
   647  //sys	Mknod(path string, mode uint32, dev int) (err error)
   648  //sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
   649  //sys	Mlock(b []byte) (err error)
   650  //sys	Mlockall(flags int) (err error)
   651  //sys	Mprotect(b []byte, prot int) (err error)
   652  //sys	Msync(b []byte, flags int) (err error)
   653  //sys	Munlock(b []byte) (err error)
   654  //sys	Munlockall() (err error)
   655  //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   656  //sys	Open(path string, mode int, perm uint32) (fd int, err error)
   657  //sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
   658  //sys	Pathconf(path string, name int) (val int, err error)
   659  //sys	Pause() (err error)
   660  //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
   661  //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
   662  //sys	read(fd int, p []byte) (n int, err error)
   663  //sys	Readlink(path string, buf []byte) (n int, err error)
   664  //sys	Rename(from string, to string) (err error)
   665  //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
   666  //sys	Rmdir(path string) (err error)
   667  //sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
   668  //sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
   669  //sysnb	Setegid(egid int) (err error)
   670  //sysnb	Seteuid(euid int) (err error)
   671  //sysnb	Setgid(gid int) (err error)
   672  //sys	Sethostname(p []byte) (err error)
   673  //sysnb	Setpgid(pid int, pgid int) (err error)
   674  //sys	Setpriority(which int, who int, prio int) (err error)
   675  //sysnb	Setregid(rgid int, egid int) (err error)
   676  //sysnb	Setreuid(ruid int, euid int) (err error)
   677  //sysnb	Setrlimit(which int, lim *Rlimit) (err error)
   678  //sysnb	Setsid() (pid int, err error)
   679  //sysnb	Setuid(uid int) (err error)
   680  //sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
   681  //sys	Stat(path string, stat *Stat_t) (err error)
   682  //sys	Statvfs(path string, vfsstat *Statvfs_t) (err error)
   683  //sys	Symlink(path string, link string) (err error)
   684  //sys	Sync() (err error)
   685  //sys	Sysconf(which int) (n int64, err error)
   686  //sysnb	Times(tms *Tms) (ticks uintptr, err error)
   687  //sys	Truncate(path string, length int64) (err error)
   688  //sys	Fsync(fd int) (err error)
   689  //sys	Ftruncate(fd int, length int64) (err error)
   690  //sys	Umask(mask int) (oldmask int)
   691  //sysnb	Uname(buf *Utsname) (err error)
   692  //sys	Unmount(target string, flags int) (err error) = libc.umount
   693  //sys	Unlink(path string) (err error)
   694  //sys	Unlinkat(dirfd int, path string, flags int) (err error)
   695  //sys	Ustat(dev int, ubuf *Ustat_t) (err error)
   696  //sys	Utime(path string, buf *Utimbuf) (err error)
   697  //sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
   698  //sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
   699  //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
   700  //sys	munmap(addr uintptr, length uintptr) (err error)
   701  //sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
   702  //sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
   703  //sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
   704  //sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
   705  //sys	write(fd int, p []byte) (n int, err error)
   706  //sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
   707  //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
   708  //sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
   709  //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
   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  // Event Ports
   744  
   745  type fileObjCookie struct {
   746  	fobj   *fileObj
   747  	cookie interface{}
   748  }
   749  
   750  // EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
   751  type EventPort struct {
   752  	port  int
   753  	mu    sync.Mutex
   754  	fds   map[uintptr]interface{}
   755  	paths map[string]*fileObjCookie
   756  }
   757  
   758  // PortEvent is an abstraction of the port_event C struct.
   759  // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
   760  // to see if Path or Fd was the event source. The other will be
   761  // uninitialized.
   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  // NewEventPort creates a new EventPort including the
   772  // underlying call to port_create(3c).
   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  //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  	e.fds = nil
   797  	e.paths = nil
   798  	return Close(e.port)
   799  }
   800  
   801  // PathIsWatched checks to see if path is associated with this EventPort.
   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  // FdIsWatched checks to see if fd is associated with this EventPort.
   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  // AssociatePath wraps port_associate(3c) for a filesystem path including
   818  // creating the necessary file_obj from the provided stat information.
   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  // DissociatePath wraps port_dissociate(3c) for a filesystem path.
   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  // AssociateFd wraps calls to port_associate(3c) on file descriptors.
   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  // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
   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  // GetOne wraps port_get(3c) and returns a single PortEvent.
   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  // Pending wraps port_getn(3c) and returns how many events are pending.
   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  // Get wraps port_getn(3c) and fills a slice of PortEvent.
   939  // It will block until either min events have been received
   940  // or the timeout has been exceeded. It will return how many
   941  // events were actually received along with any error information.
   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  	// got will be trustworthy with ETIME, but not any other error.
   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