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