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//go: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 syscall 14 15import ( 16 "runtime" 17 "unsafe" 18) 19 20const ImplementsGetwd = true 21 22func Getwd() (string, error) { 23 var buf [pathMax]byte 24 _, err := getcwd(buf[:]) 25 if err != nil { 26 return "", err 27 } 28 n := clen(buf[:]) 29 if n < 1 { 30 return "", EINVAL 31 } 32 return string(buf[:n]), nil 33} 34 35/* 36 * Wrapped 37 */ 38 39//sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error) 40//sysnb setgroups(ngid int, gid *_Gid_t) (err error) 41 42func Getgroups() (gids []int, err error) { 43 n, err := getgroups(0, nil) 44 if err != nil { 45 return nil, err 46 } 47 if n == 0 { 48 return nil, nil 49 } 50 51 // Sanity check group count. Max is 16 on BSD. 52 if n < 0 || n > 1000 { 53 return nil, EINVAL 54 } 55 56 a := make([]_Gid_t, n) 57 n, err = getgroups(n, &a[0]) 58 if err != nil { 59 return nil, err 60 } 61 gids = make([]int, n) 62 for i, v := range a[0:n] { 63 gids[i] = int(v) 64 } 65 return 66} 67 68func Setgroups(gids []int) (err error) { 69 if len(gids) == 0 { 70 return setgroups(0, nil) 71 } 72 73 a := make([]_Gid_t, len(gids)) 74 for i, v := range gids { 75 a[i] = _Gid_t(v) 76 } 77 return setgroups(len(a), &a[0]) 78} 79 80func ReadDirent(fd int, buf []byte) (n int, err error) { 81 // Final argument is (basep *uintptr) and the syscall doesn't take nil. 82 // 64 bits should be enough. (32 bits isn't even on 386). Since the 83 // actual system call is getdirentries64, 64 is a good guess. 84 // TODO(rsc): Can we use a single global basep for all calls? 85 var base = (*uintptr)(unsafe.Pointer(new(uint64))) 86 return Getdirentries(fd, buf, base) 87} 88 89// Wait status is 7 bits at bottom, either 0 (exited), 90// 0x7F (stopped), or a signal number that caused an exit. 91// The 0x80 bit is whether there was a core dump. 92// An extra number (exit code, signal causing a stop) 93// is in the high bits. 94 95type WaitStatus uint32 96 97const ( 98 mask = 0x7F 99 core = 0x80 100 shift = 8 101 102 exited = 0 103 stopped = 0x7F 104) 105 106func (w WaitStatus) Exited() bool { return w&mask == exited } 107 108func (w WaitStatus) ExitStatus() int { 109 if w&mask != exited { 110 return -1 111 } 112 return int(w >> shift) 113} 114 115func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 } 116 117func (w WaitStatus) Signal() Signal { 118 sig := Signal(w & mask) 119 if sig == stopped || sig == 0 { 120 return -1 121 } 122 return sig 123} 124 125func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } 126 127func (w WaitStatus) Stopped() bool { return w&mask == stopped && Signal(w>>shift) != SIGSTOP } 128 129func (w WaitStatus) Continued() bool { return w&mask == stopped && Signal(w>>shift) == SIGSTOP } 130 131func (w WaitStatus) StopSignal() Signal { 132 if !w.Stopped() { 133 return -1 134 } 135 return Signal(w>>shift) & 0xFF 136} 137 138func (w WaitStatus) TrapCause() int { return -1 } 139 140//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) 141 142func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 143 var status _C_int 144 wpid, err = wait4(pid, &status, options, rusage) 145 if wstatus != nil { 146 *wstatus = WaitStatus(status) 147 } 148 return 149} 150 151//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) 152//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 153//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) 154//sysnb socket(domain int, typ int, proto int) (fd int, err error) 155//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) 156//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) 157//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 158//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) 159//sys Shutdown(s int, how int) (err error) 160 161func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 162 if sa.Port < 0 || sa.Port > 0xFFFF { 163 return nil, 0, EINVAL 164 } 165 sa.raw.Len = SizeofSockaddrInet4 166 sa.raw.Family = AF_INET 167 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 168 p[0] = byte(sa.Port >> 8) 169 p[1] = byte(sa.Port) 170 sa.raw.Addr = sa.Addr 171 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 172} 173 174func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 175 if sa.Port < 0 || sa.Port > 0xFFFF { 176 return nil, 0, EINVAL 177 } 178 sa.raw.Len = SizeofSockaddrInet6 179 sa.raw.Family = AF_INET6 180 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 181 p[0] = byte(sa.Port >> 8) 182 p[1] = byte(sa.Port) 183 sa.raw.Scope_id = sa.ZoneId 184 sa.raw.Addr = sa.Addr 185 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 186} 187 188func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 189 name := sa.Name 190 n := len(name) 191 if n >= len(sa.raw.Path) || n == 0 { 192 return nil, 0, EINVAL 193 } 194 sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL 195 sa.raw.Family = AF_UNIX 196 for i := 0; i < n; i++ { 197 sa.raw.Path[i] = int8(name[i]) 198 } 199 return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil 200} 201 202func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) { 203 if sa.Index == 0 { 204 return nil, 0, EINVAL 205 } 206 sa.raw.Len = sa.Len 207 sa.raw.Family = AF_LINK 208 sa.raw.Index = sa.Index 209 sa.raw.Type = sa.Type 210 sa.raw.Nlen = sa.Nlen 211 sa.raw.Alen = sa.Alen 212 sa.raw.Slen = sa.Slen 213 sa.raw.Data = sa.Data 214 return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil 215} 216 217func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { 218 switch rsa.Addr.Family { 219 case AF_LINK: 220 pp := (*RawSockaddrDatalink)(unsafe.Pointer(rsa)) 221 sa := new(SockaddrDatalink) 222 sa.Len = pp.Len 223 sa.Family = pp.Family 224 sa.Index = pp.Index 225 sa.Type = pp.Type 226 sa.Nlen = pp.Nlen 227 sa.Alen = pp.Alen 228 sa.Slen = pp.Slen 229 sa.Data = pp.Data 230 return sa, nil 231 232 case AF_UNIX: 233 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 234 if pp.Len < 2 || pp.Len > SizeofSockaddrUnix { 235 return nil, EINVAL 236 } 237 sa := new(SockaddrUnix) 238 239 // Some BSDs include the trailing NUL in the length, whereas 240 // others do not. Work around this by subtracting the leading 241 // family and len. The path is then scanned to see if a NUL 242 // terminator still exists within the length. 243 n := int(pp.Len) - 2 // subtract leading Family, Len 244 for i := 0; i < n; i++ { 245 if pp.Path[i] == 0 { 246 // found early NUL; assume Len included the NUL 247 // or was overestimating. 248 n = i 249 break 250 } 251 } 252 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) 253 return sa, nil 254 255 case AF_INET: 256 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 257 sa := new(SockaddrInet4) 258 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 259 sa.Port = int(p[0])<<8 + int(p[1]) 260 sa.Addr = pp.Addr 261 return sa, nil 262 263 case AF_INET6: 264 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 265 sa := new(SockaddrInet6) 266 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 267 sa.Port = int(p[0])<<8 + int(p[1]) 268 sa.ZoneId = pp.Scope_id 269 sa.Addr = pp.Addr 270 return sa, nil 271 } 272 return nil, EAFNOSUPPORT 273} 274 275func Accept(fd int) (nfd int, sa Sockaddr, err error) { 276 var rsa RawSockaddrAny 277 var len _Socklen = SizeofSockaddrAny 278 nfd, err = accept(fd, &rsa, &len) 279 if err != nil { 280 return 281 } 282 if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && len == 0 { 283 // Accepted socket has no address. 284 // This is likely due to a bug in xnu kernels, 285 // where instead of ECONNABORTED error socket 286 // is accepted, but has no address. 287 Close(nfd) 288 return 0, nil, ECONNABORTED 289 } 290 sa, err = anyToSockaddr(&rsa) 291 if err != nil { 292 Close(nfd) 293 nfd = 0 294 } 295 return 296} 297 298func Getsockname(fd int) (sa Sockaddr, err error) { 299 var rsa RawSockaddrAny 300 var len _Socklen = SizeofSockaddrAny 301 if err = getsockname(fd, &rsa, &len); err != nil { 302 return 303 } 304 // TODO(jsing): DragonFly has a "bug" (see issue 3349), which should be 305 // reported upstream. 306 if runtime.GOOS == "dragonfly" && rsa.Addr.Family == AF_UNSPEC && rsa.Addr.Len == 0 { 307 rsa.Addr.Family = AF_UNIX 308 rsa.Addr.Len = SizeofSockaddrUnix 309 } 310 return anyToSockaddr(&rsa) 311} 312 313//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) 314 315func GetsockoptByte(fd, level, opt int) (value byte, err error) { 316 var n byte 317 vallen := _Socklen(1) 318 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 319 return n, err 320} 321 322func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { 323 vallen := _Socklen(4) 324 err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) 325 return value, err 326} 327 328func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { 329 var value IPMreq 330 vallen := _Socklen(SizeofIPMreq) 331 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 332 return &value, err 333} 334 335func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { 336 var value IPv6Mreq 337 vallen := _Socklen(SizeofIPv6Mreq) 338 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 339 return &value, err 340} 341 342func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) { 343 var value IPv6MTUInfo 344 vallen := _Socklen(SizeofIPv6MTUInfo) 345 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 346 return &value, err 347} 348 349func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { 350 var value ICMPv6Filter 351 vallen := _Socklen(SizeofICMPv6Filter) 352 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 353 return &value, err 354} 355 356//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) 357//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) 358//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) 359 360func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { 361 var msg Msghdr 362 msg.Name = (*byte)(unsafe.Pointer(rsa)) 363 msg.Namelen = uint32(SizeofSockaddrAny) 364 var iov Iovec 365 if len(p) > 0 { 366 iov.Base = &p[0] 367 iov.SetLen(len(p)) 368 } 369 var dummy byte 370 if len(oob) > 0 { 371 // receive at least one normal byte 372 if len(p) == 0 { 373 iov.Base = &dummy 374 iov.SetLen(1) 375 } 376 msg.Control = &oob[0] 377 msg.SetControllen(len(oob)) 378 } 379 msg.Iov = &iov 380 msg.Iovlen = 1 381 if n, err = recvmsg(fd, &msg, flags); err != nil { 382 return 383 } 384 oobn = int(msg.Controllen) 385 recvflags = int(msg.Flags) 386 return 387} 388 389//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) 390 391func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { 392 var msg Msghdr 393 msg.Name = (*byte)(ptr) 394 msg.Namelen = uint32(salen) 395 var iov Iovec 396 if len(p) > 0 { 397 iov.Base = &p[0] 398 iov.SetLen(len(p)) 399 } 400 var dummy byte 401 if len(oob) > 0 { 402 // send at least one normal byte 403 if len(p) == 0 { 404 iov.Base = &dummy 405 iov.SetLen(1) 406 } 407 msg.Control = &oob[0] 408 msg.SetControllen(len(oob)) 409 } 410 msg.Iov = &iov 411 msg.Iovlen = 1 412 if n, err = sendmsg(fd, &msg, flags); err != nil { 413 return 0, err 414 } 415 if len(oob) > 0 && len(p) == 0 { 416 n = 0 417 } 418 return n, nil 419} 420 421//sys kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) 422 423func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err error) { 424 var change, event unsafe.Pointer 425 if len(changes) > 0 { 426 change = unsafe.Pointer(&changes[0]) 427 } 428 if len(events) > 0 { 429 event = unsafe.Pointer(&events[0]) 430 } 431 return kevent(kq, change, len(changes), event, len(events), timeout) 432} 433 434func Sysctl(name string) (value string, err error) { 435 // Translate name to mib number. 436 mib, err := nametomib(name) 437 if err != nil { 438 return "", err 439 } 440 441 // Find size. 442 n := uintptr(0) 443 if err = sysctl(mib, nil, &n, nil, 0); err != nil { 444 return "", err 445 } 446 if n == 0 { 447 return "", nil 448 } 449 450 // Read into buffer of that size. 451 buf := make([]byte, n) 452 if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil { 453 return "", err 454 } 455 456 // Throw away terminating NUL. 457 if n > 0 && buf[n-1] == '\x00' { 458 n-- 459 } 460 return string(buf[0:n]), nil 461} 462 463func SysctlUint32(name string) (value uint32, err error) { 464 // Translate name to mib number. 465 mib, err := nametomib(name) 466 if err != nil { 467 return 0, err 468 } 469 470 // Read into buffer of that size. 471 n := uintptr(4) 472 buf := make([]byte, 4) 473 if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil { 474 return 0, err 475 } 476 if n != 4 { 477 return 0, EIO 478 } 479 return *(*uint32)(unsafe.Pointer(&buf[0])), nil 480} 481 482//sys utimes(path string, timeval *[2]Timeval) (err error) 483 484func Utimes(path string, tv []Timeval) (err error) { 485 if len(tv) != 2 { 486 return EINVAL 487 } 488 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 489} 490 491func UtimesNano(path string, ts []Timespec) error { 492 if len(ts) != 2 { 493 return EINVAL 494 } 495 err := utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) 496 if err != ENOSYS { 497 return err 498 } 499 // Not as efficient as it could be because Timespec and 500 // Timeval have different types in the different OSes 501 tv := [2]Timeval{ 502 NsecToTimeval(TimespecToNsec(ts[0])), 503 NsecToTimeval(TimespecToNsec(ts[1])), 504 } 505 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 506} 507 508//sys futimes(fd int, timeval *[2]Timeval) (err error) 509 510func Futimes(fd int, tv []Timeval) (err error) { 511 if len(tv) != 2 { 512 return EINVAL 513 } 514 return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 515} 516 517//sys fcntl(fd int, cmd int, arg int) (val int, err error) 518//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) = SYS_FCNTL 519//sysnb ioctl(fd int, req int, arg int) (err error) 520//sysnb ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL 521 522var mapper = &mmapper{ 523 active: make(map[*byte][]byte), 524 mmap: mmap, 525 munmap: munmap, 526} 527 528func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 529 return mapper.Mmap(fd, offset, length, prot, flags) 530} 531 532func Munmap(b []byte) (err error) { 533 return mapper.Munmap(b) 534} 535