github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) 325 return sa, nil 326 327 case AF_INET: 328 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 329 sa := new(SockaddrInet4) 330 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 331 sa.Port = int(p[0])<<8 + int(p[1]) 332 sa.Addr = pp.Addr 333 return sa, nil 334 335 case AF_INET6: 336 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 337 sa := new(SockaddrInet6) 338 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 339 sa.Port = int(p[0])<<8 + int(p[1]) 340 sa.ZoneId = pp.Scope_id 341 sa.Addr = pp.Addr 342 return sa, nil 343 } 344 return nil, EAFNOSUPPORT 345 } 346 347 //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept 348 349 func Accept(fd int) (nfd int, sa Sockaddr, err error) { 350 var rsa RawSockaddrAny 351 var len _Socklen = SizeofSockaddrAny 352 nfd, err = accept(fd, &rsa, &len) 353 if err != nil { 354 return 355 } 356 sa, err = anyToSockaddr(&rsa) 357 if err != nil { 358 Close(nfd) 359 nfd = 0 360 } 361 return 362 } 363 364 func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { 365 var msg Msghdr 366 msg.Name = (*byte)(unsafe.Pointer(rsa)) 367 msg.Namelen = uint32(SizeofSockaddrAny) 368 var iov Iovec 369 if len(p) > 0 { 370 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 371 iov.SetLen(len(p)) 372 } 373 var dummy int8 374 if len(oob) > 0 { 375 // receive at least one normal byte 376 if len(p) == 0 { 377 iov.Base = &dummy 378 iov.SetLen(1) 379 } 380 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 381 msg.Accrightslen = int32(len(oob)) 382 } 383 msg.Iov = &iov 384 msg.Iovlen = 1 385 if n, err = recvmsg(fd, &msg, flags); err != nil { 386 return 387 } 388 oobn = int(msg.Accrightslen) 389 return 390 } 391 392 //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg 393 394 func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { 395 var msg Msghdr 396 msg.Name = (*byte)(unsafe.Pointer(ptr)) 397 msg.Namelen = uint32(salen) 398 var iov Iovec 399 if len(p) > 0 { 400 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 401 iov.SetLen(len(p)) 402 } 403 var dummy int8 404 if len(oob) > 0 { 405 // send at least one normal byte 406 if len(p) == 0 { 407 iov.Base = &dummy 408 iov.SetLen(1) 409 } 410 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 411 msg.Accrightslen = int32(len(oob)) 412 } 413 msg.Iov = &iov 414 msg.Iovlen = 1 415 if n, err = sendmsg(fd, &msg, flags); err != nil { 416 return 0, err 417 } 418 if len(oob) > 0 && len(p) == 0 { 419 n = 0 420 } 421 return n, nil 422 } 423 424 /* 425 * Exposed directly 426 */ 427 //sys Access(path string, mode uint32) (err error) 428 //sys Adjtime(delta *Timeval, olddelta *Timeval) (err error) 429 //sys Chdir(path string) (err error) 430 //sys Chmod(path string, mode uint32) (err error) 431 //sys Chown(path string, uid int, gid int) (err error) 432 //sys Chroot(path string) (err error) 433 //sys Close(fd int) (err error) 434 //sys Dup(fd int) (nfd int, err error) 435 //sys Fchdir(fd int) (err error) 436 //sys Fchmod(fd int, mode uint32) (err error) 437 //sys Fchown(fd int, uid int, gid int) (err error) 438 //sys Fpathconf(fd int, name int) (val int, err error) 439 //sys Fstat(fd int, stat *Stat_t) (err error) 440 //sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error) 441 //sysnb Getgid() (gid int) 442 //sysnb Getpid() (pid int) 443 //sys Geteuid() (euid int) 444 //sys Getegid() (egid int) 445 //sys Getppid() (ppid int) 446 //sys Getpriority(which int, who int) (n int, err error) 447 //sysnb Getrlimit(which int, lim *Rlimit) (err error) 448 //sysnb Getrusage(who int, rusage *Rusage) (err error) 449 //sysnb Gettimeofday(tv *Timeval) (err error) 450 //sysnb Getuid() (uid int) 451 //sys Kill(pid int, signum Signal) (err error) 452 //sys Lchown(path string, uid int, gid int) (err error) 453 //sys Link(path string, link string) (err error) 454 //sys Listen(s int, backlog int) (err error) = libsocket.__xnet_listen 455 //sys Lstat(path string, stat *Stat_t) (err error) 456 //sys Mkdir(path string, mode uint32) (err error) 457 //sys Mknod(path string, mode uint32, dev int) (err error) 458 //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) 459 //sys Open(path string, mode int, perm uint32) (fd int, err error) 460 //sys Pathconf(path string, name int) (val int, err error) 461 //sys pread(fd int, p []byte, offset int64) (n int, err error) 462 //sys pwrite(fd int, p []byte, offset int64) (n int, err error) 463 //sys read(fd int, p []byte) (n int, err error) 464 //sys Readlink(path string, buf []byte) (n int, err error) 465 //sys Rename(from string, to string) (err error) 466 //sys Rmdir(path string) (err error) 467 //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek 468 //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile 469 //sysnb Setegid(egid int) (err error) 470 //sysnb Seteuid(euid int) (err error) 471 //sysnb Setgid(gid int) (err error) 472 //sysnb Setpgid(pid int, pgid int) (err error) 473 //sys Setpriority(which int, who int, prio int) (err error) 474 //sysnb Setregid(rgid int, egid int) (err error) 475 //sysnb Setreuid(ruid int, euid int) (err error) 476 //sysnb setrlimit(which int, lim *Rlimit) (err error) 477 //sysnb Setsid() (pid int, err error) 478 //sysnb Setuid(uid int) (err error) 479 //sys Shutdown(s int, how int) (err error) = libsocket.shutdown 480 //sys Stat(path string, stat *Stat_t) (err error) 481 //sys Symlink(path string, link string) (err error) 482 //sys Sync() (err error) 483 //sys Truncate(path string, length int64) (err error) 484 //sys Fsync(fd int) (err error) 485 //sys Ftruncate(fd int, length int64) (err error) 486 //sys Umask(newmask int) (oldmask int) 487 //sys Unlink(path string) (err error) 488 //sys utimes(path string, times *[2]Timeval) (err error) 489 //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind 490 //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect 491 //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) 492 //sys munmap(addr uintptr, length uintptr) (err error) 493 //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto 494 //sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket 495 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair 496 //sys write(fd int, p []byte) (n int, err error) 497 //sys writev(fd int, iovecs []Iovec) (n uintptr, err error) 498 //sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt 499 //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername 500 //sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname 501 //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt 502 //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom 503 //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg 504 //sys getexecname() (path unsafe.Pointer, err error) = libc.getexecname 505 //sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) 506 507 func Getexecname() (path string, err error) { 508 ptr, err := getexecname() 509 if err != nil { 510 return "", err 511 } 512 bytes := (*[1 << 29]byte)(ptr)[:] 513 for i, b := range bytes { 514 if b == 0 { 515 return string(bytes[:i]), nil 516 } 517 } 518 panic("unreachable") 519 } 520 521 func readlen(fd int, buf *byte, nbuf int) (n int, err error) { 522 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 523 n = int(r0) 524 if e1 != 0 { 525 err = e1 526 } 527 return 528 } 529 530 func writelen(fd int, buf *byte, nbuf int) (n int, err error) { 531 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_write)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 532 n = int(r0) 533 if e1 != 0 { 534 err = e1 535 } 536 return 537 } 538 539 var mapper = &mmapper{ 540 active: make(map[*byte][]byte), 541 mmap: mmap, 542 munmap: munmap, 543 } 544 545 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 546 return mapper.Mmap(fd, offset, length, prot, flags) 547 } 548 549 func Munmap(b []byte) (err error) { 550 return mapper.Munmap(b) 551 } 552 553 func Utimes(path string, tv []Timeval) error { 554 if len(tv) != 2 { 555 return EINVAL 556 } 557 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 558 }