github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/syscall/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 syscall 14 15 import "unsafe" 16 17 const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC 18 19 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 20 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 21 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 22 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 23 24 // Implemented in asm_solaris_amd64.s. 25 func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 26 func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 27 28 type SockaddrDatalink struct { 29 Family uint16 30 Index uint16 31 Type uint8 32 Nlen uint8 33 Alen uint8 34 Slen uint8 35 Data [244]int8 36 raw RawSockaddrDatalink 37 } 38 39 func direntIno(buf []byte) (uint64, bool) { 40 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) 41 } 42 43 func direntReclen(buf []byte) (uint64, bool) { 44 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) 45 } 46 47 func direntNamlen(buf []byte) (uint64, bool) { 48 reclen, ok := direntReclen(buf) 49 if !ok { 50 return 0, false 51 } 52 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true 53 } 54 55 func Pipe(p []int) (err error) { 56 return Pipe2(p, 0) 57 } 58 59 //sysnb pipe2(p *[2]_C_int, flags int) (err error) 60 61 func Pipe2(p []int, flags int) error { 62 if len(p) != 2 { 63 return EINVAL 64 } 65 var pp [2]_C_int 66 err := pipe2(&pp, flags) 67 if err == nil { 68 p[0] = int(pp[0]) 69 p[1] = int(pp[1]) 70 } 71 return err 72 } 73 74 //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4 75 76 func Accept4(fd int, flags int) (int, Sockaddr, error) { 77 var rsa RawSockaddrAny 78 var addrlen _Socklen = SizeofSockaddrAny 79 nfd, err := accept4(fd, &rsa, &addrlen, flags) 80 if err != nil { 81 return 0, nil, err 82 } 83 if addrlen > SizeofSockaddrAny { 84 panic("RawSockaddrAny too small") 85 } 86 sa, err := anyToSockaddr(&rsa) 87 if err != nil { 88 Close(nfd) 89 return 0, nil, err 90 } 91 return nfd, sa, nil 92 } 93 94 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 95 if sa.Port < 0 || sa.Port > 0xFFFF { 96 return nil, 0, EINVAL 97 } 98 sa.raw.Family = AF_INET 99 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 100 p[0] = byte(sa.Port >> 8) 101 p[1] = byte(sa.Port) 102 sa.raw.Addr = sa.Addr 103 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil 104 } 105 106 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 107 if sa.Port < 0 || sa.Port > 0xFFFF { 108 return nil, 0, EINVAL 109 } 110 sa.raw.Family = AF_INET6 111 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 112 p[0] = byte(sa.Port >> 8) 113 p[1] = byte(sa.Port) 114 sa.raw.Scope_id = sa.ZoneId 115 sa.raw.Addr = sa.Addr 116 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil 117 } 118 119 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 120 name := sa.Name 121 n := len(name) 122 if n >= len(sa.raw.Path) { 123 return nil, 0, EINVAL 124 } 125 sa.raw.Family = AF_UNIX 126 for i := 0; i < n; i++ { 127 sa.raw.Path[i] = int8(name[i]) 128 } 129 // length is family (uint16), name, NUL. 130 sl := _Socklen(2) 131 if n > 0 { 132 sl += _Socklen(n) + 1 133 } 134 if sa.raw.Path[0] == '@' { 135 sa.raw.Path[0] = 0 136 // Don't count trailing NUL for abstract address. 137 sl-- 138 } 139 140 return unsafe.Pointer(&sa.raw), sl, nil 141 } 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(&rsa) 150 } 151 152 const ImplementsGetwd = true 153 154 //sys Getcwd(buf []byte) (n int, err error) 155 156 func Getwd() (wd string, err error) { 157 var buf [PathMax]byte 158 // Getcwd will return an error if it failed for any reason. 159 _, err = Getcwd(buf[0:]) 160 if err != nil { 161 return "", err 162 } 163 n := clen(buf[:]) 164 if n < 1 { 165 return "", EINVAL 166 } 167 return string(buf[:n]), nil 168 } 169 170 /* 171 * Wrapped 172 */ 173 174 //sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error) 175 //sysnb setgroups(ngid int, gid *_Gid_t) (err error) 176 177 func Getgroups() (gids []int, err error) { 178 n, err := getgroups(0, nil) 179 if err != nil { 180 return nil, err 181 } 182 if n == 0 { 183 return nil, nil 184 } 185 186 // Sanity check group count. Max is 16 on BSD. 187 if n < 0 || n > 1000 { 188 return nil, EINVAL 189 } 190 191 a := make([]_Gid_t, n) 192 n, err = getgroups(n, &a[0]) 193 if err != nil { 194 return nil, err 195 } 196 gids = make([]int, n) 197 for i, v := range a[0:n] { 198 gids[i] = int(v) 199 } 200 return 201 } 202 203 func Setgroups(gids []int) (err error) { 204 if len(gids) == 0 { 205 return setgroups(0, nil) 206 } 207 208 a := make([]_Gid_t, len(gids)) 209 for i, v := range gids { 210 a[i] = _Gid_t(v) 211 } 212 return setgroups(len(a), &a[0]) 213 } 214 215 func ReadDirent(fd int, buf []byte) (n int, err error) { 216 // Final argument is (basep *uintptr) and the syscall doesn't take nil. 217 // TODO(rsc): Can we use a single global basep for all calls? 218 return Getdents(fd, buf, new(uintptr)) 219 } 220 221 // Wait status is 7 bits at bottom, either 0 (exited), 222 // 0x7F (stopped), or a signal number that caused an exit. 223 // The 0x80 bit is whether there was a core dump. 224 // An extra number (exit code, signal causing a stop) 225 // is in the high bits. 226 227 type WaitStatus uint32 228 229 const ( 230 mask = 0x7F 231 core = 0x80 232 shift = 8 233 234 exited = 0 235 stopped = 0x7F 236 ) 237 238 func (w WaitStatus) Exited() bool { return w&mask == exited } 239 240 func (w WaitStatus) ExitStatus() int { 241 if w&mask != exited { 242 return -1 243 } 244 return int(w >> shift) 245 } 246 247 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 } 248 249 func (w WaitStatus) Signal() Signal { 250 sig := Signal(w & mask) 251 if sig == stopped || sig == 0 { 252 return -1 253 } 254 return sig 255 } 256 257 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } 258 259 func (w WaitStatus) Stopped() bool { return w&mask == stopped && Signal(w>>shift) != SIGSTOP } 260 261 func (w WaitStatus) Continued() bool { return w&mask == stopped && Signal(w>>shift) == SIGSTOP } 262 263 func (w WaitStatus) StopSignal() Signal { 264 if !w.Stopped() { 265 return -1 266 } 267 return Signal(w>>shift) & 0xFF 268 } 269 270 func (w WaitStatus) TrapCause() int { return -1 } 271 272 func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr) 273 274 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 275 r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage) 276 if e1 != 0 { 277 err = Errno(e1) 278 } 279 return int(r0), err 280 } 281 282 func gethostname() (name string, err uintptr) 283 284 func Gethostname() (name string, err error) { 285 name, e1 := gethostname() 286 if e1 != 0 { 287 err = Errno(e1) 288 } 289 return name, err 290 } 291 292 func UtimesNano(path string, ts []Timespec) error { 293 if len(ts) != 2 { 294 return EINVAL 295 } 296 return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) 297 } 298 299 //sys fcntl(fd int, cmd int, arg int) (val int, err error) 300 301 // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. 302 func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { 303 _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0) 304 if e1 != 0 { 305 return e1 306 } 307 return nil 308 } 309 310 func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { 311 switch rsa.Addr.Family { 312 case AF_UNIX: 313 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 314 sa := new(SockaddrUnix) 315 // Assume path ends at NUL. 316 // This is not technically the Solaris semantics for 317 // abstract Unix domain sockets -- they are supposed 318 // to be uninterpreted fixed-size binary blobs -- but 319 // everyone uses this convention. 320 n := 0 321 for n < len(pp.Path) && pp.Path[n] != 0 { 322 n++ 323 } 324 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 325 sa.Name = string(bytes) 326 return sa, nil 327 328 case AF_INET: 329 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 330 sa := new(SockaddrInet4) 331 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 332 sa.Port = int(p[0])<<8 + int(p[1]) 333 sa.Addr = pp.Addr 334 return sa, nil 335 336 case AF_INET6: 337 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 338 sa := new(SockaddrInet6) 339 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 340 sa.Port = int(p[0])<<8 + int(p[1]) 341 sa.ZoneId = pp.Scope_id 342 sa.Addr = pp.Addr 343 return sa, nil 344 } 345 return nil, EAFNOSUPPORT 346 } 347 348 //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept 349 350 func Accept(fd int) (nfd int, sa Sockaddr, err error) { 351 var rsa RawSockaddrAny 352 var len _Socklen = SizeofSockaddrAny 353 nfd, err = accept(fd, &rsa, &len) 354 if err != nil { 355 return 356 } 357 sa, err = anyToSockaddr(&rsa) 358 if err != nil { 359 Close(nfd) 360 nfd = 0 361 } 362 return 363 } 364 365 func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { 366 var msg Msghdr 367 msg.Name = (*byte)(unsafe.Pointer(rsa)) 368 msg.Namelen = uint32(SizeofSockaddrAny) 369 var iov Iovec 370 if len(p) > 0 { 371 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 372 iov.SetLen(len(p)) 373 } 374 var dummy int8 375 if len(oob) > 0 { 376 // receive at least one normal byte 377 if len(p) == 0 { 378 iov.Base = &dummy 379 iov.SetLen(1) 380 } 381 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 382 msg.Accrightslen = int32(len(oob)) 383 } 384 msg.Iov = &iov 385 msg.Iovlen = 1 386 if n, err = recvmsg(fd, &msg, flags); err != nil { 387 return 388 } 389 oobn = int(msg.Accrightslen) 390 return 391 } 392 393 //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg 394 395 func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { 396 var msg Msghdr 397 msg.Name = (*byte)(unsafe.Pointer(ptr)) 398 msg.Namelen = uint32(salen) 399 var iov Iovec 400 if len(p) > 0 { 401 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 402 iov.SetLen(len(p)) 403 } 404 var dummy int8 405 if len(oob) > 0 { 406 // send at least one normal byte 407 if len(p) == 0 { 408 iov.Base = &dummy 409 iov.SetLen(1) 410 } 411 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 412 msg.Accrightslen = int32(len(oob)) 413 } 414 msg.Iov = &iov 415 msg.Iovlen = 1 416 if n, err = sendmsg(fd, &msg, flags); err != nil { 417 return 0, err 418 } 419 if len(oob) > 0 && len(p) == 0 { 420 n = 0 421 } 422 return n, nil 423 } 424 425 /* 426 * Exposed directly 427 */ 428 //sys Access(path string, mode uint32) (err error) 429 //sys Adjtime(delta *Timeval, olddelta *Timeval) (err error) 430 //sys Chdir(path string) (err error) 431 //sys Chmod(path string, mode uint32) (err error) 432 //sys Chown(path string, uid int, gid int) (err error) 433 //sys Chroot(path string) (err error) 434 //sys Close(fd int) (err error) 435 //sys Dup(fd int) (nfd int, err error) 436 //sys Fchdir(fd int) (err error) 437 //sys Fchmod(fd int, mode uint32) (err error) 438 //sys Fchown(fd int, uid int, gid int) (err error) 439 //sys Fpathconf(fd int, name int) (val int, err error) 440 //sys Fstat(fd int, stat *Stat_t) (err error) 441 //sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error) 442 //sysnb Getgid() (gid int) 443 //sysnb Getpid() (pid int) 444 //sys Geteuid() (euid int) 445 //sys Getegid() (egid int) 446 //sys Getppid() (ppid int) 447 //sys Getpriority(which int, who int) (n int, err error) 448 //sysnb Getrlimit(which int, lim *Rlimit) (err error) 449 //sysnb Getrusage(who int, rusage *Rusage) (err error) 450 //sysnb Gettimeofday(tv *Timeval) (err error) 451 //sysnb Getuid() (uid int) 452 //sys Kill(pid int, signum Signal) (err error) 453 //sys Lchown(path string, uid int, gid int) (err error) 454 //sys Link(path string, link string) (err error) 455 //sys Listen(s int, backlog int) (err error) = libsocket.__xnet_listen 456 //sys Lstat(path string, stat *Stat_t) (err error) 457 //sys Mkdir(path string, mode uint32) (err error) 458 //sys Mknod(path string, mode uint32, dev int) (err error) 459 //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) 460 //sys Open(path string, mode int, perm uint32) (fd int, err error) 461 //sys Pathconf(path string, name int) (val int, err error) 462 //sys pread(fd int, p []byte, offset int64) (n int, err error) 463 //sys pwrite(fd int, p []byte, offset int64) (n int, err error) 464 //sys read(fd int, p []byte) (n int, err error) 465 //sys Readlink(path string, buf []byte) (n int, err error) 466 //sys Rename(from string, to string) (err error) 467 //sys Rmdir(path string) (err error) 468 //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek 469 //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile 470 //sysnb Setegid(egid int) (err error) 471 //sysnb Seteuid(euid int) (err error) 472 //sysnb Setgid(gid int) (err error) 473 //sysnb Setpgid(pid int, pgid int) (err error) 474 //sys Setpriority(which int, who int, prio int) (err error) 475 //sysnb Setregid(rgid int, egid int) (err error) 476 //sysnb Setreuid(ruid int, euid int) (err error) 477 //sysnb Setrlimit(which int, lim *Rlimit) (err error) 478 //sysnb Setsid() (pid int, err error) 479 //sysnb Setuid(uid int) (err error) 480 //sys Shutdown(s int, how int) (err error) = libsocket.shutdown 481 //sys Stat(path string, stat *Stat_t) (err error) 482 //sys Symlink(path string, link string) (err error) 483 //sys Sync() (err error) 484 //sys Truncate(path string, length int64) (err error) 485 //sys Fsync(fd int) (err error) 486 //sys Ftruncate(fd int, length int64) (err error) 487 //sys Umask(newmask int) (oldmask int) 488 //sys Unlink(path string) (err error) 489 //sys utimes(path string, times *[2]Timeval) (err error) 490 //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind 491 //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect 492 //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) 493 //sys munmap(addr uintptr, length uintptr) (err error) 494 //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto 495 //sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket 496 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair 497 //sys write(fd int, p []byte) (n int, err error) 498 //sys writev(fd int, iovecs []Iovec) (n uintptr, err error) 499 //sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt 500 //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername 501 //sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname 502 //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt 503 //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom 504 //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg 505 //sys getexecname() (path unsafe.Pointer, err error) = libc.getexecname 506 //sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) 507 508 func Getexecname() (path string, err error) { 509 ptr, err := getexecname() 510 if err != nil { 511 return "", err 512 } 513 bytes := (*[1 << 29]byte)(ptr)[:] 514 for i, b := range bytes { 515 if b == 0 { 516 return string(bytes[:i]), nil 517 } 518 } 519 panic("unreachable") 520 } 521 522 func readlen(fd int, buf *byte, nbuf int) (n int, err error) { 523 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 524 n = int(r0) 525 if e1 != 0 { 526 err = e1 527 } 528 return 529 } 530 531 func writelen(fd int, buf *byte, nbuf int) (n int, err error) { 532 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_write)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 533 n = int(r0) 534 if e1 != 0 { 535 err = e1 536 } 537 return 538 } 539 540 var mapper = &mmapper{ 541 active: make(map[*byte][]byte), 542 mmap: mmap, 543 munmap: munmap, 544 } 545 546 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 547 return mapper.Mmap(fd, offset, length, prot, flags) 548 } 549 550 func Munmap(b []byte) (err error) { 551 return mapper.Munmap(b) 552 } 553 554 func Utimes(path string, tv []Timeval) error { 555 if len(tv) != 2 { 556 return EINVAL 557 } 558 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 559 }