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