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