gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

syscall_solaris.go (32543B)


      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 }