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// +build darwin dragonfly freebsd netbsd openbsd 6 7// BSD system call wrappers shared by *BSD based systems 8// including OS X (Darwin) and FreeBSD. Like the other 9// syscall_*.go files it is compiled as Go code but also 10// used as input to mksyscall which parses the //sys 11// lines and generates system call stubs. 12 13package unix 14 15import ( 16 "runtime" 17 "syscall" 18 "unsafe" 19) 20 21/* 22 * Wrapped 23 */ 24 25//sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error) 26//sysnb setgroups(ngid int, gid *_Gid_t) (err error) 27 28func Getgroups() (gids []int, err error) { 29 n, err := getgroups(0, nil) 30 if err != nil { 31 return nil, err 32 } 33 if n == 0 { 34 return nil, nil 35 } 36 37 // Sanity check group count. Max is 16 on BSD. 38 if n < 0 || n > 1000 { 39 return nil, EINVAL 40 } 41 42 a := make([]_Gid_t, n) 43 n, err = getgroups(n, &a[0]) 44 if err != nil { 45 return nil, err 46 } 47 gids = make([]int, n) 48 for i, v := range a[0:n] { 49 gids[i] = int(v) 50 } 51 return 52} 53 54func Setgroups(gids []int) (err error) { 55 if len(gids) == 0 { 56 return setgroups(0, nil) 57 } 58 59 a := make([]_Gid_t, len(gids)) 60 for i, v := range gids { 61 a[i] = _Gid_t(v) 62 } 63 return setgroups(len(a), &a[0]) 64} 65 66// Wait status is 7 bits at bottom, either 0 (exited), 67// 0x7F (stopped), or a signal number that caused an exit. 68// The 0x80 bit is whether there was a core dump. 69// An extra number (exit code, signal causing a stop) 70// is in the high bits. 71 72type WaitStatus uint32 73 74const ( 75 mask = 0x7F 76 core = 0x80 77 shift = 8 78 79 exited = 0 80 killed = 9 81 stopped = 0x7F 82) 83 84func (w WaitStatus) Exited() bool { return w&mask == exited } 85 86func (w WaitStatus) ExitStatus() int { 87 if w&mask != exited { 88 return -1 89 } 90 return int(w >> shift) 91} 92 93func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 } 94 95func (w WaitStatus) Signal() syscall.Signal { 96 sig := syscall.Signal(w & mask) 97 if sig == stopped || sig == 0 { 98 return -1 99 } 100 return sig 101} 102 103func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } 104 105func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP } 106 107func (w WaitStatus) Killed() bool { return w&mask == killed && syscall.Signal(w>>shift) != SIGKILL } 108 109func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP } 110 111func (w WaitStatus) StopSignal() syscall.Signal { 112 if !w.Stopped() { 113 return -1 114 } 115 return syscall.Signal(w>>shift) & 0xFF 116} 117 118func (w WaitStatus) TrapCause() int { return -1 } 119 120//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) 121 122func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 123 var status _C_int 124 wpid, err = wait4(pid, &status, options, rusage) 125 if wstatus != nil { 126 *wstatus = WaitStatus(status) 127 } 128 return 129} 130 131//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) 132//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 133//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 134//sysnb socket(domain int, typ int, proto int) (fd int, err error) 135//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) 136//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) 137//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 138//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 139//sys Shutdown(s int, how int) (err error) 140 141func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 142 if sa.Port < 0 || sa.Port > 0xFFFF { 143 return nil, 0, EINVAL 144 } 145 sa.raw.Len = SizeofSockaddrInet4 146 sa.raw.Family = AF_INET 147 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 148 p[0] = byte(sa.Port >> 8) 149 p[1] = byte(sa.Port) 150 for i := 0; i < len(sa.Addr); i++ { 151 sa.raw.Addr[i] = sa.Addr[i] 152 } 153 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 154} 155 156func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 157 if sa.Port < 0 || sa.Port > 0xFFFF { 158 return nil, 0, EINVAL 159 } 160 sa.raw.Len = SizeofSockaddrInet6 161 sa.raw.Family = AF_INET6 162 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 163 p[0] = byte(sa.Port >> 8) 164 p[1] = byte(sa.Port) 165 sa.raw.Scope_id = sa.ZoneId 166 for i := 0; i < len(sa.Addr); i++ { 167 sa.raw.Addr[i] = sa.Addr[i] 168 } 169 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 170} 171 172func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 173 name := sa.Name 174 n := len(name) 175 if n >= len(sa.raw.Path) || n == 0 { 176 return nil, 0, EINVAL 177 } 178 sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL 179 sa.raw.Family = AF_UNIX 180 for i := 0; i < n; i++ { 181 sa.raw.Path[i] = int8(name[i]) 182 } 183 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 184} 185 186func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) { 187 if sa.Index == 0 { 188 return nil, 0, EINVAL 189 } 190 sa.raw.Len = sa.Len 191 sa.raw.Family = AF_LINK 192 sa.raw.Index = sa.Index 193 sa.raw.Type = sa.Type 194 sa.raw.Nlen = sa.Nlen 195 sa.raw.Alen = sa.Alen 196 sa.raw.Slen = sa.Slen 197 for i := 0; i < len(sa.raw.Data); i++ { 198 sa.raw.Data[i] = sa.Data[i] 199 } 200 return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil 201} 202 203func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { 204 switch rsa.Addr.Family { 205 case AF_LINK: 206 pp := (*RawSockaddrDatalink)(unsafe.Pointer(rsa)) 207 sa := new(SockaddrDatalink) 208 sa.Len = pp.Len 209 sa.Family = pp.Family 210 sa.Index = pp.Index 211 sa.Type = pp.Type 212 sa.Nlen = pp.Nlen 213 sa.Alen = pp.Alen 214 sa.Slen = pp.Slen 215 for i := 0; i < len(sa.Data); i++ { 216 sa.Data[i] = pp.Data[i] 217 } 218 return sa, nil 219 220 case AF_UNIX: 221 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 222 if pp.Len < 2 || pp.Len > SizeofSockaddrUnix { 223 return nil, EINVAL 224 } 225 sa := new(SockaddrUnix) 226 227 // Some BSDs include the trailing NUL in the length, whereas 228 // others do not. Work around this by subtracting the leading 229 // family and len. The path is then scanned to see if a NUL 230 // terminator still exists within the length. 231 n := int(pp.Len) - 2 // subtract leading Family, Len 232 for i := 0; i < n; i++ { 233 if pp.Path[i] == 0 { 234 // found early NUL; assume Len included the NUL 235 // or was overestimating. 236 n = i 237 break 238 } 239 } 240 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] 241 sa.Name = string(bytes) 242 return sa, nil 243 244 case AF_INET: 245 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 246 sa := new(SockaddrInet4) 247 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 248 sa.Port = int(p[0])<<8 + int(p[1]) 249 for i := 0; i < len(sa.Addr); i++ { 250 sa.Addr[i] = pp.Addr[i] 251 } 252 return sa, nil 253 254 case AF_INET6: 255 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 256 sa := new(SockaddrInet6) 257 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 258 sa.Port = int(p[0])<<8 + int(p[1]) 259 sa.ZoneId = pp.Scope_id 260 for i := 0; i < len(sa.Addr); i++ { 261 sa.Addr[i] = pp.Addr[i] 262 } 263 return sa, nil 264 } 265 return nil, EAFNOSUPPORT 266} 267 268func Accept(fd int) (nfd int, sa Sockaddr, err error) { 269 var rsa RawSockaddrAny 270 var len _Socklen = SizeofSockaddrAny 271 nfd, err = accept(fd, &rsa, &len) 272 if err != nil { 273 return 274 } 275 if runtime.GOOS == "darwin" && len == 0 { 276 // Accepted socket has no address. 277 // This is likely due to a bug in xnu kernels, 278 // where instead of ECONNABORTED error socket 279 // is accepted, but has no address. 280 Close(nfd) 281 return 0, nil, ECONNABORTED 282 } 283 sa, err = anyToSockaddr(fd, &rsa) 284 if err != nil { 285 Close(nfd) 286 nfd = 0 287 } 288 return 289} 290 291func Getsockname(fd int) (sa Sockaddr, err error) { 292 var rsa RawSockaddrAny 293 var len _Socklen = SizeofSockaddrAny 294 if err = getsockname(fd, &rsa, &len); err != nil { 295 return 296 } 297 // TODO(jsing): DragonFly has a "bug" (see issue 3349), which should be 298 // reported upstream. 299 if runtime.GOOS == "dragonfly" && rsa.Addr.Family == AF_UNSPEC && rsa.Addr.Len == 0 { 300 rsa.Addr.Family = AF_UNIX 301 rsa.Addr.Len = SizeofSockaddrUnix 302 } 303 return anyToSockaddr(fd, &rsa) 304} 305 306//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) 307 308// GetsockoptString returns the string value of the socket option opt for the 309// socket associated with fd at the given socket level. 310func GetsockoptString(fd, level, opt int) (string, error) { 311 buf := make([]byte, 256) 312 vallen := _Socklen(len(buf)) 313 err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen) 314 if err != nil { 315 return "", err 316 } 317 return string(buf[:vallen-1]), nil 318} 319 320//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) 321//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) 322//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) 323 324func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { 325 var msg Msghdr 326 var rsa RawSockaddrAny 327 msg.Name = (*byte)(unsafe.Pointer(&rsa)) 328 msg.Namelen = uint32(SizeofSockaddrAny) 329 var iov Iovec 330 if len(p) > 0 { 331 iov.Base = (*byte)(unsafe.Pointer(&p[0])) 332 iov.SetLen(len(p)) 333 } 334 var dummy byte 335 if len(oob) > 0 { 336 // receive at least one normal byte 337 if len(p) == 0 { 338 iov.Base = &dummy 339 iov.SetLen(1) 340 } 341 msg.Control = (*byte)(unsafe.Pointer(&oob[0])) 342 msg.SetControllen(len(oob)) 343 } 344 msg.Iov = &iov 345 msg.Iovlen = 1 346 if n, err = recvmsg(fd, &msg, flags); err != nil { 347 return 348 } 349 oobn = int(msg.Controllen) 350 recvflags = int(msg.Flags) 351 // source address is only specified if the socket is unconnected 352 if rsa.Addr.Family != AF_UNSPEC { 353 from, err = anyToSockaddr(fd, &rsa) 354 } 355 return 356} 357 358//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) 359 360func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { 361 _, err = SendmsgN(fd, p, oob, to, flags) 362 return 363} 364 365func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { 366 var ptr unsafe.Pointer 367 var salen _Socklen 368 if to != nil { 369 ptr, salen, err = to.sockaddr() 370 if err != nil { 371 return 0, err 372 } 373 } 374 var msg Msghdr 375 msg.Name = (*byte)(unsafe.Pointer(ptr)) 376 msg.Namelen = uint32(salen) 377 var iov Iovec 378 if len(p) > 0 { 379 iov.Base = (*byte)(unsafe.Pointer(&p[0])) 380 iov.SetLen(len(p)) 381 } 382 var dummy byte 383 if len(oob) > 0 { 384 // send at least one normal byte 385 if len(p) == 0 { 386 iov.Base = &dummy 387 iov.SetLen(1) 388 } 389 msg.Control = (*byte)(unsafe.Pointer(&oob[0])) 390 msg.SetControllen(len(oob)) 391 } 392 msg.Iov = &iov 393 msg.Iovlen = 1 394 if n, err = sendmsg(fd, &msg, flags); err != nil { 395 return 0, err 396 } 397 if len(oob) > 0 && len(p) == 0 { 398 n = 0 399 } 400 return n, nil 401} 402 403//sys kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) 404 405func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err error) { 406 var change, event unsafe.Pointer 407 if len(changes) > 0 { 408 change = unsafe.Pointer(&changes[0]) 409 } 410 if len(events) > 0 { 411 event = unsafe.Pointer(&events[0]) 412 } 413 return kevent(kq, change, len(changes), event, len(events), timeout) 414} 415 416// sysctlmib translates name to mib number and appends any additional args. 417func sysctlmib(name string, args ...int) ([]_C_int, error) { 418 // Translate name to mib number. 419 mib, err := nametomib(name) 420 if err != nil { 421 return nil, err 422 } 423 424 for _, a := range args { 425 mib = append(mib, _C_int(a)) 426 } 427 428 return mib, nil 429} 430 431func Sysctl(name string) (string, error) { 432 return SysctlArgs(name) 433} 434 435func SysctlArgs(name string, args ...int) (string, error) { 436 buf, err := SysctlRaw(name, args...) 437 if err != nil { 438 return "", err 439 } 440 n := len(buf) 441 442 // Throw away terminating NUL. 443 if n > 0 && buf[n-1] == '\x00' { 444 n-- 445 } 446 return string(buf[0:n]), nil 447} 448 449func SysctlUint32(name string) (uint32, error) { 450 return SysctlUint32Args(name) 451} 452 453func SysctlUint32Args(name string, args ...int) (uint32, error) { 454 mib, err := sysctlmib(name, args...) 455 if err != nil { 456 return 0, err 457 } 458 459 n := uintptr(4) 460 buf := make([]byte, 4) 461 if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil { 462 return 0, err 463 } 464 if n != 4 { 465 return 0, EIO 466 } 467 return *(*uint32)(unsafe.Pointer(&buf[0])), nil 468} 469 470func SysctlUint64(name string, args ...int) (uint64, error) { 471 mib, err := sysctlmib(name, args...) 472 if err != nil { 473 return 0, err 474 } 475 476 n := uintptr(8) 477 buf := make([]byte, 8) 478 if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil { 479 return 0, err 480 } 481 if n != 8 { 482 return 0, EIO 483 } 484 return *(*uint64)(unsafe.Pointer(&buf[0])), nil 485} 486 487func SysctlRaw(name string, args ...int) ([]byte, error) { 488 mib, err := sysctlmib(name, args...) 489 if err != nil { 490 return nil, err 491 } 492 493 // Find size. 494 n := uintptr(0) 495 if err := sysctl(mib, nil, &n, nil, 0); err != nil { 496 return nil, err 497 } 498 if n == 0 { 499 return nil, nil 500 } 501 502 // Read into buffer of that size. 503 buf := make([]byte, n) 504 if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil { 505 return nil, err 506 } 507 508 // The actual call may return less than the original reported required 509 // size so ensure we deal with that. 510 return buf[:n], nil 511} 512 513func SysctlClockinfo(name string) (*Clockinfo, error) { 514 mib, err := sysctlmib(name) 515 if err != nil { 516 return nil, err 517 } 518 519 n := uintptr(SizeofClockinfo) 520 var ci Clockinfo 521 if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil { 522 return nil, err 523 } 524 if n != SizeofClockinfo { 525 return nil, EIO 526 } 527 return &ci, nil 528} 529 530func SysctlTimeval(name string) (*Timeval, error) { 531 mib, err := sysctlmib(name) 532 if err != nil { 533 return nil, err 534 } 535 536 var tv Timeval 537 n := uintptr(unsafe.Sizeof(tv)) 538 if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil { 539 return nil, err 540 } 541 if n != unsafe.Sizeof(tv) { 542 return nil, EIO 543 } 544 return &tv, nil 545} 546 547//sys utimes(path string, timeval *[2]Timeval) (err error) 548 549func Utimes(path string, tv []Timeval) error { 550 if tv == nil { 551 return utimes(path, nil) 552 } 553 if len(tv) != 2 { 554 return EINVAL 555 } 556 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 557} 558 559func UtimesNano(path string, ts []Timespec) error { 560 if ts == nil { 561 err := utimensat(AT_FDCWD, path, nil, 0) 562 if err != ENOSYS { 563 return err 564 } 565 return utimes(path, nil) 566 } 567 if len(ts) != 2 { 568 return EINVAL 569 } 570 // Darwin setattrlist can set nanosecond timestamps 571 err := setattrlistTimes(path, ts, 0) 572 if err != ENOSYS { 573 return err 574 } 575 err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) 576 if err != ENOSYS { 577 return err 578 } 579 // Not as efficient as it could be because Timespec and 580 // Timeval have different types in the different OSes 581 tv := [2]Timeval{ 582 NsecToTimeval(TimespecToNsec(ts[0])), 583 NsecToTimeval(TimespecToNsec(ts[1])), 584 } 585 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 586} 587 588func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { 589 if ts == nil { 590 return utimensat(dirfd, path, nil, flags) 591 } 592 if len(ts) != 2 { 593 return EINVAL 594 } 595 err := setattrlistTimes(path, ts, flags) 596 if err != ENOSYS { 597 return err 598 } 599 return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) 600} 601 602//sys futimes(fd int, timeval *[2]Timeval) (err error) 603 604func Futimes(fd int, tv []Timeval) error { 605 if tv == nil { 606 return futimes(fd, nil) 607 } 608 if len(tv) != 2 { 609 return EINVAL 610 } 611 return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 612} 613 614//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) 615 616func Poll(fds []PollFd, timeout int) (n int, err error) { 617 if len(fds) == 0 { 618 return poll(nil, 0, timeout) 619 } 620 return poll(&fds[0], len(fds), timeout) 621} 622 623// TODO: wrap 624// Acct(name nil-string) (err error) 625// Gethostuuid(uuid *byte, timeout *Timespec) (err error) 626// Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error) 627 628var mapper = &mmapper{ 629 active: make(map[*byte][]byte), 630 mmap: mmap, 631 munmap: munmap, 632} 633 634func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 635 return mapper.Mmap(fd, offset, length, prot, flags) 636} 637 638func Munmap(b []byte) (err error) { 639 return mapper.Munmap(b) 640} 641 642//sys Madvise(b []byte, behav int) (err error) 643//sys Mlock(b []byte) (err error) 644//sys Mlockall(flags int) (err error) 645//sys Mprotect(b []byte, prot int) (err error) 646//sys Msync(b []byte, flags int) (err error) 647//sys Munlock(b []byte) (err error) 648//sys Munlockall() (err error) 649