github.com/Kalvelign/golang-windows-sys-lib@v0.0.0-20221121121202-63da651435e1/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  		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
   412  		sa.Name = string(bytes)
   413  		return sa, nil
   414  
   415  	case AF_INET:
   416  		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
   417  		sa := new(SockaddrInet4)
   418  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   419  		sa.Port = int(p[0])<<8 + int(p[1])
   420  		sa.Addr = pp.Addr
   421  		return sa, nil
   422  
   423  	case AF_INET6:
   424  		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
   425  		sa := new(SockaddrInet6)
   426  		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
   427  		sa.Port = int(p[0])<<8 + int(p[1])
   428  		sa.ZoneId = pp.Scope_id
   429  		sa.Addr = pp.Addr
   430  		return sa, nil
   431  	}
   432  	return nil, EAFNOSUPPORT
   433  }
   434  
   435  //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
   436  
   437  func Accept(fd int) (nfd int, sa Sockaddr, err error) {
   438  	var rsa RawSockaddrAny
   439  	var len _Socklen = SizeofSockaddrAny
   440  	nfd, err = accept(fd, &rsa, &len)
   441  	if nfd == -1 {
   442  		return
   443  	}
   444  	sa, err = anyToSockaddr(fd, &rsa)
   445  	if err != nil {
   446  		Close(nfd)
   447  		nfd = 0
   448  	}
   449  	return
   450  }
   451  
   452  //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
   453  
   454  func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
   455  	var msg Msghdr
   456  	msg.Name = (*byte)(unsafe.Pointer(rsa))
   457  	msg.Namelen = uint32(SizeofSockaddrAny)
   458  	var dummy byte
   459  	if len(oob) > 0 {
   460  		// receive at least one normal byte
   461  		if emptyIovecs(iov) {
   462  			var iova [1]Iovec
   463  			iova[0].Base = &dummy
   464  			iova[0].SetLen(1)
   465  			iov = iova[:]
   466  		}
   467  		msg.Accrightslen = int32(len(oob))
   468  	}
   469  	if len(iov) > 0 {
   470  		msg.Iov = &iov[0]
   471  		msg.SetIovlen(len(iov))
   472  	}
   473  	if n, err = recvmsg(fd, &msg, flags); n == -1 {
   474  		return
   475  	}
   476  	oobn = int(msg.Accrightslen)
   477  	return
   478  }
   479  
   480  //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
   481  
   482  func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
   483  	var msg Msghdr
   484  	msg.Name = (*byte)(unsafe.Pointer(ptr))
   485  	msg.Namelen = uint32(salen)
   486  	var dummy byte
   487  	var empty bool
   488  	if len(oob) > 0 {
   489  		// send at least one normal byte
   490  		empty = emptyIovecs(iov)
   491  		if empty {
   492  			var iova [1]Iovec
   493  			iova[0].Base = &dummy
   494  			iova[0].SetLen(1)
   495  			iov = iova[:]
   496  		}
   497  		msg.Accrightslen = int32(len(oob))
   498  	}
   499  	if len(iov) > 0 {
   500  		msg.Iov = &iov[0]
   501  		msg.SetIovlen(len(iov))
   502  	}
   503  	if n, err = sendmsg(fd, &msg, flags); err != nil {
   504  		return 0, err
   505  	}
   506  	if len(oob) > 0 && empty {
   507  		n = 0
   508  	}
   509  	return n, nil
   510  }
   511  
   512  //sys	acct(path *byte) (err error)
   513  
   514  func Acct(path string) (err error) {
   515  	if len(path) == 0 {
   516  		// Assume caller wants to disable accounting.
   517  		return acct(nil)
   518  	}
   519  
   520  	pathp, err := BytePtrFromString(path)
   521  	if err != nil {
   522  		return err
   523  	}
   524  	return acct(pathp)
   525  }
   526  
   527  //sys	__makedev(version int, major uint, minor uint) (val uint64)
   528  
   529  func Mkdev(major, minor uint32) uint64 {
   530  	return __makedev(NEWDEV, uint(major), uint(minor))
   531  }
   532  
   533  //sys	__major(version int, dev uint64) (val uint)
   534  
   535  func Major(dev uint64) uint32 {
   536  	return uint32(__major(NEWDEV, dev))
   537  }
   538  
   539  //sys	__minor(version int, dev uint64) (val uint)
   540  
   541  func Minor(dev uint64) uint32 {
   542  	return uint32(__minor(NEWDEV, dev))
   543  }
   544  
   545  /*
   546   * Expose the ioctl function
   547   */
   548  
   549  //sys	ioctlRet(fd int, req uint, arg uintptr) (ret int, err error) = libc.ioctl
   550  
   551  func ioctl(fd int, req uint, arg uintptr) (err error) {
   552  	_, err = ioctlRet(fd, req, arg)
   553  	return err
   554  }
   555  
   556  func IoctlSetTermio(fd int, req uint, value *Termio) error {
   557  	err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
   558  	runtime.KeepAlive(value)
   559  	return err
   560  }
   561  
   562  func IoctlGetTermio(fd int, req uint) (*Termio, error) {
   563  	var value Termio
   564  	err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
   565  	return &value, err
   566  }
   567  
   568  //sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)
   569  
   570  func Poll(fds []PollFd, timeout int) (n int, err error) {
   571  	if len(fds) == 0 {
   572  		return poll(nil, 0, timeout)
   573  	}
   574  	return poll(&fds[0], len(fds), timeout)
   575  }
   576  
   577  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
   578  	if raceenabled {
   579  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   580  	}
   581  	return sendfile(outfd, infd, offset, count)
   582  }
   583  
   584  /*
   585   * Exposed directly
   586   */
   587  //sys	Access(path string, mode uint32) (err error)
   588  //sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
   589  //sys	Chdir(path string) (err error)
   590  //sys	Chmod(path string, mode uint32) (err error)
   591  //sys	Chown(path string, uid int, gid int) (err error)
   592  //sys	Chroot(path string) (err error)
   593  //sys	Close(fd int) (err error)
   594  //sys	Creat(path string, mode uint32) (fd int, err error)
   595  //sys	Dup(fd int) (nfd int, err error)
   596  //sys	Dup2(oldfd int, newfd int) (err error)
   597  //sys	Exit(code int)
   598  //sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
   599  //sys	Fchdir(fd int) (err error)
   600  //sys	Fchmod(fd int, mode uint32) (err error)
   601  //sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
   602  //sys	Fchown(fd int, uid int, gid int) (err error)
   603  //sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
   604  //sys	Fdatasync(fd int) (err error)
   605  //sys	Flock(fd int, how int) (err error)
   606  //sys	Fpathconf(fd int, name int) (val int, err error)
   607  //sys	Fstat(fd int, stat *Stat_t) (err error)
   608  //sys	Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
   609  //sys	Fstatvfs(fd int, vfsstat *Statvfs_t) (err error)
   610  //sys	Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
   611  //sysnb	Getgid() (gid int)
   612  //sysnb	Getpid() (pid int)
   613  //sysnb	Getpgid(pid int) (pgid int, err error)
   614  //sysnb	Getpgrp() (pgid int, err error)
   615  //sys	Geteuid() (euid int)
   616  //sys	Getegid() (egid int)
   617  //sys	Getppid() (ppid int)
   618  //sys	Getpriority(which int, who int) (n int, err error)
   619  //sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   620  //sysnb	Getrusage(who int, rusage *Rusage) (err error)
   621  //sysnb	Getsid(pid int) (sid int, err error)
   622  //sysnb	Gettimeofday(tv *Timeval) (err error)
   623  //sysnb	Getuid() (uid int)
   624  //sys	Kill(pid int, signum syscall.Signal) (err error)
   625  //sys	Lchown(path string, uid int, gid int) (err error)
   626  //sys	Link(path string, link string) (err error)
   627  //sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten
   628  //sys	Lstat(path string, stat *Stat_t) (err error)
   629  //sys	Madvise(b []byte, advice int) (err error)
   630  //sys	Mkdir(path string, mode uint32) (err error)
   631  //sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
   632  //sys	Mkfifo(path string, mode uint32) (err error)
   633  //sys	Mkfifoat(dirfd int, path string, mode uint32) (err error)
   634  //sys	Mknod(path string, mode uint32, dev int) (err error)
   635  //sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
   636  //sys	Mlock(b []byte) (err error)
   637  //sys	Mlockall(flags int) (err error)
   638  //sys	Mprotect(b []byte, prot int) (err error)
   639  //sys	Msync(b []byte, flags int) (err error)
   640  //sys	Munlock(b []byte) (err error)
   641  //sys	Munlockall() (err error)
   642  //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   643  //sys	Open(path string, mode int, perm uint32) (fd int, err error)
   644  //sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
   645  //sys	Pathconf(path string, name int) (val int, err error)
   646  //sys	Pause() (err error)
   647  //sys	pread(fd int, p []byte, offset int64) (n int, err error)
   648  //sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
   649  //sys	read(fd int, p []byte) (n int, err error)
   650  //sys	Readlink(path string, buf []byte) (n int, err error)
   651  //sys	Rename(from string, to string) (err error)
   652  //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
   653  //sys	Rmdir(path string) (err error)
   654  //sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
   655  //sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
   656  //sysnb	Setegid(egid int) (err error)
   657  //sysnb	Seteuid(euid int) (err error)
   658  //sysnb	Setgid(gid int) (err error)
   659  //sys	Sethostname(p []byte) (err error)
   660  //sysnb	Setpgid(pid int, pgid int) (err error)
   661  //sys	Setpriority(which int, who int, prio int) (err error)
   662  //sysnb	Setregid(rgid int, egid int) (err error)
   663  //sysnb	Setreuid(ruid int, euid int) (err error)
   664  //sysnb	Setrlimit(which int, lim *Rlimit) (err error)
   665  //sysnb	Setsid() (pid int, err error)
   666  //sysnb	Setuid(uid int) (err error)
   667  //sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
   668  //sys	Stat(path string, stat *Stat_t) (err error)
   669  //sys	Statvfs(path string, vfsstat *Statvfs_t) (err error)
   670  //sys	Symlink(path string, link string) (err error)
   671  //sys	Sync() (err error)
   672  //sys	Sysconf(which int) (n int64, err error)
   673  //sysnb	Times(tms *Tms) (ticks uintptr, err error)
   674  //sys	Truncate(path string, length int64) (err error)
   675  //sys	Fsync(fd int) (err error)
   676  //sys	Ftruncate(fd int, length int64) (err error)
   677  //sys	Umask(mask int) (oldmask int)
   678  //sysnb	Uname(buf *Utsname) (err error)
   679  //sys	Unmount(target string, flags int) (err error) = libc.umount
   680  //sys	Unlink(path string) (err error)
   681  //sys	Unlinkat(dirfd int, path string, flags int) (err error)
   682  //sys	Ustat(dev int, ubuf *Ustat_t) (err error)
   683  //sys	Utime(path string, buf *Utimbuf) (err error)
   684  //sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
   685  //sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
   686  //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
   687  //sys	munmap(addr uintptr, length uintptr) (err error)
   688  //sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
   689  //sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
   690  //sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
   691  //sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
   692  //sys	write(fd int, p []byte) (n int, err error)
   693  //sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
   694  //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
   695  //sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
   696  //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
   697  
   698  func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
   699  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   700  	n = int(r0)
   701  	if e1 != 0 {
   702  		err = e1
   703  	}
   704  	return
   705  }
   706  
   707  func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
   708  	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
   709  	n = int(r0)
   710  	if e1 != 0 {
   711  		err = e1
   712  	}
   713  	return
   714  }
   715  
   716  var mapper = &mmapper{
   717  	active: make(map[*byte][]byte),
   718  	mmap:   mmap,
   719  	munmap: munmap,
   720  }
   721  
   722  func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
   723  	return mapper.Mmap(fd, offset, length, prot, flags)
   724  }
   725  
   726  func Munmap(b []byte) (err error) {
   727  	return mapper.Munmap(b)
   728  }
   729  
   730  // Event Ports
   731  
   732  type fileObjCookie struct {
   733  	fobj   *fileObj
   734  	cookie interface{}
   735  }
   736  
   737  // EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
   738  type EventPort struct {
   739  	port  int
   740  	mu    sync.Mutex
   741  	fds   map[uintptr]*fileObjCookie
   742  	paths map[string]*fileObjCookie
   743  	// The user cookie presents an interesting challenge from a memory management perspective.
   744  	// There are two paths by which we can discover that it is no longer in use:
   745  	// 1. The user calls port_dissociate before any events fire
   746  	// 2. An event fires and we return it to the user
   747  	// The tricky situation is if the event has fired in the kernel but
   748  	// the user hasn't requested/received it yet.
   749  	// If the user wants to port_dissociate before the event has been processed,
   750  	// we should handle things gracefully. To do so, we need to keep an extra
   751  	// reference to the cookie around until the event is processed
   752  	// thus the otherwise seemingly extraneous "cookies" map
   753  	// The key of this map is a pointer to the corresponding fCookie
   754  	cookies map[*fileObjCookie]struct{}
   755  }
   756  
   757  // PortEvent is an abstraction of the port_event C struct.
   758  // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
   759  // to see if Path or Fd was the event source. The other will be
   760  // uninitialized.
   761  type PortEvent struct {
   762  	Cookie interface{}
   763  	Events int32
   764  	Fd     uintptr
   765  	Path   string
   766  	Source uint16
   767  	fobj   *fileObj
   768  }
   769  
   770  // NewEventPort creates a new EventPort including the
   771  // underlying call to port_create(3c).
   772  func NewEventPort() (*EventPort, error) {
   773  	port, err := port_create()
   774  	if err != nil {
   775  		return nil, err
   776  	}
   777  	e := &EventPort{
   778  		port:    port,
   779  		fds:     make(map[uintptr]*fileObjCookie),
   780  		paths:   make(map[string]*fileObjCookie),
   781  		cookies: make(map[*fileObjCookie]struct{}),
   782  	}
   783  	return e, nil
   784  }
   785  
   786  //sys	port_create() (n int, err error)
   787  //sys	port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
   788  //sys	port_dissociate(port int, source int, object uintptr) (n int, err error)
   789  //sys	port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
   790  //sys	port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
   791  
   792  // Close closes the event port.
   793  func (e *EventPort) Close() error {
   794  	e.mu.Lock()
   795  	defer e.mu.Unlock()
   796  	err := Close(e.port)
   797  	if err != nil {
   798  		return err
   799  	}
   800  	e.fds = nil
   801  	e.paths = nil
   802  	e.cookies = nil
   803  	return nil
   804  }
   805  
   806  // PathIsWatched checks to see if path is associated with this EventPort.
   807  func (e *EventPort) PathIsWatched(path string) bool {
   808  	e.mu.Lock()
   809  	defer e.mu.Unlock()
   810  	_, found := e.paths[path]
   811  	return found
   812  }
   813  
   814  // FdIsWatched checks to see if fd is associated with this EventPort.
   815  func (e *EventPort) FdIsWatched(fd uintptr) bool {
   816  	e.mu.Lock()
   817  	defer e.mu.Unlock()
   818  	_, found := e.fds[fd]
   819  	return found
   820  }
   821  
   822  // AssociatePath wraps port_associate(3c) for a filesystem path including
   823  // creating the necessary file_obj from the provided stat information.
   824  func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
   825  	e.mu.Lock()
   826  	defer e.mu.Unlock()
   827  	if _, found := e.paths[path]; found {
   828  		return fmt.Errorf("%v is already associated with this Event Port", path)
   829  	}
   830  	fCookie, err := createFileObjCookie(path, stat, cookie)
   831  	if err != nil {
   832  		return err
   833  	}
   834  	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie)))
   835  	if err != nil {
   836  		return err
   837  	}
   838  	e.paths[path] = fCookie
   839  	e.cookies[fCookie] = struct{}{}
   840  	return nil
   841  }
   842  
   843  // DissociatePath wraps port_dissociate(3c) for a filesystem path.
   844  func (e *EventPort) DissociatePath(path string) error {
   845  	e.mu.Lock()
   846  	defer e.mu.Unlock()
   847  	f, ok := e.paths[path]
   848  	if !ok {
   849  		return fmt.Errorf("%v is not associated with this Event Port", path)
   850  	}
   851  	_, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
   852  	// If the path is no longer associated with this event port (ENOENT)
   853  	// we should delete it from our map. We can still return ENOENT to the caller.
   854  	// But we need to save the cookie
   855  	if err != nil && err != ENOENT {
   856  		return err
   857  	}
   858  	if err == nil {
   859  		// dissociate was successful, safe to delete the cookie
   860  		fCookie := e.paths[path]
   861  		delete(e.cookies, fCookie)
   862  	}
   863  	delete(e.paths, path)
   864  	return err
   865  }
   866  
   867  // AssociateFd wraps calls to port_associate(3c) on file descriptors.
   868  func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
   869  	e.mu.Lock()
   870  	defer e.mu.Unlock()
   871  	if _, found := e.fds[fd]; found {
   872  		return fmt.Errorf("%v is already associated with this Event Port", fd)
   873  	}
   874  	fCookie, err := createFileObjCookie("", nil, cookie)
   875  	if err != nil {
   876  		return err
   877  	}
   878  	_, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie)))
   879  	if err != nil {
   880  		return err
   881  	}
   882  	e.fds[fd] = fCookie
   883  	e.cookies[fCookie] = struct{}{}
   884  	return nil
   885  }
   886  
   887  // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
   888  func (e *EventPort) DissociateFd(fd uintptr) error {
   889  	e.mu.Lock()
   890  	defer e.mu.Unlock()
   891  	_, ok := e.fds[fd]
   892  	if !ok {
   893  		return fmt.Errorf("%v is not associated with this Event Port", fd)
   894  	}
   895  	_, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
   896  	if err != nil && err != ENOENT {
   897  		return err
   898  	}
   899  	if err == nil {
   900  		// dissociate was successful, safe to delete the cookie
   901  		fCookie := e.fds[fd]
   902  		delete(e.cookies, fCookie)
   903  	}
   904  	delete(e.fds, fd)
   905  	return err
   906  }
   907  
   908  func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) {
   909  	fCookie := new(fileObjCookie)
   910  	fCookie.cookie = cookie
   911  	if name != "" && stat != nil {
   912  		fCookie.fobj = new(fileObj)
   913  		bs, err := ByteSliceFromString(name)
   914  		if err != nil {
   915  			return nil, err
   916  		}
   917  		fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
   918  		s := stat.Sys().(*syscall.Stat_t)
   919  		fCookie.fobj.Atim.Sec = s.Atim.Sec
   920  		fCookie.fobj.Atim.Nsec = s.Atim.Nsec
   921  		fCookie.fobj.Mtim.Sec = s.Mtim.Sec
   922  		fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec
   923  		fCookie.fobj.Ctim.Sec = s.Ctim.Sec
   924  		fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec
   925  	}
   926  	return fCookie, nil
   927  }
   928  
   929  // GetOne wraps port_get(3c) and returns a single PortEvent.
   930  func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
   931  	pe := new(portEvent)
   932  	_, err := port_get(e.port, pe, t)
   933  	if err != nil {
   934  		return nil, err
   935  	}
   936  	p := new(PortEvent)
   937  	e.mu.Lock()
   938  	defer e.mu.Unlock()
   939  	err = e.peIntToExt(pe, p)
   940  	if err != nil {
   941  		return nil, err
   942  	}
   943  	return p, nil
   944  }
   945  
   946  // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
   947  // NOTE: Always call this function while holding the e.mu mutex
   948  func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error {
   949  	if e.cookies == nil {
   950  		return fmt.Errorf("this EventPort is already closed")
   951  	}
   952  	peExt.Events = peInt.Events
   953  	peExt.Source = peInt.Source
   954  	fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User))
   955  	_, found := e.cookies[fCookie]
   956  
   957  	if !found {
   958  		panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254")
   959  	}
   960  	peExt.Cookie = fCookie.cookie
   961  	delete(e.cookies, fCookie)
   962  
   963  	switch peInt.Source {
   964  	case PORT_SOURCE_FD:
   965  		peExt.Fd = uintptr(peInt.Object)
   966  		// Only remove the fds entry if it exists and this cookie matches
   967  		if fobj, ok := e.fds[peExt.Fd]; ok {
   968  			if fobj == fCookie {
   969  				delete(e.fds, peExt.Fd)
   970  			}
   971  		}
   972  	case PORT_SOURCE_FILE:
   973  		peExt.fobj = fCookie.fobj
   974  		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
   975  		// Only remove the paths entry if it exists and this cookie matches
   976  		if fobj, ok := e.paths[peExt.Path]; ok {
   977  			if fobj == fCookie {
   978  				delete(e.paths, peExt.Path)
   979  			}
   980  		}
   981  	}
   982  	return nil
   983  }
   984  
   985  // Pending wraps port_getn(3c) and returns how many events are pending.
   986  func (e *EventPort) Pending() (int, error) {
   987  	var n uint32 = 0
   988  	_, err := port_getn(e.port, nil, 0, &n, nil)
   989  	return int(n), err
   990  }
   991  
   992  // Get wraps port_getn(3c) and fills a slice of PortEvent.
   993  // It will block until either min events have been received
   994  // or the timeout has been exceeded. It will return how many
   995  // events were actually received along with any error information.
   996  func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
   997  	if min == 0 {
   998  		return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
   999  	}
  1000  	if len(s) < min {
  1001  		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
  1002  	}
  1003  	got := uint32(min)
  1004  	max := uint32(len(s))
  1005  	var err error
  1006  	ps := make([]portEvent, max)
  1007  	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
  1008  	// got will be trustworthy with ETIME, but not any other error.
  1009  	if err != nil && err != ETIME {
  1010  		return 0, err
  1011  	}
  1012  	e.mu.Lock()
  1013  	defer e.mu.Unlock()
  1014  	valid := 0
  1015  	for i := 0; i < int(got); i++ {
  1016  		err2 := e.peIntToExt(&ps[i], &s[i])
  1017  		if err2 != nil {
  1018  			if valid == 0 && err == nil {
  1019  				// If err2 is the only error and there are no valid events
  1020  				// to return, return it to the caller.
  1021  				err = err2
  1022  			}
  1023  			break
  1024  		}
  1025  		valid = i + 1
  1026  	}
  1027  	return valid, err
  1028  }
  1029  
  1030  //sys	putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error)
  1031  
  1032  func Putmsg(fd int, cl []byte, data []byte, flags int) (err error) {
  1033  	var clp, datap *strbuf
  1034  	if len(cl) > 0 {
  1035  		clp = &strbuf{
  1036  			Len: int32(len(cl)),
  1037  			Buf: (*int8)(unsafe.Pointer(&cl[0])),
  1038  		}
  1039  	}
  1040  	if len(data) > 0 {
  1041  		datap = &strbuf{
  1042  			Len: int32(len(data)),
  1043  			Buf: (*int8)(unsafe.Pointer(&data[0])),
  1044  		}
  1045  	}
  1046  	return putmsg(fd, clp, datap, flags)
  1047  }
  1048  
  1049  //sys	getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error)
  1050  
  1051  func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags int, err error) {
  1052  	var clp, datap *strbuf
  1053  	if len(cl) > 0 {
  1054  		clp = &strbuf{
  1055  			Maxlen: int32(len(cl)),
  1056  			Buf:    (*int8)(unsafe.Pointer(&cl[0])),
  1057  		}
  1058  	}
  1059  	if len(data) > 0 {
  1060  		datap = &strbuf{
  1061  			Maxlen: int32(len(data)),
  1062  			Buf:    (*int8)(unsafe.Pointer(&data[0])),
  1063  		}
  1064  	}
  1065  
  1066  	if err = getmsg(fd, clp, datap, &flags); err != nil {
  1067  		return nil, nil, 0, err
  1068  	}
  1069  
  1070  	if len(cl) > 0 {
  1071  		retCl = cl[:clp.Len]
  1072  	}
  1073  	if len(data) > 0 {
  1074  		retData = data[:datap.Len]
  1075  	}
  1076  	return retCl, retData, flags, nil
  1077  }
  1078  
  1079  func IoctlSetIntRetInt(fd int, req uint, arg int) (int, error) {
  1080  	return ioctlRet(fd, req, uintptr(arg))
  1081  }
  1082  
  1083  func IoctlSetString(fd int, req uint, val string) error {
  1084  	bs := make([]byte, len(val)+1)
  1085  	copy(bs[:len(bs)-1], val)
  1086  	err := ioctl(fd, req, uintptr(unsafe.Pointer(&bs[0])))
  1087  	runtime.KeepAlive(&bs[0])
  1088  	return err
  1089  }
  1090  
  1091  // Lifreq Helpers
  1092  
  1093  func (l *Lifreq) SetName(name string) error {
  1094  	if len(name) >= len(l.Name) {
  1095  		return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1)
  1096  	}
  1097  	for i := range name {
  1098  		l.Name[i] = int8(name[i])
  1099  	}
  1100  	return nil
  1101  }
  1102  
  1103  func (l *Lifreq) SetLifruInt(d int) {
  1104  	*(*int)(unsafe.Pointer(&l.Lifru[0])) = d
  1105  }
  1106  
  1107  func (l *Lifreq) GetLifruInt() int {
  1108  	return *(*int)(unsafe.Pointer(&l.Lifru[0]))
  1109  }
  1110  
  1111  func (l *Lifreq) SetLifruUint(d uint) {
  1112  	*(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
  1113  }
  1114  
  1115  func (l *Lifreq) GetLifruUint() uint {
  1116  	return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
  1117  }
  1118  
  1119  func IoctlLifreq(fd int, req uint, l *Lifreq) error {
  1120  	return ioctl(fd, req, uintptr(unsafe.Pointer(l)))
  1121  }
  1122  
  1123  // Strioctl Helpers
  1124  
  1125  func (s *Strioctl) SetInt(i int) {
  1126  	s.Len = int32(unsafe.Sizeof(i))
  1127  	s.Dp = (*int8)(unsafe.Pointer(&i))
  1128  }
  1129  
  1130  func IoctlSetStrioctlRetInt(fd int, req uint, s *Strioctl) (int, error) {
  1131  	return ioctlRet(fd, req, uintptr(unsafe.Pointer(s)))
  1132  }