// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin dragonfly freebsd netbsd openbsd

// BSD system call wrappers shared by *BSD based systems
// including OS X (Darwin) and FreeBSD.  Like the other
// syscall_*.go files it is compiled as Go code but also
// used as input to mksyscall which parses the //sys
// lines and generates system call stubs.

package syscall

import (
	
	
)

const ImplementsGetwd = true

func () (string, error) {
	var  [pathMax]byte
	,  := getcwd([:])
	if  != nil {
		return "", 
	}
	 := clen([:])
	if  < 1 {
		return "", EINVAL
	}
	return string([:]), nil
}

/*
 * Wrapped
 */

//sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
//sysnb	setgroups(ngid int, gid *_Gid_t) (err error)

func () ( []int,  error) {
	,  := getgroups(0, nil)
	if  != nil {
		return nil, 
	}
	if  == 0 {
		return nil, nil
	}

	// Sanity check group count. Max is 16 on BSD.
	if  < 0 ||  > 1000 {
		return nil, EINVAL
	}

	 := make([]_Gid_t, )
	,  = getgroups(, &[0])
	if  != nil {
		return nil, 
	}
	 = make([]int, )
	for ,  := range [0:] {
		[] = int()
	}
	return
}

func ( []int) ( error) {
	if len() == 0 {
		return setgroups(0, nil)
	}

	 := make([]_Gid_t, len())
	for ,  := range  {
		[] = _Gid_t()
	}
	return setgroups(len(), &[0])
}

func ( int,  []byte) ( int,  error) {
	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
	// 64 bits should be enough. (32 bits isn't even on 386). Since the
	// actual system call is getdirentries64, 64 is a good guess.
	// TODO(rsc): Can we use a single global basep for all calls?
	var  = (*uintptr)(unsafe.Pointer(new(uint64)))
	return Getdirentries(, , )
}

// Wait status is 7 bits at bottom, either 0 (exited),
// 0x7F (stopped), or a signal number that caused an exit.
// The 0x80 bit is whether there was a core dump.
// An extra number (exit code, signal causing a stop)
// is in the high bits.

type WaitStatus uint32

const (
	mask  = 0x7F
	core  = 0x80
	shift = 8

	exited  = 0
	stopped = 0x7F
)

func ( WaitStatus) () bool { return &mask == exited }

func ( WaitStatus) () int {
	if &mask != exited {
		return -1
	}
	return int( >> shift)
}

func ( WaitStatus) () bool { return &mask != stopped && &mask != 0 }

func ( WaitStatus) () Signal {
	 := Signal( & mask)
	if  == stopped ||  == 0 {
		return -1
	}
	return 
}

func ( WaitStatus) () bool { return .Signaled() && &core != 0 }

func ( WaitStatus) () bool { return &mask == stopped && Signal(>>shift) != SIGSTOP }

func ( WaitStatus) () bool { return &mask == stopped && Signal(>>shift) == SIGSTOP }

func ( WaitStatus) () Signal {
	if !.Stopped() {
		return -1
	}
	return Signal(>>shift) & 0xFF
}

func ( WaitStatus) () int { return -1 }

//sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error)

func ( int,  *WaitStatus,  int,  *Rusage) ( int,  error) {
	var  _C_int
	,  = wait4(, &, , )
	if  != nil {
		* = WaitStatus()
	}
	return
}

//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys	Shutdown(s int, how int) (err error)

func ( *SockaddrInet4) () (unsafe.Pointer, _Socklen, error) {
	if .Port < 0 || .Port > 0xFFFF {
		return nil, 0, EINVAL
	}
	.raw.Len = SizeofSockaddrInet4
	.raw.Family = AF_INET
	 := (*[2]byte)(unsafe.Pointer(&.raw.Port))
	[0] = byte(.Port >> 8)
	[1] = byte(.Port)
	for  := 0;  < len(.Addr); ++ {
		.raw.Addr[] = .Addr[]
	}
	return unsafe.Pointer(&.raw), _Socklen(.raw.Len), nil
}

func ( *SockaddrInet6) () (unsafe.Pointer, _Socklen, error) {
	if .Port < 0 || .Port > 0xFFFF {
		return nil, 0, EINVAL
	}
	.raw.Len = SizeofSockaddrInet6
	.raw.Family = AF_INET6
	 := (*[2]byte)(unsafe.Pointer(&.raw.Port))
	[0] = byte(.Port >> 8)
	[1] = byte(.Port)
	.raw.Scope_id = .ZoneId
	for  := 0;  < len(.Addr); ++ {
		.raw.Addr[] = .Addr[]
	}
	return unsafe.Pointer(&.raw), _Socklen(.raw.Len), nil
}

func ( *SockaddrUnix) () (unsafe.Pointer, _Socklen, error) {
	 := .Name
	 := len()
	if  >= len(.raw.Path) ||  == 0 {
		return nil, 0, EINVAL
	}
	.raw.Len = byte(3 + ) // 2 for Family, Len; 1 for NUL
	.raw.Family = AF_UNIX
	for  := 0;  < ; ++ {
		.raw.Path[] = int8([])
	}
	return unsafe.Pointer(&.raw), _Socklen(.raw.Len), nil
}

