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) (err error) { 274 if len(ts) != 2 { 275 return EINVAL 276 } 277 var tv [2]Timeval 278 for i := 0; i < 2; i++ { 279 tv[i].Sec = ts[i].Sec 280 tv[i].Usec = ts[i].Nsec / 1000 281 } 282 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 283 } 284 285 //sys fcntl(fd int, cmd int, arg int) (val int, err error) 286 287 // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. 288 func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { 289 _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0) 290 if e1 != 0 { 291 return e1 292 } 293 return nil 294 } 295 296 func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { 297 switch rsa.Addr.Family { 298 case AF_UNIX: 299 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 300 sa := new(SockaddrUnix) 301 // Assume path ends at NUL. 302 // This is not technically the Solaris semantics for 303 // abstract Unix domain sockets -- they are supposed 304 // to be uninterpreted fixed-size binary blobs -- but 305 // everyone uses this convention. 306 n := 0 307 for n < len(pp.Path) && pp.Path[n] != 0 { 308 n++ 309 } 310 bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 311 sa.Name = string(bytes) 312 return sa, nil 313 314 case AF_INET: 315 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 316 sa := new(SockaddrInet4) 317 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 318 sa.Port = int(p[0])<<8 + int(p[1]) 319 for i := 0; i < len(sa.Addr); i++ { 320 sa.Addr[i] = pp.Addr[i] 321 } 322 return sa, nil 323 324 case AF_INET6: 325 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 326 sa := new(SockaddrInet6) 327 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 328 sa.Port = int(p[0])<<8 + int(p[1]) 329 sa.ZoneId = pp.Scope_id 330 for i := 0; i < len(sa.Addr); i++ { 331 sa.Addr[i] = pp.Addr[i] 332 } 333 return sa, nil 334 } 335 return nil, EAFNOSUPPORT 336 } 337 338 //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept 339 340 func Accept(fd int) (nfd int, sa Sockaddr, err error) { 341 var rsa RawSockaddrAny 342 var len _Socklen = SizeofSockaddrAny 343 nfd, err = accept(fd, &rsa, &len) 344 if err != nil { 345 return 346 } 347 sa, err = anyToSockaddr(&rsa) 348 if err != nil { 349 Close(nfd) 350 nfd = 0 351 } 352 return 353 } 354 355 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { 356 var msg Msghdr 357 var rsa RawSockaddrAny 358 msg.Name = (*byte)(unsafe.Pointer(&rsa)) 359 msg.Namelen = uint32(SizeofSockaddrAny) 360 var iov Iovec 361 if len(p) > 0 { 362 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 363 iov.SetLen(len(p)) 364 } 365 var dummy int8 366 if len(oob) > 0 { 367 // receive at least one normal byte 368 if len(p) == 0 { 369 iov.Base = &dummy 370 iov.SetLen(1) 371 } 372 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 373 msg.Accrightslen = int32(len(oob)) 374 } 375 msg.Iov = &iov 376 msg.Iovlen = 1 377 if n, err = recvmsg(fd, &msg, flags); err != nil { 378 return 379 } 380 oobn = int(msg.Accrightslen) 381 // source address is only specified if the socket is unconnected 382 if rsa.Addr.Family != AF_UNSPEC { 383 from, err = anyToSockaddr(&rsa) 384 } 385 return 386 } 387 388 func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { 389 _, err = SendmsgN(fd, p, oob, to, flags) 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, to Sockaddr, flags int) (n int, err error) { 396 var ptr unsafe.Pointer 397 var salen _Socklen 398 if to != nil { 399 ptr, salen, err = to.sockaddr() 400 if err != nil { 401 return 0, err 402 } 403 } 404 var msg Msghdr 405 msg.Name = (*byte)(unsafe.Pointer(ptr)) 406 msg.Namelen = uint32(salen) 407 var iov Iovec 408 if len(p) > 0 { 409 iov.Base = (*int8)(unsafe.Pointer(&p[0])) 410 iov.SetLen(len(p)) 411 } 412 var dummy int8 413 if len(oob) > 0 { 414 // send at least one normal byte 415 if len(p) == 0 { 416 iov.Base = &dummy 417 iov.SetLen(1) 418 } 419 msg.Accrights = (*int8)(unsafe.Pointer(&oob[0])) 420 msg.Accrightslen = int32(len(oob)) 421 } 422 msg.Iov = &iov 423 msg.Iovlen = 1 424 if n, err = sendmsg(fd, &msg, flags); err != nil { 425 return 0, err 426 } 427 if len(oob) > 0 && len(p) == 0 { 428 n = 0 429 } 430 return n, nil 431 } 432 433 /* 434 * Exposed directly 435 */ 436 //sys Access(path string, mode uint32) (err error) 437 //sys Adjtime(delta *Timeval, olddelta *Timeval) (err error) 438 //sys Chdir(path string) (err error) 439 //sys Chmod(path string, mode uint32) (err error) 440 //sys Chown(path string, uid int, gid int) (err error) 441 //sys Chroot(path string) (err error) 442 //sys Close(fd int) (err error) 443 //sys Dup(fd int) (nfd int, err error) 444 //sys Exit(code int) 445 //sys Fchdir(fd int) (err error) 446 //sys Fchmod(fd int, mode uint32) (err error) 447 //sys Fchown(fd int, uid int, gid int) (err error) 448 //sys Fpathconf(fd int, name int) (val int, err error) 449 //sys Fstat(fd int, stat *Stat_t) (err error) 450 //sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error) 451 //sysnb Getgid() (gid int) 452 //sysnb Getpid() (pid int) 453 //sys Geteuid() (euid int) 454 //sys Getegid() (egid int) 455 //sys Getppid() (ppid int) 456 //sys Getpriority(which int, who int) (n int, err error) 457 //sysnb Getrlimit(which int, lim *Rlimit) (err error) 458 //sysnb Gettimeofday(tv *Timeval) (err error) 459 //sysnb Getuid() (uid int) 460 //sys Kill(pid int, signum Signal) (err error) 461 //sys Lchown(path string, uid int, gid int) (err error) 462 //sys Link(path string, link string) (err error) 463 //sys Listen(s int, backlog int) (err error) = libsocket.__xnet_listen 464 //sys Lstat(path string, stat *Stat_t) (err error) 465 //sys Mkdir(path string, mode uint32) (err error) 466 //sys Mknod(path string, mode uint32, dev int) (err error) 467 //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) 468 //sys Open(path string, mode int, perm uint32) (fd int, err error) 469 //sys Pathconf(path string, name int) (val int, err error) 470 //sys Pread(fd int, p []byte, offset int64) (n int, err error) 471 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) 472 //sys read(fd int, p []byte) (n int, err error) 473 //sys Readlink(path string, buf []byte) (n int, err error) 474 //sys Rename(from string, to string) (err error) 475 //sys Rmdir(path string) (err error) 476 //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek 477 //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile 478 //sysnb Setegid(egid int) (err error) 479 //sysnb Seteuid(euid int) (err error) 480 //sysnb Setgid(gid int) (err error) 481 //sysnb Setpgid(pid int, pgid int) (err error) 482 //sys Setpriority(which int, who int, prio int) (err error) 483 //sysnb Setregid(rgid int, egid int) (err error) 484 //sysnb Setreuid(ruid int, euid int) (err error) 485 //sysnb Setrlimit(which int, lim *Rlimit) (err error) 486 //sysnb Setsid() (pid int, err error) 487 //sysnb Setuid(uid int) (err error) 488 //sys Shutdown(s int, how int) (err error) = libsocket.shutdown 489 //sys Stat(path string, stat *Stat_t) (err error) 490 //sys Symlink(path string, link string) (err error) 491 //sys Sync() (err error) 492 //sys Truncate(path string, length int64) (err error) 493 //sys Fsync(fd int) (err error) 494 //sys Ftruncate(fd int, length int64) (err error) 495 //sys Umask(newmask int) (oldmask int) 496 //sys Unlink(path string) (err error) 497 //sys utimes(path string, times *[2]Timeval) (err error) 498 //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind 499 //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect 500 //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) 501 //sys munmap(addr uintptr, length uintptr) (err error) 502 //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto 503 //sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket 504 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair 505 //sys write(fd int, p []byte) (n int, err error) 506 //sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt 507 //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername 508 //sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname 509 //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt 510 //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom 511 //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg 512 //sys getexecname() (path unsafe.Pointer, err error) = libc.getexecname 513 514 func Getexecname() (path string, err error) { 515 ptr, err := getexecname() 516 if err != nil { 517 return "", err 518 } 519 bytes := (*[1 << 29]byte)(ptr)[:] 520 for i, b := range bytes { 521 if b == 0 { 522 return string(bytes[:i]), nil 523 } 524 } 525 panic("unreachable") 526 } 527 528 func readlen(fd int, buf *byte, nbuf int) (n int, err error) { 529 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_read)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 530 n = int(r0) 531 if e1 != 0 { 532 err = e1 533 } 534 return 535 } 536 537 func writelen(fd int, buf *byte, nbuf int) (n int, err error) { 538 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_write)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0) 539 n = int(r0) 540 if e1 != 0 { 541 err = e1 542 } 543 return 544 } 545 546 func Utimes(path string, tv []Timeval) error { 547 if len(tv) != 2 { 548 return EINVAL 549 } 550 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 551 } 552