package unix
import (
"bytes"
"sort"
"sync"
"syscall"
"unsafe"
)
var (
Stdin = 0
Stdout = 1
Stderr = 2
)
var (
errEAGAIN error = syscall .EAGAIN
errEINVAL error = syscall .EINVAL
errENOENT error = syscall .ENOENT
)
var (
signalNameMapOnce sync .Once
signalNameMap map [string ]syscall .Signal
)
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
}
func ErrnoName (e syscall .Errno ) string {
i := sort .Search (len (errorList ), func (i int ) bool {
return errorList [i ].num >= e
})
if i < len (errorList ) && errorList [i ].num == e {
return errorList [i ].name
}
return ""
}
func SignalName (s syscall .Signal ) string {
i := sort .Search (len (signalList ), func (i int ) bool {
return signalList [i ].num >= s
})
if i < len (signalList ) && signalList [i ].num == s {
return signalList [i ].name
}
return ""
}
func SignalNum (s string ) syscall .Signal {
signalNameMapOnce .Do (func () {
signalNameMap = make (map [string ]syscall .Signal , len (signalList ))
for _ , signal := range signalList {
signalNameMap [signal .name ] = signal .num
}
})
return signalNameMap [s ]
}
func clen(n []byte ) int {
i := bytes .IndexByte (n , 0 )
if i == -1 {
i = len (n )
}
return i
}
type mmapper struct {
sync .Mutex
active map [*byte ][]byte
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
}
addr , errno := m .mmap (0 , uintptr (length ), prot , flags , fd , offset )
if errno != nil {
return nil , errno
}
b := unsafe .Slice ((*byte )(unsafe .Pointer (addr )), length )
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
}
p := &data [cap (data )-1 ]
m .Lock ()
defer m .Unlock ()
b := m .active [p ]
if b == nil || &b [0 ] != &data [0 ] {
return EINVAL
}
if errno := m .munmap (uintptr (unsafe .Pointer (&b [0 ])), uintptr (len (b ))); errno != nil {
return errno
}
delete (m .active , p )
return nil
}
func Mmap (fd int , offset int64 , length int , prot int , flags int ) (data []byte , err error ) {
return mapper .Mmap (fd , offset , length , prot , flags )
}
func Munmap (b []byte ) (err error ) {
return mapper .Munmap (b )
}
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
}
func Pread (fd int , p []byte , offset int64 ) (n int , err error ) {
n , err = pread (fd , p , offset )
if raceenabled {
if n > 0 {
raceWriteRange (unsafe .Pointer (&p [0 ]), n )
}
if err == nil {
raceAcquire (unsafe .Pointer (&ioSync ))
}
}
return
}
func Pwrite (fd int , p []byte , offset int64 ) (n int , err error ) {
if raceenabled {
raceReleaseMerge (unsafe .Pointer (&ioSync ))
}
n , err = pwrite (fd , p , offset )
if raceenabled && n > 0 {
raceReadRange (unsafe .Pointer (&p [0 ]), n )
}
return
}
var SocketDisableIPv6 bool
type Sockaddr interface {
sockaddr() (ptr unsafe .Pointer , len _Socklen , err error )
}
type SockaddrInet4 struct {
Port int
Addr [4 ]byte
raw RawSockaddrInet4
}
type SockaddrInet6 struct {
Port int
ZoneId uint32
Addr [16 ]byte
raw RawSockaddrInet6
}
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 (fd , &rsa )
}
func GetsockoptByte (fd , level , opt int ) (value byte , err error ) {
var n byte
vallen := _Socklen (1 )
err = getsockopt (fd , level , opt , unsafe .Pointer (&n ), &vallen )
return n , err
}
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 GetsockoptInet4Addr (fd , level , opt int ) (value [4 ]byte , err error ) {
vallen := _Socklen (4 )
err = getsockopt (fd , level , opt , unsafe .Pointer (&value [0 ]), &vallen )
return value , err
}
func GetsockoptIPMreq (fd , level , opt int ) (*IPMreq , error ) {
var value IPMreq
vallen := _Socklen (SizeofIPMreq )
err := getsockopt (fd , level , opt , unsafe .Pointer (&value ), &vallen )
return &value , err
}
func GetsockoptIPv6Mreq (fd , level , opt int ) (*IPv6Mreq , error ) {
var value IPv6Mreq
vallen := _Socklen (SizeofIPv6Mreq )
err := getsockopt (fd , level , opt , unsafe .Pointer (&value ), &vallen )
return &value , err
}
func GetsockoptIPv6MTUInfo (fd , level , opt int ) (*IPv6MTUInfo , error ) {
var value IPv6MTUInfo
vallen := _Socklen (SizeofIPv6MTUInfo )
err := getsockopt (fd , level , opt , unsafe .Pointer (&value ), &vallen )
return &value , err
}
func GetsockoptICMPv6Filter (fd , level , opt int ) (*ICMPv6Filter , error ) {
var value ICMPv6Filter
vallen := _Socklen (SizeofICMPv6Filter )
err := getsockopt (fd , level , opt , unsafe .Pointer (&value ), &vallen )
return &value , err
}
func GetsockoptLinger (fd , level , opt int ) (*Linger , error ) {
var linger Linger
vallen := _Socklen (SizeofLinger )
err := getsockopt (fd , level , opt , unsafe .Pointer (&linger ), &vallen )
return &linger , err
}
func GetsockoptTimeval (fd , level , opt int ) (*Timeval , error ) {
var tv Timeval
vallen := _Socklen (unsafe .Sizeof (tv ))
err := getsockopt (fd , level , opt , unsafe .Pointer (&tv ), &vallen )
return &tv , err
}
func GetsockoptUint64 (fd , level , opt int ) (value uint64 , err error ) {
var n uint64
vallen := _Socklen (8 )
err = getsockopt (fd , level , opt , unsafe .Pointer (&n ), &vallen )
return 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 (fd , &rsa )
}
return
}
func Recvmsg (fd int , p , oob []byte , flags int ) (n , oobn int , recvflags int , from Sockaddr , err error ) {
var iov [1 ]Iovec
if len (p ) > 0 {
iov [0 ].Base = &p [0 ]
iov [0 ].SetLen (len (p ))
}
var rsa RawSockaddrAny
n , oobn , recvflags , err = recvmsgRaw (fd , iov [:], oob , flags , &rsa )
if rsa .Addr .Family != AF_UNSPEC {
from , err = anyToSockaddr (fd , &rsa )
}
return
}
func RecvmsgBuffers (fd int , buffers [][]byte , oob []byte , flags int ) (n , oobn int , recvflags int , from Sockaddr , err error ) {
iov := make ([]Iovec , len (buffers ))
for i := range buffers {
if len (buffers [i ]) > 0 {
iov [i ].Base = &buffers [i ][0 ]
iov [i ].SetLen (len (buffers [i ]))
} else {
iov [i ].Base = (*byte )(unsafe .Pointer (&_zero ))
}
}
var rsa RawSockaddrAny
n , oobn , recvflags , err = recvmsgRaw (fd , iov , oob , flags , &rsa )
if err == nil && rsa .Addr .Family != AF_UNSPEC {
from , err = anyToSockaddr (fd , &rsa )
}
return
}
func Sendmsg (fd int , p , oob []byte , to Sockaddr , flags int ) (err error ) {
_, err = SendmsgN (fd , p , oob , to , flags )
return
}
func SendmsgN (fd int , p , oob []byte , to Sockaddr , flags int ) (n int , err error ) {
var iov [1 ]Iovec
if len (p ) > 0 {
iov [0 ].Base = &p [0 ]
iov [0 ].SetLen (len (p ))
}
var ptr unsafe .Pointer
var salen _Socklen
if to != nil {
ptr , salen , err = to .sockaddr ()
if err != nil {
return 0 , err
}
}
return sendmsgN (fd , iov [:], oob , ptr , salen , flags )
}
func SendmsgBuffers (fd int , buffers [][]byte , oob []byte , to Sockaddr , flags int ) (n int , err error ) {
iov := make ([]Iovec , len (buffers ))
for i := range buffers {
if len (buffers [i ]) > 0 {
iov [i ].Base = &buffers [i ][0 ]
iov [i ].SetLen (len (buffers [i ]))
} else {
iov [i ].Base = (*byte )(unsafe .Pointer (&_zero ))
}
}
var ptr unsafe .Pointer
var salen _Socklen
if to != nil {
ptr , salen , err = to .sockaddr ()
if err != nil {
return 0 , err
}
}
return sendmsgN (fd , iov , oob , ptr , salen , flags )
}
func Send (s int , buf []byte , flags int ) (err error ) {
return sendto (s , buf , flags , nil , 0 )
}
func Sendto (fd int , p []byte , flags int , to Sockaddr ) (err error ) {
var ptr unsafe .Pointer
var salen _Socklen
if to != nil {
ptr , salen , err = to .sockaddr ()
if err != nil {
return err
}
}
return sendto (fd , p , flags , ptr , salen )
}
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 ) {
var p unsafe .Pointer
if len (s ) > 0 {
p = unsafe .Pointer (&[]byte (s )[0 ])
}
return setsockopt (fd , level , opt , p , 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 SetsockoptUint64 (fd , level , opt int , value uint64 ) (err error ) {
return setsockopt (fd , level , opt , unsafe .Pointer (&value ), 8 )
}
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
}
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 (flag &O_NONBLOCK != 0 ) == nonblocking {
return nil
}
if nonblocking {
flag |= O_NONBLOCK
} else {
flag &= ^O_NONBLOCK
}
_, err = fcntl (fd , F_SETFL , flag )
return err
}
func Exec (argv0 string , argv []string , envv []string ) error {
return syscall .Exec (argv0 , argv , envv )
}
func Lutimes (path string , tv []Timeval ) error {
if tv == nil {
return UtimesNanoAt (AT_FDCWD , path , nil , AT_SYMLINK_NOFOLLOW )
}
if len (tv ) != 2 {
return EINVAL
}
ts := []Timespec {
NsecToTimespec (TimevalToNsec (tv [0 ])),
NsecToTimespec (TimevalToNsec (tv [1 ])),
}
return UtimesNanoAt (AT_FDCWD , path , ts , AT_SYMLINK_NOFOLLOW )
}
func emptyIovecs(iov []Iovec ) bool {
for i := range iov {
if iov [i ].Len > 0 {
return false
}
}
return true
}
func Setrlimit (resource int , rlim *Rlimit ) error {
return syscall .Setrlimit (resource , (*syscall .Rlimit )(rlim ))
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .