2016-06-08 11:59:16 +02:00
// 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 linux netbsd openbsd solaris
package unix
import (
2017-12-13 09:16:44 +01:00
"bytes"
2016-06-08 11:59:16 +02:00
"runtime"
"sync"
"syscall"
"unsafe"
)
var (
Stdin = 0
Stdout = 1
Stderr = 2
)
const (
darwin64Bit = runtime . GOOS == "darwin" && sizeofPtr == 8
dragonfly64Bit = runtime . GOOS == "dragonfly" && sizeofPtr == 8
netbsd32Bit = runtime . GOOS == "netbsd" && sizeofPtr == 4
2017-12-13 09:16:44 +01:00
solaris64Bit = runtime . GOOS == "solaris" && sizeofPtr == 8
2016-06-08 11:59:16 +02:00
)
// Do the interface allocations only once for common
// Errno values.
var (
errEAGAIN error = syscall . EAGAIN
errEINVAL error = syscall . EINVAL
errENOENT error = syscall . ENOENT
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr ( e syscall . Errno ) error {
switch e {
case 0 :
return nil
case EAGAIN :
return errEAGAIN
case EINVAL :
return errEINVAL
case ENOENT :
return errENOENT
}
return e
}
2017-12-13 09:16:44 +01:00
// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
func clen ( n [ ] byte ) int {
i := bytes . IndexByte ( n , 0 )
if i == - 1 {
i = len ( n )
}
return i
}
2016-06-08 11:59:16 +02:00
// Mmap manager, for use by operating system-specific implementations.
type mmapper struct {
sync . Mutex
active map [ * byte ] [ ] byte // active mappings; key is last byte in mapping
mmap func ( addr , length uintptr , prot , flags , fd int , offset int64 ) ( uintptr , error )
munmap func ( addr uintptr , length uintptr ) error
}
func ( m * mmapper ) Mmap ( fd int , offset int64 , length int , prot int , flags int ) ( data [ ] byte , err error ) {
if length <= 0 {
return nil , EINVAL
}
// Map the requested memory.
addr , errno := m . mmap ( 0 , uintptr ( length ) , prot , flags , fd , offset )
if errno != nil {
return nil , errno
}
// Slice memory layout
var sl = struct {
addr uintptr
len int
cap int
} { addr , length , length }
// Use unsafe to turn sl into a []byte.
b := * ( * [ ] byte ) ( unsafe . Pointer ( & sl ) )
// Register mapping in m and return it.
p := & b [ cap ( b ) - 1 ]
m . Lock ( )
defer m . Unlock ( )
m . active [ p ] = b
return b , nil
}
func ( m * mmapper ) Munmap ( data [ ] byte ) ( err error ) {
if len ( data ) == 0 || len ( data ) != cap ( data ) {
return EINVAL
}
// Find the base of the mapping.
p := & data [ cap ( data ) - 1 ]
m . Lock ( )
defer m . Unlock ( )
b := m . active [ p ]
if b == nil || & b [ 0 ] != & data [ 0 ] {
return EINVAL
}
// Unmap the memory and update m.
if errno := m . munmap ( uintptr ( unsafe . Pointer ( & b [ 0 ] ) ) , uintptr ( len ( b ) ) ) ; errno != nil {
return errno
}
delete ( m . active , p )
return nil
}
func Read ( fd int , p [ ] byte ) ( n int , err error ) {
n , err = read ( fd , p )
if raceenabled {
if n > 0 {
raceWriteRange ( unsafe . Pointer ( & p [ 0 ] ) , n )
}
if err == nil {
raceAcquire ( unsafe . Pointer ( & ioSync ) )
}
}
return
}
func Write ( fd int , p [ ] byte ) ( n int , err error ) {
if raceenabled {
raceReleaseMerge ( unsafe . Pointer ( & ioSync ) )
}
n , err = write ( fd , p )
if raceenabled && n > 0 {
raceReadRange ( unsafe . Pointer ( & p [ 0 ] ) , n )
}
return
}
// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool
2017-12-13 09:16:44 +01:00
// Sockaddr represents a socket address.
2016-06-08 11:59:16 +02:00
type Sockaddr interface {
sockaddr ( ) ( ptr unsafe . Pointer , len _Socklen , err error ) // lowercase; only we can define Sockaddrs
}
2017-12-13 09:16:44 +01:00
// SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets.
2016-06-08 11:59:16 +02:00
type SockaddrInet4 struct {
Port int
Addr [ 4 ] byte
raw RawSockaddrInet4
}
2017-12-13 09:16:44 +01:00
// SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets.
2016-06-08 11:59:16 +02:00
type SockaddrInet6 struct {
Port int
ZoneId uint32
Addr [ 16 ] byte
raw RawSockaddrInet6
}
2017-12-13 09:16:44 +01:00
// SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets.
2016-06-08 11:59:16 +02:00
type SockaddrUnix struct {
Name string
raw RawSockaddrUnix
}
func Bind ( fd int , sa Sockaddr ) ( err error ) {
ptr , n , err := sa . sockaddr ( )
if err != nil {
return err
}
return bind ( fd , ptr , n )
}
func Connect ( fd int , sa Sockaddr ) ( err error ) {
ptr , n , err := sa . sockaddr ( )
if err != nil {
return err
}
return connect ( fd , ptr , n )
}
func Getpeername ( fd int ) ( sa Sockaddr , err error ) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
if err = getpeername ( fd , & rsa , & len ) ; err != nil {
return
}
return anyToSockaddr ( & rsa )
}
func GetsockoptInt ( fd , level , opt int ) ( value int , err error ) {
var n int32
vallen := _Socklen ( 4 )
err = getsockopt ( fd , level , opt , unsafe . Pointer ( & n ) , & vallen )
return int ( n ) , err
}
func Recvfrom ( fd int , p [ ] byte , flags int ) ( n int , from Sockaddr , err error ) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
if n , err = recvfrom ( fd , p , flags , & rsa , & len ) ; err != nil {
return
}
if rsa . Addr . Family != AF_UNSPEC {
from , err = anyToSockaddr ( & rsa )
}
return
}
func Sendto ( fd int , p [ ] byte , flags int , to Sockaddr ) ( err error ) {
ptr , n , err := to . sockaddr ( )
if err != nil {
return err
}
return sendto ( fd , p , flags , ptr , n )
}
func SetsockoptByte ( fd , level , opt int , value byte ) ( err error ) {
return setsockopt ( fd , level , opt , unsafe . Pointer ( & value ) , 1 )
}
func SetsockoptInt ( fd , level , opt int , value int ) ( err error ) {
var n = int32 ( value )
return setsockopt ( fd , level , opt , unsafe . Pointer ( & n ) , 4 )
}
func SetsockoptInet4Addr ( fd , level , opt int , value [ 4 ] byte ) ( err error ) {
return setsockopt ( fd , level , opt , unsafe . Pointer ( & value [ 0 ] ) , 4 )
}
func SetsockoptIPMreq ( fd , level , opt int , mreq * IPMreq ) ( err error ) {
return setsockopt ( fd , level , opt , unsafe . Pointer ( mreq ) , SizeofIPMreq )
}
func SetsockoptIPv6Mreq ( fd , level , opt int , mreq * IPv6Mreq ) ( err error ) {
return setsockopt ( fd , level , opt , unsafe . Pointer ( mreq ) , SizeofIPv6Mreq )
}
func SetsockoptICMPv6Filter ( fd , level , opt int , filter * ICMPv6Filter ) error {
return setsockopt ( fd , level , opt , unsafe . Pointer ( filter ) , SizeofICMPv6Filter )
}
func SetsockoptLinger ( fd , level , opt int , l * Linger ) ( err error ) {
return setsockopt ( fd , level , opt , unsafe . Pointer ( l ) , SizeofLinger )
}
func SetsockoptString ( fd , level , opt int , s string ) ( err error ) {
return setsockopt ( fd , level , opt , unsafe . Pointer ( & [ ] byte ( s ) [ 0 ] ) , uintptr ( len ( s ) ) )
}
func SetsockoptTimeval ( fd , level , opt int , tv * Timeval ) ( err error ) {
return setsockopt ( fd , level , opt , unsafe . Pointer ( tv ) , unsafe . Sizeof ( * tv ) )
}
func Socket ( domain , typ , proto int ) ( fd int , err error ) {
if domain == AF_INET6 && SocketDisableIPv6 {
return - 1 , EAFNOSUPPORT
}
fd , err = socket ( domain , typ , proto )
return
}
func Socketpair ( domain , typ , proto int ) ( fd [ 2 ] int , err error ) {
var fdx [ 2 ] int32
err = socketpair ( domain , typ , proto , & fdx )
if err == nil {
fd [ 0 ] = int ( fdx [ 0 ] )
fd [ 1 ] = int ( fdx [ 1 ] )
}
return
}
func Sendfile ( outfd int , infd int , offset * int64 , count int ) ( written int , err error ) {
if raceenabled {
raceReleaseMerge ( unsafe . Pointer ( & ioSync ) )
}
return sendfile ( outfd , infd , offset , count )
}
var ioSync int64
func CloseOnExec ( fd int ) { fcntl ( fd , F_SETFD , FD_CLOEXEC ) }
func SetNonblock ( fd int , nonblocking bool ) ( err error ) {
flag , err := fcntl ( fd , F_GETFL , 0 )
if err != nil {
return err
}
if nonblocking {
flag |= O_NONBLOCK
} else {
flag &= ^ O_NONBLOCK
}
_ , err = fcntl ( fd , F_SETFL , flag )
return err
}
2017-12-13 09:16:44 +01:00
// Exec calls execve(2), which replaces the calling executable in the process
// tree. argv0 should be the full path to an executable ("/bin/ls") and the
// executable name should also be the first argument in argv (["ls", "-l"]).
// envv are the environment variables that should be passed to the new
// process (["USER=go", "PWD=/tmp"]).
func Exec ( argv0 string , argv [ ] string , envv [ ] string ) error {
return syscall . Exec ( argv0 , argv , envv )
}