func ( *SockaddrDatalink) () (unsafe.Pointer, _Socklen, error) {
	if .Index == 0 {
		return nil, 0, EINVAL
	}
	.raw.Len = .Len
	.raw.Family = AF_LINK
	.raw.Index = .Index
	.raw.Type = .Type
	.raw.Nlen = .Nlen
	.raw.Alen = .Alen
	.raw.Slen = .Slen
	for  := 0;  < len(.raw.Data); ++ {
		.raw.Data[] = .Data[]
	}
	return unsafe.Pointer(&.raw), SizeofSockaddrDatalink, nil
}

func ( *RawSockaddrAny) (Sockaddr, error) {
	switch .Addr.Family {
	case AF_LINK:
		 := (*RawSockaddrDatalink)(unsafe.Pointer())
		 := new(SockaddrDatalink)
		.Len = .Len
		.Family = .Family
		.Index = .Index
		.Type = .Type
		.Nlen = .Nlen
		.Alen = .Alen
		.Slen = .Slen
		for  := 0;  < len(.Data); ++ {
			.Data[] = .Data[]
		}
		return , nil

	case AF_UNIX:
		 := (*RawSockaddrUnix)(unsafe.Pointer())
		if .Len < 2 || .Len > SizeofSockaddrUnix {
			return nil, EINVAL
		}
		 := new(SockaddrUnix)

		// Some BSDs include the trailing NUL in the length, whereas
		// others do not. Work around this by subtracting the leading
		// family and len. The path is then scanned to see if a NUL
		// terminator still exists within the length.
		 := int(.Len) - 2 // subtract leading Family, Len
		for  := 0;  < ; ++ {
			if .Path[] == 0 {
				// found early NUL; assume Len included the NUL
				// or was overestimating.
				 = 
				break
			}
		}
		 := (*[len(.Path)]byte)(unsafe.Pointer(&.Path[0]))[0:]
		.Name = string()
		return , nil

	case AF_INET:
		 := (*RawSockaddrInet4)(unsafe.Pointer())
		 := new(SockaddrInet4)
		 := (*[2]byte)(unsafe.Pointer(&.Port))
		.Port = int([0])<<8 + int([1])
		for  := 0;  < len(.Addr); ++ {
			.Addr[] = .Addr[]
		}
		return , nil

	case AF_INET6:
		 := (*RawSockaddrInet6)(unsafe.Pointer())
		 := new(SockaddrInet6)
		 := (*[2]byte)(unsafe.Pointer(&.Port))
		.Port = int([0])<<8 + int([1])
		.ZoneId = .Scope_id
		for  := 0;  < len(.Addr); ++ {
			.Addr[] = .Addr[]
		}
		return , nil
	}
	return nil, EAFNOSUPPORT
}

func ( int) ( int,  Sockaddr,  error) {
	var  RawSockaddrAny
	var  _Socklen = SizeofSockaddrAny
	,  = accept(, &, &)
	if  != nil {
		return
	}
	if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") &&  == 0 {
		// Accepted socket has no address.
		// This is likely due to a bug in xnu kernels,
		// where instead of ECONNABORTED error socket
		// is accepted, but has no address.
		Close()
		return 0, nil, ECONNABORTED
	}
	,  = anyToSockaddr(&)
	if  != nil {
		Close()
		 = 0
	}
	return
}

func ( int) ( Sockaddr,  error) {
	var  RawSockaddrAny
	var  _Socklen = SizeofSockaddrAny
	if  = getsockname(, &, &);  != nil {
		return
	}
	// TODO(jsing): DragonFly has a "bug" (see issue 3349), which should be
	// reported upstream.
	if runtime.GOOS == "dragonfly" && .Addr.Family == AF_UNSPEC && .Addr.Len == 0 {
		.Addr.Family = AF_UNIX
		.Addr.Len = SizeofSockaddrUnix
	}
	return anyToSockaddr(&)
}

//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)

func (, ,  int) ( byte,  error) {
	var  byte
	 := _Socklen(1)
	 = getsockopt(, , , unsafe.Pointer(&), &)
	return , 
}

func (, ,  int) ( [4]byte,  error) {
	 := _Socklen(4)
	 = getsockopt(, , , unsafe.Pointer(&[0]), &)
	return , 
}

