github.com/euank/go@v0.0.0-20160829210321-495514729181/src/syscall/syscall_unix.go (about)

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