github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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  	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