...

Source file src/syscall/syscall_bsd.go

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

View as plain text