Home | History | Annotate | Download | only in syscall
      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 linux netbsd openbsd solaris
      6 
      7 package syscall
      8 
      9 import (
     10 	"runtime"
     11 	"sync"
     12 	"unsafe"
     13 )
     14 
     15 var (
     16 	Stdin  = 0
     17 	Stdout = 1
     18 	Stderr = 2
     19 )
     20 
     21 const (
     22 	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
     23 	dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
     24 	netbsd32Bit    = runtime.GOOS == "netbsd" && sizeofPtr == 4
     25 )
     26 
     27 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
     28 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
     29 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
     30 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
     31 
     32 // Mmap manager, for use by operating system-specific implementations.
     33 
     34 type mmapper struct {
     35 	sync.Mutex
     36 	active map[*byte][]byte // active mappings; key is last byte in mapping
     37 	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
     38 	munmap func(addr uintptr, length uintptr) error
     39 }
     40 
     41 func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
     42 	if length <= 0 {
     43 		return nil, EINVAL
     44 	}
     45 
     46 	// Map the requested memory.
     47 	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
     48 	if errno != nil {
     49 		return nil, errno
     50 	}
     51 
     52 	// Slice memory layout
     53 	var sl = struct {
     54 		addr uintptr
     55 		len  int
     56 		cap  int
     57 	}{addr, length, length}
     58 
     59 	// Use unsafe to turn sl into a []byte.
     60 	b := *(*[]byte)(unsafe.Pointer(&sl))
     61 
     62 	// Register mapping in m and return it.
     63 	p := &b[cap(b)-1]
     64 	m.Lock()
     65 	defer m.Unlock()
     66 	m.active[p] = b
     67 	return b, nil
     68 }
     69 
     70 func (m *mmapper) Munmap(data []byte) (err error) {
     71 	if len(data) == 0 || len(data) != cap(data) {
     72 		return EINVAL
     73 	}
     74 
     75 	// Find the base of the mapping.
     76 	p := &data[cap(data)-1]
     77 	m.Lock()
     78 	defer m.Unlock()
     79 	b := m.active[p]
     80 	if b == nil || &b[0] != &data[0] {
     81 		return EINVAL
     82 	}
     83 
     84 	// Unmap the memory and update m.
     85 	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
     86 		return errno
     87 	}
     88 	delete(m.active, p)
     89 	return nil
     90 }
     91 
     92 // An Errno is an unsigned number describing an error condition.
     93 // It implements the error interface.  The zero Errno is by convention
     94 // a non-error, so code to convert from Errno to error should use:
     95 //	err = nil
     96 //	if errno != 0 {
     97 //		err = errno
     98 //	}
     99 type Errno uintptr
    100 
    101 func (e Errno) Error() string {
    102 	if 0 <= int(e) && int(e) < len(errors) {
    103 		s := errors[e]
    104 		if s != "" {
    105 			return s
    106 		}
    107 	}
    108 	return "errno " + itoa(int(e))
    109 }
    110 
    111 func (e Errno) Temporary() bool {
    112 	return e == EINTR || e == EMFILE || e == ECONNRESET || e == ECONNABORTED || e.Timeout()
    113 }
    114 
    115 func (e Errno) Timeout() bool {
    116 	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
    117 }
    118 
    119 // Do the interface allocations only once for common
    120 // Errno values.
    121 var (
    122 	errEAGAIN error = EAGAIN
    123 	errEINVAL error = EINVAL
    124 	errENOENT error = ENOENT
    125 )
    126 
    127 // errnoErr returns common boxed Errno values, to prevent
    128 // allocations at runtime.
    129 func errnoErr(e Errno) error {
    130 	switch e {
    131 	case 0:
    132 		return nil
    133 	case EAGAIN:
    134 		return errEAGAIN
    135 	case EINVAL:
    136 		return errEINVAL
    137 	case ENOENT:
    138 		return errENOENT
    139 	}
    140 	return e
    141 }
    142 
    143 // A Signal is a number describing a process signal.
    144 // It implements the os.Signal interface.
    145 type Signal int
    146 
    147 func (s Signal) Signal() {}
    148 
    149 func (s Signal) String() string {
    150 	if 0 <= s && int(s) < len(signals) {
    151 		str := signals[s]
    152 		if str != "" {
    153 			return str
    154 		}
    155 	}
    156 	return "signal " + itoa(int(s))
    157 }
    158 
    159 func Read(fd int, p []byte) (n int, err error) {
    160 	n, err = read(fd, p)
    161 	if raceenabled {
    162 		if n > 0 {
    163 			raceWriteRange(unsafe.Pointer(&p[0]), n)
    164 		}
    165 		if err == nil {
    166 			raceAcquire(unsafe.Pointer(&ioSync))
    167 		}
    168 	}
    169 	return
    170 }
    171 
    172 func Write(fd int, p []byte) (n int, err error) {
    173 	if raceenabled {
    174 		raceReleaseMerge(unsafe.Pointer(&ioSync))
    175 	}
    176 	n, err = write(fd, p)
    177 	if raceenabled && n > 0 {
    178 		raceReadRange(unsafe.Pointer(&p[0]), n)
    179 	}
    180 	return
    181 }
    182 
    183 // For testing: clients can set this flag to force
    184 // creation of IPv6 sockets to return EAFNOSUPPORT.
    185 var SocketDisableIPv6 bool
    186 
    187 type Sockaddr interface {
    188 	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
    189 }
    190 
    191 type SockaddrInet4 struct {
    192 	Port int
    193 	Addr [4]byte
    194 	raw  RawSockaddrInet4
    195 }
    196 
    197 type SockaddrInet6 struct {
    198 	Port   int
    199 	ZoneId uint32
    200 	Addr   [16]byte
    201 	raw    RawSockaddrInet6
    202 }
    203 
    204 type SockaddrUnix struct {
    205 	Name string
    206 	raw  RawSockaddrUnix
    207 }
    208 
    209 func Bind(fd int, sa Sockaddr) (err error) {
    210 	ptr, n, err := sa.sockaddr()
    211 	if err != nil {
    212 		return err
    213 	}
    214 	return bind(fd, ptr, n)
    215 }
    216 
    217 func Connect(fd int, sa Sockaddr) (err error) {
    218 	ptr, n, err := sa.sockaddr()
    219 	if err != nil {
    220 		return err
    221 	}
    222 	return connect(fd, ptr, n)
    223 }
    224 
    225 func Getpeername(fd int) (sa Sockaddr, err error) {
    226 	var rsa RawSockaddrAny
    227 	var len _Socklen = SizeofSockaddrAny
    228 	if err = getpeername(fd, &rsa, &len); err != nil {
    229 		return
    230 	}
    231 	return anyToSockaddr(&rsa)
    232 }
    233 
    234 func GetsockoptInt(fd, level, opt int) (value int, err error) {
    235 	var n int32
    236 	vallen := _Socklen(4)
    237 	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
    238 	return int(n), err
    239 }
    240 
    241 func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
    242 	var rsa RawSockaddrAny
    243 	var len _Socklen = SizeofSockaddrAny
    244 	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
    245 		return
    246 	}
    247 	if rsa.Addr.Family != AF_UNSPEC {
    248 		from, err = anyToSockaddr(&rsa)
    249 	}
    250 	return
    251 }
    252 
    253 func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
    254 	ptr, n, err := to.sockaddr()
    255 	if err != nil {
    256 		return err
    257 	}
    258 	return sendto(fd, p, flags, ptr, n)
    259 }
    260 
    261 func SetsockoptByte(fd, level, opt int, value byte) (err error) {
    262 	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
    263 }
    264 
    265 func SetsockoptInt(fd, level, opt int, value int) (err error) {
    266 	var n = int32(value)
    267 	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
    268 }
    269 
    270 func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
    271 	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
    272 }
    273 
    274 func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
    275 	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
    276 }
    277 
    278 func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
    279 	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
    280 }
    281 
    282 func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
    283 	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
    284 }
    285 
    286 func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
    287 	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
    288 }
    289 
    290 func SetsockoptString(fd, level, opt int, s string) (err error) {
    291 	return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s)))
    292 }
    293 
    294 func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
    295 	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
    296 }
    297 
    298 func Socket(domain, typ, proto int) (fd int, err error) {
    299 	if domain == AF_INET6 && SocketDisableIPv6 {
    300 		return -1, EAFNOSUPPORT
    301 	}
    302 	fd, err = socket(domain, typ, proto)
    303 	return
    304 }
    305 
    306 func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
    307 	var fdx [2]int32
    308 	err = socketpair(domain, typ, proto, &fdx)
    309 	if err == nil {
    310 		fd[0] = int(fdx[0])
    311 		fd[1] = int(fdx[1])
    312 	}
    313 	return
    314 }
    315 
    316 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
    317 	if raceenabled {
    318 		raceReleaseMerge(unsafe.Pointer(&ioSync))
    319 	}
    320 	return sendfile(outfd, infd, offset, count)
    321 }
    322 
    323 var ioSync int64
    324