func (, ,  int) (*IPMreq, error) {
	var  IPMreq
	 := _Socklen(SizeofIPMreq)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

func (, ,  int) (*IPv6Mreq, error) {
	var  IPv6Mreq
	 := _Socklen(SizeofIPv6Mreq)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

func (, ,  int) (*IPv6MTUInfo, error) {
	var  IPv6MTUInfo
	 := _Socklen(SizeofIPv6MTUInfo)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

func (, ,  int) (*ICMPv6Filter, error) {
	var  ICMPv6Filter
	 := _Socklen(SizeofICMPv6Filter)
	 := getsockopt(, , , unsafe.Pointer(&), &)
	return &, 
}

//sys   recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys   sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)

func ( int, ,  []byte,  int) (,  int,  int,  Sockaddr,  error) {
	var  Msghdr
	var  RawSockaddrAny
	.Name = (*byte)(unsafe.Pointer(&))
	.Namelen = uint32(SizeofSockaddrAny)
	var  Iovec
	if len() > 0 {
		.Base = (*byte)(unsafe.Pointer(&[0]))
		.SetLen(len())
	}
	var  byte
	if len() > 0 {
		// receive at least one normal byte
		if len() == 0 {
			.Base = &
			.SetLen(1)
		}
		.Control = (*byte)(unsafe.Pointer(&[0]))
		.SetControllen(len())
	}
	.Iov = &
	.Iovlen = 1
	if ,  = recvmsg(, &, );  != nil {
		return
	}
	 = int(.Controllen)
	 = int(.Flags)
	// source address is only specified if the socket is unconnected
	if .Addr.Family != AF_UNSPEC {
		,  = anyToSockaddr(&)
	}
	return
}

//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)

func ( int, ,  []byte,  Sockaddr,  int) ( error) {
	_,  = SendmsgN(, , , , )
	return
}

func ( int, ,  []byte,  Sockaddr,  int) ( int,  error) {
	var  unsafe.Pointer
	var  _Socklen
	if  != nil {
		, ,  = .sockaddr()
		if  != nil {
			return 0, 
		}
	}
	var  Msghdr
	.Name = (*byte)(unsafe.Pointer())
	.Namelen = uint32()
	var  Iovec
	if len() > 0 {
		.Base = (*byte)(unsafe.Pointer(&[0]))
		.SetLen(len())
	}
	var  byte
	if len() > 0 {
		// send at least one normal byte
		if len() == 0 {
			.Base = &
			.SetLen(1)
		}
		.Control = (*byte)(unsafe.Pointer(&[0]))
		.SetControllen(len())
	}
	.Iov = &
	.Iovlen = 1
	if ,  = sendmsg(, &, );  != nil {
		return 0, 
	}
	if len() > 0 && len() == 0 {
		 = 0
	}
	return , nil
}

//sys	kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error)

func ( int, ,  []Kevent_t,  *Timespec) ( int,  error) {
	var ,  unsafe.Pointer
	if len() > 0 {
		 = unsafe.Pointer(&[0])
	}
	if len() > 0 {
		 = unsafe.Pointer(&[0])
	}
	return kevent(, , len(), , len(), )
}

func ( string) ( string,  error) {
	// Translate name to mib number.
	,  := nametomib()
	if  != nil {
		return "", 
	}

	// Find size.
	 := uintptr(0)
	if  = sysctl(, nil, &, nil, 0);  != nil {
		return "", 
	}
	if  == 0 {
		return "", nil
	}

	// Read into buffer of that size.
	 := make([]byte, )
	if  = sysctl(, &[0], &, nil, 0);  != nil {
		return "", 
	}

	// Throw away terminating NUL.
	if  > 0 && [-1] == '\x00' {
		--
	}
	return string([0:]), nil
}

func ( string) ( uint32,  error) {
	// Translate name to mib number.
	,  := nametomib()
	if  != nil {
		return 0, 
	}

	// Read into buffer of that size.
	 := uintptr(4)
	 := make([]byte, 4)
	if  = sysctl(, &[0], &, nil, 0);  != nil {
		return 0, 
	}
	if  != 4 {
		return 0, EIO
	}
	return *(*uint32)(unsafe.Pointer(&[0])), nil
}

//sys	utimes(path string, timeval *[2]Timeval) (err error)

func ( string,  []Timeval) ( error) {
	if len() != 2 {
		return EINVAL
	}
	return utimes(, (*[2]Timeval)(unsafe.Pointer(&[0])))
}

func ( string,  []Timespec) error {
	if len() != 2 {
		return EINVAL
	}
	// Darwin setattrlist can set nanosecond timestamps
	 := setattrlistTimes(, )
	if  != ENOSYS {
		return 
	}
	 = utimensat(_AT_FDCWD, , (*[2]Timespec)(unsafe.Pointer(&[0])), 0)
	if  != ENOSYS {
		return 
	}
	// Not as efficient as it could be because Timespec and
	// Timeval have different types in the different OSes
	 := [2]Timeval{
		NsecToTimeval(TimespecToNsec([0])),
		NsecToTimeval(TimespecToNsec([1])),
	}
	return utimes(, (*[2]Timeval)(unsafe.Pointer(&[0])))
}

//sys	futimes(fd int, timeval *[2]Timeval) (err error)

func ( int,  []Timeval) ( error) {
	if len() != 2 {
		return EINVAL
	}
	return futimes(, (*[2]Timeval)(unsafe.Pointer(&[0])))
}

//sys	fcntl(fd int, cmd int, arg int) (val int, err error)

var mapper = &mmapper{
	active: make(map[*byte][]byte),
	mmap:   mmap,
	munmap: munmap,
}

func ( int,  int64,  int,  int,  int) ( []byte,  error) {
	return mapper.Mmap(, , , , )
}

func ( []byte) ( error) {
	return mapper.Munmap()
}