golang.org/x/sys@v0.9.0/unix/syscall_solaris.go (about)

     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  	if err == nil {
    70  		p[0] = int(pp[0])
    71  		p[1] = int(pp[1])
    72  	}
    73  	return nil
    74  }
    75  
    76  //sysnb	pipe2(p *[2]_C_int, flags int) (err error)
    77  
    78  func Pipe2(p []int, flags int) error {
    79  	if len(p) != 2 {
    80  		return EINVAL
    81  	}
    82  	var pp [2]_C_int
    83  	err := pipe2(&pp, flags)
    84  	if err == nil {
    85  		p[0] = int(pp[0])
    86  		p[1] = int(pp[1])
    87  	}
    88  	return err
    89  }
    90  
    91  func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
    92  	if sa.Port < 0 || sa.Port > 0xFFFF {
    93  		return nil, 0, EINVAL
    94  	}
    95  	sa.raw.Family = AF_INET
    96  	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
    97  	p[0] = byte(sa.Port >> 8)
    98  	p[1] = byte(sa.Port)
    99  	sa.raw.Addr = sa.Addr
   100  	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
   101  }
   102  
   103  func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
   104  	if sa.Port < 0 || sa.Port > 0xFFFF {
   105  		return nil, 0, EINVAL
   106  	}
   107  	sa.raw.Family = AF_INET6
   108  	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
   109  	p[0] = byte(sa.Port >> 8)
   110  	p[1] = byte(sa.Port)
   111  	sa.raw.Scope_id = sa.ZoneId
   112  	sa.raw.Addr = sa.Addr
   113  	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
   114  }
   115  
   116  func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
   117  	name := sa.Name
   118  	n := len(name)
   119  	if n >= len(sa.raw.Path) {
   120  		return nil, 0, EINVAL
   121  	}
   122  	sa.raw.Family = AF_UNIX
   123  	for i := 0; i < n; i++ {
   124  		sa.raw.Path[i] = int8(name[i])
   125  	}
   126  	// length is family (uint16), name, NUL.
   127  	sl := _Socklen(2)
   128  	if n > 0 {
   129  		sl += _Socklen(n) + 1
   130  	}
   131  	if sa.raw.Path[0] == '@' {
   132  		sa.raw.Path[0] = 0
   133  		// Don't count trailing NUL for abstract address.
   134  		sl--
   135  	}
   136  
   137  	return unsafe.Pointer(&sa.raw), sl, nil
   138  }
   139  
   140  //sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
   141  
   142  func Getsockname(fd int) (sa Sockaddr, err error) {
   143  	var rsa RawSockaddrAny
   144  	var len _Socklen = SizeofSockaddrAny
   145  	if err = getsockname(fd, &rsa, &len); err != nil {
   146  		return
   147  	}
   148  	return anyToSockaddr(fd, &rsa)
   149  }
   150  
   151  // GetsockoptString returns the string value of the socket option opt for the
   152  // socket associated with fd at the given socket level.
   153  func GetsockoptString(fd, level, opt int) (string, error) {
   154  	buf := make([]byte, 256)
   155  	vallen := _Socklen(len(buf))
   156  	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
   157  	if err != nil {
   158  		return "", err
   159  	}
   160  	return string(buf[:vallen-1]), nil
   161  }
   162  
   163  const ImplementsGetwd = true
   164  
   165  //sys	Getcwd(buf []byte) (n int, err error)
   166  
   167  func Getwd() (wd string, err error) {
   168  	var buf [PathMax]byte
   169  	// Getcwd will return an error if it failed for any reason.
   170  	_, err = Getcwd(buf[0:])
   171  	if err != nil {
   172  		return "", err
   173  	}
   174  	n := clen(buf[:])
   175  	if n < 1 {
   176  		return "", EINVAL
   177  	}
   178  	return string(buf[:n]), nil
   179  }
   180  
   181  /*
   182   * Wrapped
   183   */
   184  
   185  //sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
   186  //sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
   187  
   188  func Getgroups() (gids []int, err error) {
   189  	n, err := getgroups(0, nil)
   190  	// Check for error and sanity check group count. Newer versions of
   191  	// Solaris allow up to 1024 (NGROUPS_MAX).
   192  	if n < 0 || n > 1024 {
   193  		if err != nil {
   194  			return nil, err
   195  		}
   196  		return nil, EINVAL
   197  	} else if n == 0 {
   198  		return nil, nil
   199  	}
   200  
   201  	a := make([]_Gid_t, n)
   202  	n, err = getgroups(n, &a[0])
   203  	if n == -1 {
   204  		return nil, err
   205  	}
   206  	gids = make([]int, n)
   207  	for i, v := range a[0:n] {
   208  		gids[i] = int(v)
   209  	}
   210  	return
   211  }
   212  
   213  func Setgroups(gids []int) (err error) {
   214  	if len(gids) == 0 {
   215  		return setgroups(0, nil)
   216  	}
   217  
   218  	a := make([]_Gid_t, len(gids))
   219  	for i, v := range gids {
   220  		a[i] = _Gid_t(v)
   221  	}
   222  	return setgroups(len(a), &a[0])
   223  }
   224  
   225  // ReadDirent reads directory entries from fd and writes them into buf.
   226  func ReadDirent(fd int, buf []byte) (n int, err error) {
   227  	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
   228  	// TODO(rsc): Can we use a single global basep for all calls?
   229  	return Getdents(fd, buf, new(uintptr))
   230  }
   231  
   232  // Wait status is 7 bits at bottom, either 0 (exited),
   233  // 0x7F (stopped), or a signal number that caused an exit.
   234  // The 0x80 bit is whether there was a core dump.
   235  // An extra number (exit code, signal causing a stop)
   236  // is in the high bits.
   237  
   238  type WaitStatus uint32
   239  
   240  const (
   241  	mask  = 0x7F
   242  	core  = 0x80
   243  	shift = 8
   244  
   245  	exited  = 0
   246  	stopped = 0x7F
   247  )
   248  
   249  func (w WaitStatus) Exited() bool { return w&mask == exited }
   250  
   251  func (w WaitStatus) ExitStatus() int {
   252  	if w&mask != exited {
   253  		return -1
   254  	}
   255  	return int(w >> shift)
   256  }
   257  
   258  func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
   259  
   260  func (w WaitStatus) Signal() syscall.Signal {
   261  	sig := syscall.Signal(w & mask)
   262  	if sig == stopped || sig == 0 {
   263  		return -1
   264  	}
   265  	return sig
   266  }
   267  
   268  func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
   269  
   270  func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
   271  
   272  func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
   273  
   274  func (w WaitStatus) StopSignal() syscall.Signal {
   275  	if !w.Stopped() {
   276  		return -1
   277  	}
   278  	return syscall.Signal(w>>shift) & 0xFF
   279  }
   280  
   281  func (w WaitStatus) TrapCause() int { return -1 }
   282  
   283  //sys	wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
   284  
   285  func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
   286  	var status _C_int
   287  	rpid, err := wait4(int32(pid), &status, options, rusage)
   288  	wpid := int(rpid)
   289  	if wpid == -1 {
   290  		return wpid, err
   291  	}
   292  	if wstatus != nil {
   293  		*wstatus = WaitStatus(status)
   294  	}
   295  	return wpid, nil
   296  }
   297  
   298  //sys	gethostname(buf []byte) (n int, err error)
   299  
   300  func Gethostname() (name string, err error) {
   301  	var buf [MaxHostNameLen]byte
   302  	n, err := gethostname(buf[:])
   303  	if n != 0 {
   304  		return "", err
   305  	}
   306  	n = clen(buf[:])
   307  	if n < 1 {
   308  		return "", EFAULT
   309  	}
   310  	return string(buf[:n]), nil
   311  }
   312  
   313  //sys	utimes(path string, times *[2]Timeval) (err error)
   314  
   315  func Utimes(path string, tv []Timeval) (err error) {
   316  	if tv == nil {
   317  		return utimes(path, nil)
   318  	}
   319  	if len(tv) != 2 {
   320  		return EINVAL
   321  	}
   322  	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   323  }
   324  
   325  //sys	utimensat(fd int, path string, times *[2]Timespec, flag int) (err error)
   326  
   327  func UtimesNano(path string, ts []Timespec) error {
   328  	if ts == nil {
   329  		return utimensat(AT_FDCWD, path, nil, 0)
   330  	}
   331  	if len(ts) != 2 {
   332  		return EINVAL
   333  	}
   334  	return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
   335  }
   336  
   337  func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
   338  	if ts == nil {
   339  		return utimensat(dirfd, path, nil, flags)
   340  	}
   341  	if len(ts) != 2 {
   342  		return EINVAL
   343  	}
   344  	return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
   345  }
   346  
   347  //sys	fcntl(fd int, cmd int, arg int) (val int, err error)
   348  
   349  // FcntlInt performs a fcntl syscall on fd with the provided command and argument.
   350  func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
   351  	valptr, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
   352  	var err error
   353  	if errno != 0 {
   354  		err = errno
   355  	}
   356  	return int(valptr), err
   357  }
   358  
   359  // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
   360  func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
   361  	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
   362  	if e1 != 0 {
   363  		return e1
   364  	}
   365  	return nil
   366  }
   367  
   368  //sys	futimesat(fildes int, path *byte, times *[2]Timeval) (err error)
   369  
   370  func Futimesat(dirfd int, path string, tv []Timeval) error {
   371  	pathp, err := BytePtrFromString(path)
   372  	if err != nil {
   373  		return err
   374  	}
   375  	if tv == nil {
   376  		return futimesat(dirfd, pathp, nil)
   377  	}
   378  	if len(tv) != 2 {
   379  		return EINVAL
   380  	}
   381  	return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   382  }
   383  
   384  // Solaris doesn't have an futimes function because it allows NULL to be
   385  // specified as the path for futimesat. However, Go doesn't like
   386  // NULL-style string interfaces, so this simple wrapper is provided.
   387  func Futimes(fd int, tv []Timeval) error {
   388  	if tv == nil {
   389  		return futimesat(fd, nil, nil)
   390  	}
   391  	if len(tv) != 2 {
   392  		return EINVAL
   393  	}
   394  	return futimesat(fd, nil, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
   395  }
   396  
   397  func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
   398  	switch rsa.Addr.Family {
   399  	case AF_UNIX:
   400  		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
   401  		sa := new(SockaddrUnix)
   402  		// Assume path ends at NUL.
   403  		// This is not technically the Solaris semantics for
   404  		// abstract Unix domain sockets -- they are supposed
   405  		// to be uninterpreted fixed-size binary blobs -- but
   406  		// everyone uses this convention.
   407  		n := 0
   408  		for n < len(pp.Path) && pp.Path[n] != 0 {
   409  			n++
   410  		}
   411  		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
   412  		return sa, nil
   413  
   414  	case AF_INET:
   415  		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
   416  		sa := new(SockaddrInet4)
   417  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   418  		sa.Port = int(p[0])<<8 + int(p[1])
   419  		sa.Addr = pp.Addr
   420  		return sa, nil
   421  
   422  	case AF_INET6:
   423  		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
   424  		sa := new(SockaddrInet6)
   425  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   426  		sa.Port = int(p[0])<<8 + int(p[1])
   427  		sa.ZoneId = pp.Scope_id
   428  		sa.Addr = pp.Addr
   429  		return sa, nil
   430  	}
   431  	return nil, EAFNOSUPPORT
   432  }
   433  
   434  //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
   435  
   436  func Accept(fd int) (nfd int, sa Sockaddr, err error) {
   437  	var rsa RawSockaddrAny
   438  	var len _Socklen = SizeofSockaddrAny
   439  	nfd, err = accept(fd, &rsa, &len)
   440  	if nfd == -1 {
   441  		return
   442  	}
   443  	sa, err = anyToSockaddr(fd, &rsa)
   444  	if err != nil {
   445  		Close(nfd)
   446  		nfd = 0
   447  	}
   448  	return
   449  }
   450  
   451  //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
   452  
   453  func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
   454  	var msg Msghdr
   455  	msg.Name = (*byte)(unsafe.Pointer(rsa))
   456  	msg.Namelen = uint32(SizeofSockaddrAny)
   457  	var dummy byte
   458  	if len(oob) > 0 {
   459  		// receive at least one normal byte
   460  		if emptyIovecs(iov) {
   461  			var iova [1]Iovec
   462  			iova[0].Base = &dummy
   463  			iova[0].SetLen(1)
   464  			iov = iova[:]
   465  		}
   466  		msg.Accrightslen = int32(len(oob))
   467  	}
   468  	if len(iov) > 0 {
   469  		msg.Iov = &iov[0]
   470  		msg.SetIovlen(len(iov))
   471  	}
   472  	if n, err = recvmsg(fd, &msg, flags); n == -1 {
   473  		return
   474  	}
   475  	oobn = int(msg.Accrightslen)
   476  	return
   477  }
   478  
   479  //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
   480  
   481  func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
   482  	var msg Msghdr
   483  	msg.Name = (*byte)(unsafe.Pointer(ptr))
   484  	msg.Namelen = uint32(salen)
   485  	var dummy byte
   486  	var empty bool
   487  	if len(oob) > 0 {
   488  		// send at least one normal byte
   489  		empty = emptyIovecs(iov)
   490  		if empty {
   491  			var iova [1]Iovec
   492  			iova[0].Base = &dummy
   493  			iova[0].SetLen(1)
   494  			iov = iova[:]
   495  		}
   496  		msg.Accrightslen = int32(len(oob))
   497  	}
   498  	if len(iov) > 0 {
   499  		msg.Iov = &iov[0]
   500  		msg.SetIovlen(len(iov))
   501  	}
   502  	if n, err = sendmsg(fd, &msg, flags); err != nil {
   503  		return 0, err
   504  	}
   505  	if len(oob) > 0 && empty {
   506  		n = 0
   507  	}
   508  	return n, nil
   509  }
   510  
   511  //sys	acct(path *byte) (err error)
   512  
   513  func Acct(path string) (err error) {
   514  	if len(path) == 0 {
   515  		// Assume caller wants to disable accounting.
   516  		return acct(nil)
   517  	}
   518  
   519  	pathp, err := BytePtrFromString(path)
   520  	if err != nil {
   521  		return err
   522  	}
   523  	return acct(pathp)
   524  }
   525  
   526  //sys	__makedev(version int, major uint, minor uint) (val uint64)
   527  
   528  func Mkdev(major, minor uint32) uint64 {
   529  	return __makedev(NEWDEV, uint(major), uint(minor))
   530  }
   531  
   532  //sys	__major(version int, dev uint64) (val uint)
   533  
   534  func Major(dev uint64) uint32 {
   535  	return uint32(__major(NEWDEV, dev))
   536  }
   537  
   538  //sys	__minor(version int, dev uint64) (val uint)
   539  
   540  func Minor(dev uint64) uint32 {
   541  	return uint32(__minor(NEWDEV, dev))
   542  }
   543  
   544  /*
   545   * Expose the ioctl function
   546   */
   547  
   548  //sys	ioctlRet(fd int, req int, arg uintptr) (ret int, err error) = libc.ioctl
   549  //sys	ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) = libc.ioctl
   550  
   551  func ioctl(fd int, req int, arg uintptr) (err error) {
   552  	_, err = ioctlRet(fd, req, arg)
   553  	return err
   554  }
   555  
   556  func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
   557  	_, err = ioctlPtrRet(fd, req, arg)
   558  	return err
   559  }
   560  
   561  func IoctlSetTermio(fd int, req int, value *Termio) error {
   562  	return ioctlPtr(fd, req, unsafe.Pointer(value))
   563  }
   564  
   565  func IoctlGetTermio(fd int, req int) (*Termio, error) {
   566  	var value Termio
   567  	err := ioctlPtr(fd, req, unsafe.Pointer(&value))
   568  	return &value, err
   569  }
   570  
   571  //sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)
   572  
   573  func Poll(fds []PollFd, timeout int) (n int, err error) {
   574  	if len(fds) == 0 {
   575  		return poll(nil, 0, timeout)
   576  	}
   577  	return poll(&fds[0], len(fds), timeout)
   578  }
   579  
   580  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
   581  	if raceenabled {
   582  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   583  	}
   584  	return sendfile(outfd, infd, offset, count)
   585  }
   586  
   587  /*
   588   * Exposed directly
   589   */
   590  //sys	Access(path string, mode uint32) (err error)
   591  //sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
   592  //sys	Chdir(path string) (err error)
   593  //sys	Chmod(path string, mode uint32) (err error)
   594  //sys	Chown(path string, uid int, gid int) (err error)
   595  //sys	Chroot(path string) (err error)
   596  //sys	ClockGettime(clockid int32, time *Timespec) (err error)
   597  //sys	Close(fd int) (err error)
   598  //sys	Creat(path string, mode uint32) (fd int, err error)
   599  //sys	Dup(fd int) (nfd int, err error)
   600  //sys	Dup2(oldfd int, newfd int) (err error)
   601  //sys	Exit(code int)
   602  //sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
   603  //sys	Fchdir(fd int) (err error)
   604  //sys	Fchmod(fd int, mode uint32) (err error)
   605  //sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
   606  //sys	Fchown(fd int, uid int, gid int) (err error)
   607  //sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
   608  //sys	Fdatasync(fd int) (err error)
   609  //sys	Flock(fd int, how int) (err error)
   610  //sys	Fpathconf(fd int, name int) (val int, err error)
   611  //sys	Fstat(fd int, stat *Stat_t) (err error)
   612  //sys	Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
   613  //sys	Fstatvfs(fd int, vfsstat *Statvfs_t) (err error)
   614  //sys	Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
   615  //sysnb	Getgid() (gid int)
   616  //sysnb	Getpid() (pid int)
   617  //sysnb	Getpgid(pid int) (pgid int, err error)
   618  //sysnb	Getpgrp() (pgid int, err error)
   619  //sys	Geteuid() (euid int)
   620  //sys	Getegid() (egid int)
   621  //sys	Getppid() (ppid int)
   622  //sys	Getpriority(which int, who int) (n int, err error)
   623  //sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   624  //sysnb	Getrusage(who int, rusage *Rusage) (err error)
   625  //sysnb	Getsid(pid int) (sid int, err error)
   626  //sysnb	Gettimeofday(tv *Timeval) (err error)
   627  //sysnb	Getuid() (uid int)
   628  //sys	Kill(pid int, signum syscall.Signal) (err error)
   629  //sys	Lchown(path string, uid int, gid int) (err error)
   630  //sys	Link(path string, link string) (err error)
   631  //sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten
   632  //sys	Lstat(path string, stat *Stat_t) (err error)
   633  //sys	Madvise(b []byte, advice int) (err error)
   634  //sys	Mkdir(path string, mode uint32) (err error)
   635  //sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
   636  //sys	Mkfifo(path string, mode uint32) (err error)
   637  //sys	Mkfifoat(dirfd int, path string, mode uint32) (err error)
   638  //sys	Mknod(path string, mode uint32, dev int) (err error)
   639  //sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
   640  //sys	Mlock(b []byte) (err error)
   641  //sys	Mlockall(flags int) (err error)
   642  //sys	Mprotect(b []byte, prot int) (err error)
   643  //sys	Msync(b []byte, flags int) (err error)
   644  //sys	Munlock(b []byte) (err error)
   645  //sys	Munlockall() (err error)
   646  //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   647  //sys	Open(path string, mode int, perm uint32) (fd int, err error)
   648  //sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
   649  //sys	Pathconf(path string, name int) (val int, err error)
   650  //sys	Pause() (err error)
   651  //sys	pread(fd int, p []byte, offset int64) (n int, err error)
   652  //sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
   653  //sys	read(fd int, p []byte) (n int, err error)
   654  //sys	Readlink(path string, buf []byte) (n int, err error)
   655  //sys	Rename(from string, to string) (err error)
   656  //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
   657  //sys	Rmdir(path string) (err error)
   658  //sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
   659  //sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
   660  //sysnb	Setegid(egid int) (err error)
   661  //sysnb	Seteuid(euid int) (err error)
   662  //sysnb	Setgid(gid int) (err error)
   663  //sys	Sethostname(p []byte) (err error)
   664  //sysnb	Setpgid(pid int, pgid int) (err error)
   665  //sys	Setpriority(which int, who int, prio int) (err error)
   666  //sysnb	Setregid(rgid int, egid int) (err error)
   667  //sysnb	Setreuid(ruid int, euid int) (err error)
   668  //sysnb	Setsid() (pid int, err error)
   669  //sysnb	Setuid(uid int) (err error)
   670  //sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
   671  //sys	Stat(path string, stat *Stat_t) (err error)
   672  //sys	Statvfs(path string, vfsstat *Statvfs_t) (err error)
   673  //sys	Symlink(path string, link string) (err error)
   674  //sys	Sync() (err error)
   675  //sys	Sysconf(which int) (n int64, err error)
   676  //sysnb	Times(tms *Tms) (ticks uintptr, err error)
   677  //sys	Truncate(path string, length int64) (err error)
   678  //sys	Fsync(fd int) (err error)
   679  //sys	Ftruncate(fd int, length int64) (err error)
   680  //sys	Umask(mask int) (oldmask int)
   681  //sysnb	Uname(buf *Utsname) (err error)
   682  //sys	Unmount(target string, flags int) (err error) = libc.umount
   683  //sys	Unlink(path string) (err error)
   684  //sys	Unlinkat(dirfd int, path string, flags int) (err error)
   685  //sys	Ustat(dev int, ubuf *Ustat_t) (err error)
   686  //sys	Utime(path string, buf *Utimbuf) (err error)
   687  //sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
   688  //sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
   689  //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
   690  //sys	munmap(addr uintptr, length uintptr) (err error)
   691  //sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
   692  //sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
   693  //sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
   694  //sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
   695  //sys	write(fd int, p []byte) (n int, err error)
   696  //sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
   697  //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
   698  //sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
   699  //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
   700  
   701  func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
   702  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   703  	n = int(r0)
   704  	if e1 != 0 {
   705  		err = e1
   706  	}
   707  	return
   708  }
   709  
   710  func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
   711  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   712  	n = int(r0)
   713  	if e1 != 0 {
   714  		err = e1
   715  	}
   716  	return
   717  }
   718  
   719  var mapper = &mmapper{
   720  	active: make(map[*byte][]byte),
   721  	mmap:   mmap,
   722  	munmap: munmap,
   723  }
   724  
   725  func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
   726  	return mapper.Mmap(fd, offset, length, prot, flags)
   727  }
   728  
   729  func Munmap(b []byte) (err error) {
   730  	return mapper.Munmap(b)
   731  }
   732  
   733  // Event Ports
   734  
   735  type fileObjCookie struct {
   736  	fobj   *fileObj
   737  	cookie interface{}
   738  }
   739  
   740  // EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
   741  type EventPort struct {
   742  	port  int
   743  	mu    sync.Mutex
   744  	fds   map[uintptr]*fileObjCookie
   745  	paths map[string]*fileObjCookie
   746  	// The user cookie presents an interesting challenge from a memory management perspective.
   747  	// There are two paths by which we can discover that it is no longer in use:
   748  	// 1. The user calls port_dissociate before any events fire
   749  	// 2. An event fires and we return it to the user
   750  	// The tricky situation is if the event has fired in the kernel but
   751  	// the user hasn't requested/received it yet.
   752  	// If the user wants to port_dissociate before the event has been processed,
   753  	// we should handle things gracefully. To do so, we need to keep an extra
   754  	// reference to the cookie around until the event is processed
   755  	// thus the otherwise seemingly extraneous "cookies" map
   756  	// The key of this map is a pointer to the corresponding fCookie
   757  	cookies map[*fileObjCookie]struct{}
   758  }
   759  
   760  // PortEvent is an abstraction of the port_event C struct.
   761  // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
   762  // to see if Path or Fd was the event source. The other will be
   763  // uninitialized.
   764  type PortEvent struct {
   765  	Cookie interface{}
   766  	Events int32
   767  	Fd     uintptr
   768  	Path   string
   769  	Source uint16
   770  	fobj   *fileObj
   771  }
   772  
   773  // NewEventPort creates a new EventPort including the
   774  // underlying call to port_create(3c).
   775  func NewEventPort() (*EventPort, error) {
   776  	port, err := port_create()
   777  	if err != nil {
   778  		return nil, err
   779  	}
   780  	e := &EventPort{
   781  		port:    port,
   782  		fds:     make(map[uintptr]*fileObjCookie),
   783  		paths:   make(map[string]*fileObjCookie),
   784  		cookies: make(map[*fileObjCookie]struct{}),
   785  	}
   786  	return e, nil
   787  }
   788  
   789  //sys	port_create() (n int, err error)
   790  //sys	port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
   791  //sys	port_dissociate(port int, source int, object uintptr) (n int, err error)
   792  //sys	port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
   793  //sys	port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
   794  
   795  // Close closes the event port.
   796  func (e *EventPort) Close() error {
   797  	e.mu.Lock()
   798  	defer e.mu.Unlock()
   799  	err := Close(e.port)
   800  	if err != nil {
   801  		return err
   802  	}
   803  	e.fds = nil
   804  	e.paths = nil
   805  	e.cookies = nil
   806  	return nil
   807  }
   808  
   809  // PathIsWatched checks to see if path is associated with this EventPort.
   810  func (e *EventPort) PathIsWatched(path string) bool {
   811  	e.mu.Lock()
   812  	defer e.mu.Unlock()
   813  	_, found := e.paths[path]
   814  	return found
   815  }
   816  
   817  // FdIsWatched checks to see if fd is associated with this EventPort.
   818  func (e *EventPort) FdIsWatched(fd uintptr) bool {
   819  	e.mu.Lock()
   820  	defer e.mu.Unlock()
   821  	_, found := e.fds[fd]
   822  	return found
   823  }
   824  
   825  // AssociatePath wraps port_associate(3c) for a filesystem path including
   826  // creating the necessary file_obj from the provided stat information.
   827  func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
   828  	e.mu.Lock()
   829  	defer e.mu.Unlock()
   830  	if _, found := e.paths[path]; found {
   831  		return fmt.Errorf("%v is already associated with this Event Port", path)
   832  	}
   833  	fCookie, err := createFileObjCookie(path, stat, cookie)
   834  	if err != nil {
   835  		return err
   836  	}
   837  	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie)))
   838  	if err != nil {
   839  		return err
   840  	}
   841  	e.paths[path] = fCookie
   842  	e.cookies[fCookie] = struct{}{}
   843  	return nil
   844  }
   845  
   846  // DissociatePath wraps port_dissociate(3c) for a filesystem path.
   847  func (e *EventPort) DissociatePath(path string) error {
   848  	e.mu.Lock()
   849  	defer e.mu.Unlock()
   850  	f, ok := e.paths[path]
   851  	if !ok {
   852  		return fmt.Errorf("%v is not associated with this Event Port", path)
   853  	}
   854  	_, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
   855  	// If the path is no longer associated with this event port (ENOENT)
   856  	// we should delete it from our map. We can still return ENOENT to the caller.
   857  	// But we need to save the cookie
   858  	if err != nil && err != ENOENT {
   859  		return err
   860  	}
   861  	if err == nil {
   862  		// dissociate was successful, safe to delete the cookie
   863  		fCookie := e.paths[path]
   864  		delete(e.cookies, fCookie)
   865  	}
   866  	delete(e.paths, path)
   867  	return err
   868  }
   869  
   870  // AssociateFd wraps calls to port_associate(3c) on file descriptors.
   871  func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
   872  	e.mu.Lock()
   873  	defer e.mu.Unlock()
   874  	if _, found := e.fds[fd]; found {
   875  		return fmt.Errorf("%v is already associated with this Event Port", fd)
   876  	}
   877  	fCookie, err := createFileObjCookie("", nil, cookie)
   878  	if err != nil {
   879  		return err
   880  	}
   881  	_, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie)))
   882  	if err != nil {
   883  		return err
   884  	}
   885  	e.fds[fd] = fCookie
   886  	e.cookies[fCookie] = struct{}{}
   887  	return nil
   888  }
   889  
   890  // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
   891  func (e *EventPort) DissociateFd(fd uintptr) error {
   892  	e.mu.Lock()
   893  	defer e.mu.Unlock()
   894  	_, ok := e.fds[fd]
   895  	if !ok {
   896  		return fmt.Errorf("%v is not associated with this Event Port", fd)
   897  	}
   898  	_, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
   899  	if err != nil && err != ENOENT {
   900  		return err
   901  	}
   902  	if err == nil {
   903  		// dissociate was successful, safe to delete the cookie
   904  		fCookie := e.fds[fd]
   905  		delete(e.cookies, fCookie)
   906  	}
   907  	delete(e.fds, fd)
   908  	return err
   909  }
   910  
   911  func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) {
   912  	fCookie := new(fileObjCookie)
   913  	fCookie.cookie = cookie
   914  	if name != "" && stat != nil {
   915  		fCookie.fobj = new(fileObj)
   916  		bs, err := ByteSliceFromString(name)
   917  		if err != nil {
   918  			return nil, err
   919  		}
   920  		fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
   921  		s := stat.Sys().(*syscall.Stat_t)
   922  		fCookie.fobj.Atim.Sec = s.Atim.Sec
   923  		fCookie.fobj.Atim.Nsec = s.Atim.Nsec
   924  		fCookie.fobj.Mtim.Sec = s.Mtim.Sec
   925  		fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec
   926  		fCookie.fobj.Ctim.Sec = s.Ctim.Sec
   927  		fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec
   928  	}
   929  	return fCookie, nil
   930  }
   931  
   932  // GetOne wraps port_get(3c) and returns a single PortEvent.
   933  func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
   934  	pe := new(portEvent)
   935  	_, err := port_get(e.port, pe, t)
   936  	if err != nil {
   937  		return nil, err
   938  	}
   939  	p := new(PortEvent)
   940  	e.mu.Lock()
   941  	defer e.mu.Unlock()
   942  	err = e.peIntToExt(pe, p)
   943  	if err != nil {
   944  		return nil, err
   945  	}
   946  	return p, nil
   947  }
   948  
   949  // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
   950  // NOTE: Always call this function while holding the e.mu mutex
   951  func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error {
   952  	if e.cookies == nil {
   953  		return fmt.Errorf("this EventPort is already closed")
   954  	}
   955  	peExt.Events = peInt.Events
   956  	peExt.Source = peInt.Source
   957  	fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User))
   958  	_, found := e.cookies[fCookie]
   959  
   960  	if !found {
   961  		panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254")
   962  	}
   963  	peExt.Cookie = fCookie.cookie
   964  	delete(e.cookies, fCookie)
   965  
   966  	switch peInt.Source {
   967  	case PORT_SOURCE_FD:
   968  		peExt.Fd = uintptr(peInt.Object)
   969  		// Only remove the fds entry if it exists and this cookie matches
   970  		if fobj, ok := e.fds[peExt.Fd]; ok {
   971  			if fobj == fCookie {
   972  				delete(e.fds, peExt.Fd)
   973  			}
   974  		}
   975  	case PORT_SOURCE_FILE:
   976  		peExt.fobj = fCookie.fobj
   977  		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
   978  		// Only remove the paths entry if it exists and this cookie matches
   979  		if fobj, ok := e.paths[peExt.Path]; ok {
   980  			if fobj == fCookie {
   981  				delete(e.paths, peExt.Path)
   982  			}
   983  		}
   984  	}
   985  	return nil
   986  }
   987  
   988  // Pending wraps port_getn(3c) and returns how many events are pending.
   989  func (e *EventPort) Pending() (int, error) {
   990  	var n uint32 = 0
   991  	_, err := port_getn(e.port, nil, 0, &n, nil)
   992  	return int(n), err
   993  }
   994  
   995  // Get wraps port_getn(3c) and fills a slice of PortEvent.
   996  // It will block until either min events have been received
   997  // or the timeout has been exceeded. It will return how many
   998  // events were actually received along with any error information.
   999  func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
  1000  	if min == 0 {
  1001  		return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
  1002  	}
  1003  	if len(s) < min {
  1004  		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
  1005  	}
  1006  	got := uint32(min)
  1007  	max := uint32(len(s))
  1008  	var err error
  1009  	ps := make([]portEvent, max)
  1010  	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
  1011  	// got will be trustworthy with ETIME, but not any other error.
  1012  	if err != nil && err != ETIME {
  1013  		return 0, err
  1014  	}
  1015  	e.mu.Lock()
  1016  	defer e.mu.Unlock()
  1017  	valid := 0
  1018  	for i := 0; i < int(got); i++ {
  1019  		err2 := e.peIntToExt(&ps[i], &s[i])
  1020  		if err2 != nil {
  1021  			if valid == 0 && err == nil {
  1022  				// If err2 is the only error and there are no valid events
  1023  				// to return, return it to the caller.
  1024  				err = err2
  1025  			}
  1026  			break
  1027  		}
  1028  		valid = i + 1
  1029  	}
  1030  	return valid, err
  1031  }
  1032  
  1033  //sys	putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error)
  1034  
  1035  func Putmsg(fd int, cl []byte, data []byte, flags int) (err error) {
  1036  	var clp, datap *strbuf
  1037  	if len(cl) > 0 {
  1038  		clp = &strbuf{
  1039  			Len: int32(len(cl)),
  1040  			Buf: (*int8)(unsafe.Pointer(&cl[0])),
  1041  		}
  1042  	}
  1043  	if len(data) > 0 {
  1044  		datap = &strbuf{
  1045  			Len: int32(len(data)),
  1046  			Buf: (*int8)(unsafe.Pointer(&data[0])),
  1047  		}
  1048  	}
  1049  	return putmsg(fd, clp, datap, flags)
  1050  }
  1051  
  1052  //sys	getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error)
  1053  
  1054  func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags int, err error) {
  1055  	var clp, datap *strbuf
  1056  	if len(cl) > 0 {
  1057  		clp = &strbuf{
  1058  			Maxlen: int32(len(cl)),
  1059  			Buf:    (*int8)(unsafe.Pointer(&cl[0])),
  1060  		}
  1061  	}
  1062  	if len(data) > 0 {
  1063  		datap = &strbuf{
  1064  			Maxlen: int32(len(data)),
  1065  			Buf:    (*int8)(unsafe.Pointer(&data[0])),
  1066  		}
  1067  	}
  1068  
  1069  	if err = getmsg(fd, clp, datap, &flags); err != nil {
  1070  		return nil, nil, 0, err
  1071  	}
  1072  
  1073  	if len(cl) > 0 {
  1074  		retCl = cl[:clp.Len]
  1075  	}
  1076  	if len(data) > 0 {
  1077  		retData = data[:datap.Len]
  1078  	}
  1079  	return retCl, retData, flags, nil
  1080  }
  1081  
  1082  func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
  1083  	return ioctlRet(fd, req, uintptr(arg))
  1084  }
  1085  
  1086  func IoctlSetString(fd int, req int, val string) error {
  1087  	bs := make([]byte, len(val)+1)
  1088  	copy(bs[:len(bs)-1], val)
  1089  	err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
  1090  	runtime.KeepAlive(&bs[0])
  1091  	return err
  1092  }
  1093  
  1094  // Lifreq Helpers
  1095  
  1096  func (l *Lifreq) SetName(name string) error {
  1097  	if len(name) >= len(l.Name) {
  1098  		return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1)
  1099  	}
  1100  	for i := range name {
  1101  		l.Name[i] = int8(name[i])
  1102  	}
  1103  	return nil
  1104  }
  1105  
  1106  func (l *Lifreq) SetLifruInt(d int) {
  1107  	*(*int)(unsafe.Pointer(&l.Lifru[0])) = d
  1108  }
  1109  
  1110  func (l *Lifreq) GetLifruInt() int {
  1111  	return *(*int)(unsafe.Pointer(&l.Lifru[0]))
  1112  }
  1113  
  1114  func (l *Lifreq) SetLifruUint(d uint) {
  1115  	*(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
  1116  }
  1117  
  1118  func (l *Lifreq) GetLifruUint() uint {
  1119  	return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
  1120  }
  1121  
  1122  func IoctlLifreq(fd int, req int, l *Lifreq) error {
  1123  	return ioctlPtr(fd, req, unsafe.Pointer(l))
  1124  }
  1125  
  1126  // Strioctl Helpers
  1127  
  1128  func (s *Strioctl) SetInt(i int) {
  1129  	s.Len = int32(unsafe.Sizeof(i))
  1130  	s.Dp = (*int8)(unsafe.Pointer(&i))
  1131  }
  1132  
  1133  func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
  1134  	return ioctlPtrRet(fd, req, unsafe.Pointer(s))
  1135  }