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