usb-ks

USB Killswitch
git clone git://git.laack.co/usb-ks.git
Log | Files | Refs | README | LICENSE

syscall_solaris.go (29641B)


      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, p, 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 iov Iovec
    459 	if len(p) > 0 {
    460 		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
    461 		iov.SetLen(len(p))
    462 	}
    463 	var dummy int8
    464 	if len(oob) > 0 {
    465 		// receive at least one normal byte
    466 		if len(p) == 0 {
    467 			iov.Base = &dummy
    468 			iov.SetLen(1)
    469 		}
    470 		msg.Accrightslen = int32(len(oob))
    471 	}
    472 	msg.Iov = &iov
    473 	msg.Iovlen = 1
    474 	if n, err = recvmsg(fd, &msg, flags); n == -1 {
    475 		return
    476 	}
    477 	oobn = int(msg.Accrightslen)
    478 	return
    479 }
    480 
    481 //sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
    482 
    483 func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
    484 	var msg Msghdr
    485 	msg.Name = (*byte)(unsafe.Pointer(ptr))
    486 	msg.Namelen = uint32(salen)
    487 	var iov Iovec
    488 	if len(p) > 0 {
    489 		iov.Base = (*int8)(unsafe.Pointer(&p[0]))
    490 		iov.SetLen(len(p))
    491 	}
    492 	var dummy int8
    493 	if len(oob) > 0 {
    494 		// send at least one normal byte
    495 		if len(p) == 0 {
    496 			iov.Base = &dummy
    497 			iov.SetLen(1)
    498 		}
    499 		msg.Accrightslen = int32(len(oob))
    500 	}
    501 	msg.Iov = &iov
    502 	msg.Iovlen = 1
    503 	if n, err = sendmsg(fd, &msg, flags); err != nil {
    504 		return 0, err
    505 	}
    506 	if len(oob) > 0 && len(p) == 0 {
    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	Gettimeofday(tv *Timeval) (err error)
    622 //sysnb	Getuid() (uid int)
    623 //sys	Kill(pid int, signum syscall.Signal) (err error)
    624 //sys	Lchown(path string, uid int, gid int) (err error)
    625 //sys	Link(path string, link string) (err error)
    626 //sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten
    627 //sys	Lstat(path string, stat *Stat_t) (err error)
    628 //sys	Madvise(b []byte, advice int) (err error)
    629 //sys	Mkdir(path string, mode uint32) (err error)
    630 //sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
    631 //sys	Mkfifo(path string, mode uint32) (err error)
    632 //sys	Mkfifoat(dirfd int, path string, mode uint32) (err error)
    633 //sys	Mknod(path string, mode uint32, dev int) (err error)
    634 //sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
    635 //sys	Mlock(b []byte) (err error)
    636 //sys	Mlockall(flags int) (err error)
    637 //sys	Mprotect(b []byte, prot int) (err error)
    638 //sys	Msync(b []byte, flags int) (err error)
    639 //sys	Munlock(b []byte) (err error)
    640 //sys	Munlockall() (err error)
    641 //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
    642 //sys	Open(path string, mode int, perm uint32) (fd int, err error)
    643 //sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
    644 //sys	Pathconf(path string, name int) (val int, err error)
    645 //sys	Pause() (err error)
    646 //sys	pread(fd int, p []byte, offset int64) (n int, err error)
    647 //sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
    648 //sys	read(fd int, p []byte) (n int, err error)
    649 //sys	Readlink(path string, buf []byte) (n int, err error)
    650 //sys	Rename(from string, to string) (err error)
    651 //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
    652 //sys	Rmdir(path string) (err error)
    653 //sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
    654 //sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
    655 //sysnb	Setegid(egid int) (err error)
    656 //sysnb	Seteuid(euid int) (err error)
    657 //sysnb	Setgid(gid int) (err error)
    658 //sys	Sethostname(p []byte) (err error)
    659 //sysnb	Setpgid(pid int, pgid int) (err error)
    660 //sys	Setpriority(which int, who int, prio int) (err error)
    661 //sysnb	Setregid(rgid int, egid int) (err error)
    662 //sysnb	Setreuid(ruid int, euid int) (err error)
    663 //sysnb	Setrlimit(which int, lim *Rlimit) (err error)
    664 //sysnb	Setsid() (pid int, err error)
    665 //sysnb	Setuid(uid int) (err error)
    666 //sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
    667 //sys	Stat(path string, stat *Stat_t) (err error)
    668 //sys	Statvfs(path string, vfsstat *Statvfs_t) (err error)
    669 //sys	Symlink(path string, link string) (err error)
    670 //sys	Sync() (err error)
    671 //sys	Sysconf(which int) (n int64, err error)
    672 //sysnb	Times(tms *Tms) (ticks uintptr, err error)
    673 //sys	Truncate(path string, length int64) (err error)
    674 //sys	Fsync(fd int) (err error)
    675 //sys	Ftruncate(fd int, length int64) (err error)
    676 //sys	Umask(mask int) (oldmask int)
    677 //sysnb	Uname(buf *Utsname) (err error)
    678 //sys	Unmount(target string, flags int) (err error) = libc.umount
    679 //sys	Unlink(path string) (err error)
    680 //sys	Unlinkat(dirfd int, path string, flags int) (err error)
    681 //sys	Ustat(dev int, ubuf *Ustat_t) (err error)
    682 //sys	Utime(path string, buf *Utimbuf) (err error)
    683 //sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
    684 //sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
    685 //sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
    686 //sys	munmap(addr uintptr, length uintptr) (err error)
    687 //sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
    688 //sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
    689 //sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
    690 //sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
    691 //sys	write(fd int, p []byte) (n int, err error)
    692 //sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
    693 //sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
    694 //sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
    695 //sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
    696 
    697 func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
    698 	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
    699 	n = int(r0)
    700 	if e1 != 0 {
    701 		err = e1
    702 	}
    703 	return
    704 }
    705 
    706 func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
    707 	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
    708 	n = int(r0)
    709 	if e1 != 0 {
    710 		err = e1
    711 	}
    712 	return
    713 }
    714 
    715 var mapper = &mmapper{
    716 	active: make(map[*byte][]byte),
    717 	mmap:   mmap,
    718 	munmap: munmap,
    719 }
    720 
    721 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
    722 	return mapper.Mmap(fd, offset, length, prot, flags)
    723 }
    724 
    725 func Munmap(b []byte) (err error) {
    726 	return mapper.Munmap(b)
    727 }
    728 
    729 // Event Ports
    730 
    731 type fileObjCookie struct {
    732 	fobj   *fileObj
    733 	cookie interface{}
    734 }
    735 
    736 // EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
    737 type EventPort struct {
    738 	port  int
    739 	mu    sync.Mutex
    740 	fds   map[uintptr]*fileObjCookie
    741 	paths map[string]*fileObjCookie
    742 	// The user cookie presents an interesting challenge from a memory management perspective.
    743 	// There are two paths by which we can discover that it is no longer in use:
    744 	// 1. The user calls port_dissociate before any events fire
    745 	// 2. An event fires and we return it to the user
    746 	// The tricky situation is if the event has fired in the kernel but
    747 	// the user hasn't requested/received it yet.
    748 	// If the user wants to port_dissociate before the event has been processed,
    749 	// we should handle things gracefully. To do so, we need to keep an extra
    750 	// reference to the cookie around until the event is processed
    751 	// thus the otherwise seemingly extraneous "cookies" map
    752 	// The key of this map is a pointer to the corresponding &fCookie.cookie
    753 	cookies map[*interface{}]*fileObjCookie
    754 }
    755 
    756 // PortEvent is an abstraction of the port_event C struct.
    757 // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
    758 // to see if Path or Fd was the event source. The other will be
    759 // uninitialized.
    760 type PortEvent struct {
    761 	Cookie interface{}
    762 	Events int32
    763 	Fd     uintptr
    764 	Path   string
    765 	Source uint16
    766 	fobj   *fileObj
    767 }
    768 
    769 // NewEventPort creates a new EventPort including the
    770 // underlying call to port_create(3c).
    771 func NewEventPort() (*EventPort, error) {
    772 	port, err := port_create()
    773 	if err != nil {
    774 		return nil, err
    775 	}
    776 	e := &EventPort{
    777 		port:    port,
    778 		fds:     make(map[uintptr]*fileObjCookie),
    779 		paths:   make(map[string]*fileObjCookie),
    780 		cookies: make(map[*interface{}]*fileObjCookie),
    781 	}
    782 	return e, nil
    783 }
    784 
    785 //sys	port_create() (n int, err error)
    786 //sys	port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
    787 //sys	port_dissociate(port int, source int, object uintptr) (n int, err error)
    788 //sys	port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
    789 //sys	port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
    790 
    791 // Close closes the event port.
    792 func (e *EventPort) Close() error {
    793 	e.mu.Lock()
    794 	defer e.mu.Unlock()
    795 	err := Close(e.port)
    796 	if err != nil {
    797 		return err
    798 	}
    799 	e.fds = nil
    800 	e.paths = nil
    801 	return nil
    802 }
    803 
    804 // PathIsWatched checks to see if path is associated with this EventPort.
    805 func (e *EventPort) PathIsWatched(path string) bool {
    806 	e.mu.Lock()
    807 	defer e.mu.Unlock()
    808 	_, found := e.paths[path]
    809 	return found
    810 }
    811 
    812 // FdIsWatched checks to see if fd is associated with this EventPort.
    813 func (e *EventPort) FdIsWatched(fd uintptr) bool {
    814 	e.mu.Lock()
    815 	defer e.mu.Unlock()
    816 	_, found := e.fds[fd]
    817 	return found
    818 }
    819 
    820 // AssociatePath wraps port_associate(3c) for a filesystem path including
    821 // creating the necessary file_obj from the provided stat information.
    822 func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
    823 	e.mu.Lock()
    824 	defer e.mu.Unlock()
    825 	if _, found := e.paths[path]; found {
    826 		return fmt.Errorf("%v is already associated with this Event Port", path)
    827 	}
    828 	fobj, err := createFileObj(path, stat)
    829 	if err != nil {
    830 		return err
    831 	}
    832 	fCookie := &fileObjCookie{fobj, cookie}
    833 	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
    834 	if err != nil {
    835 		return err
    836 	}
    837 	e.paths[path] = fCookie
    838 	e.cookies[&fCookie.cookie] = fCookie
    839 	return nil
    840 }
    841 
    842 // DissociatePath wraps port_dissociate(3c) for a filesystem path.
    843 func (e *EventPort) DissociatePath(path string) error {
    844 	e.mu.Lock()
    845 	defer e.mu.Unlock()
    846 	f, ok := e.paths[path]
    847 	if !ok {
    848 		return fmt.Errorf("%v is not associated with this Event Port", path)
    849 	}
    850 	_, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
    851 	// If the path is no longer associated with this event port (ENOENT)
    852 	// we should delete it from our map. We can still return ENOENT to the caller.
    853 	// But we need to save the cookie
    854 	if err != nil && err != ENOENT {
    855 		return err
    856 	}
    857 	if err == nil {
    858 		// dissociate was successful, safe to delete the cookie
    859 		fCookie := e.paths[path]
    860 		delete(e.cookies, &fCookie.cookie)
    861 	}
    862 	delete(e.paths, path)
    863 	return err
    864 }
    865 
    866 // AssociateFd wraps calls to port_associate(3c) on file descriptors.
    867 func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
    868 	e.mu.Lock()
    869 	defer e.mu.Unlock()
    870 	if _, found := e.fds[fd]; found {
    871 		return fmt.Errorf("%v is already associated with this Event Port", fd)
    872 	}
    873 	fCookie := &fileObjCookie{nil, cookie}
    874 	_, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
    875 	if err != nil {
    876 		return err
    877 	}
    878 	e.fds[fd] = fCookie
    879 	e.cookies[&fCookie.cookie] = fCookie
    880 	return nil
    881 }
    882 
    883 // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
    884 func (e *EventPort) DissociateFd(fd uintptr) error {
    885 	e.mu.Lock()
    886 	defer e.mu.Unlock()
    887 	_, ok := e.fds[fd]
    888 	if !ok {
    889 		return fmt.Errorf("%v is not associated with this Event Port", fd)
    890 	}
    891 	_, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
    892 	if err != nil && err != ENOENT {
    893 		return err
    894 	}
    895 	if err == nil {
    896 		// dissociate was successful, safe to delete the cookie
    897 		fCookie := e.fds[fd]
    898 		delete(e.cookies, &fCookie.cookie)
    899 	}
    900 	delete(e.fds, fd)
    901 	return err
    902 }
    903 
    904 func createFileObj(name string, stat os.FileInfo) (*fileObj, error) {
    905 	fobj := new(fileObj)
    906 	bs, err := ByteSliceFromString(name)
    907 	if err != nil {
    908 		return nil, err
    909 	}
    910 	fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
    911 	s := stat.Sys().(*syscall.Stat_t)
    912 	fobj.Atim.Sec = s.Atim.Sec
    913 	fobj.Atim.Nsec = s.Atim.Nsec
    914 	fobj.Mtim.Sec = s.Mtim.Sec
    915 	fobj.Mtim.Nsec = s.Mtim.Nsec
    916 	fobj.Ctim.Sec = s.Ctim.Sec
    917 	fobj.Ctim.Nsec = s.Ctim.Nsec
    918 	return fobj, nil
    919 }
    920 
    921 // GetOne wraps port_get(3c) and returns a single PortEvent.
    922 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
    923 	pe := new(portEvent)
    924 	_, err := port_get(e.port, pe, t)
    925 	if err != nil {
    926 		return nil, err
    927 	}
    928 	p := new(PortEvent)
    929 	e.mu.Lock()
    930 	defer e.mu.Unlock()
    931 	e.peIntToExt(pe, p)
    932 	return p, nil
    933 }
    934 
    935 // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
    936 // NOTE: Always call this function while holding the e.mu mutex
    937 func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) {
    938 	peExt.Events = peInt.Events
    939 	peExt.Source = peInt.Source
    940 	cookie := (*interface{})(unsafe.Pointer(peInt.User))
    941 	peExt.Cookie = *cookie
    942 	switch peInt.Source {
    943 	case PORT_SOURCE_FD:
    944 		delete(e.cookies, cookie)
    945 		peExt.Fd = uintptr(peInt.Object)
    946 		// Only remove the fds entry if it exists and this cookie matches
    947 		if fobj, ok := e.fds[peExt.Fd]; ok {
    948 			if &fobj.cookie == cookie {
    949 				delete(e.fds, peExt.Fd)
    950 			}
    951 		}
    952 	case PORT_SOURCE_FILE:
    953 		if fCookie, ok := e.cookies[cookie]; ok && uintptr(unsafe.Pointer(fCookie.fobj)) == uintptr(peInt.Object) {
    954 			// Use our stashed reference rather than using unsafe on what we got back
    955 			// the unsafe version would be (*fileObj)(unsafe.Pointer(uintptr(peInt.Object)))
    956 			peExt.fobj = fCookie.fobj
    957 		} else {
    958 			panic("mismanaged memory")
    959 		}
    960 		delete(e.cookies, cookie)
    961 		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
    962 		// Only remove the paths entry if it exists and this cookie matches
    963 		if fobj, ok := e.paths[peExt.Path]; ok {
    964 			if &fobj.cookie == cookie {
    965 				delete(e.paths, peExt.Path)
    966 			}
    967 		}
    968 	}
    969 }
    970 
    971 // Pending wraps port_getn(3c) and returns how many events are pending.
    972 func (e *EventPort) Pending() (int, error) {
    973 	var n uint32 = 0
    974 	_, err := port_getn(e.port, nil, 0, &n, nil)
    975 	return int(n), err
    976 }
    977 
    978 // Get wraps port_getn(3c) and fills a slice of PortEvent.
    979 // It will block until either min events have been received
    980 // or the timeout has been exceeded. It will return how many
    981 // events were actually received along with any error information.
    982 func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
    983 	if min == 0 {
    984 		return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
    985 	}
    986 	if len(s) < min {
    987 		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
    988 	}
    989 	got := uint32(min)
    990 	max := uint32(len(s))
    991 	var err error
    992 	ps := make([]portEvent, max, max)
    993 	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
    994 	// got will be trustworthy with ETIME, but not any other error.
    995 	if err != nil && err != ETIME {
    996 		return 0, err
    997 	}
    998 	e.mu.Lock()
    999 	defer e.mu.Unlock()
   1000 	for i := 0; i < int(got); i++ {
   1001 		e.peIntToExt(&ps[i], &s[i])
   1002 	}
   1003 	return int(got), err
   1004 }