github.com/juelite/golang.org-x-sys@v0.0.0-20181121071242-7b69e1c5db33/unix/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 unix
     8  
     9  import (
    10  	"runtime"
    11  	"sync"
    12  	"syscall"
    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  // Do the interface allocations only once for common
    29  // Errno values.
    30  var (
    31  	errEAGAIN error = syscall.EAGAIN
    32  	errEINVAL error = syscall.EINVAL
    33  	errENOENT error = syscall.ENOENT
    34  )
    35  
    36  // errnoErr returns common boxed Errno values, to prevent
    37  // allocations at runtime.
    38  func errnoErr(e syscall.Errno) error {
    39  	switch e {
    40  	case 0:
    41  		return nil
    42  	case EAGAIN:
    43  		return errEAGAIN
    44  	case EINVAL:
    45  		return errEINVAL
    46  	case ENOENT:
    47  		return errENOENT
    48  	}
    49  	return e
    50  }
    51  
    52  // Mmap manager, for use by operating system-specific implementations.
    53  
    54  type mmapper struct {
    55  	sync.Mutex
    56  	active map[*byte][]byte // active mappings; key is last byte in mapping
    57  	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
    58  	munmap func(addr uintptr, length uintptr) error
    59  }
    60  
    61  func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
    62  	if length <= 0 {
    63  		return nil, EINVAL
    64  	}
    65  
    66  	// Map the requested memory.
    67  	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
    68  	if errno != nil {
    69  		return nil, errno
    70  	}
    71  
    72  	// Slice memory layout
    73  	var sl = struct {
    74  		addr uintptr
    75  		len  int
    76  		cap  int
    77  	}{addr, length, length}
    78  
    79  	// Use unsafe to turn sl into a []byte.
    80  	b := *(*[]byte)(unsafe.Pointer(&sl))
    81  
    82  	// Register mapping in m and return it.
    83  	p := &b[cap(b)-1]
    84  	m.Lock()
    85  	defer m.Unlock()
    86  	m.active[p] = b
    87  	return b, nil
    88  }
    89  
    90  func (m *mmapper) Munmap(data []byte) (err error) {
    91  	if len(data) == 0 || len(data) != cap(data) {
    92  		return EINVAL
    93  	}
    94  
    95  	// Find the base of the mapping.
    96  	p := &data[cap(data)-1]
    97  	m.Lock()
    98  	defer m.Unlock()
    99  	b := m.active[p]
   100  	if b == nil || &b[0] != &data[0] {
   101  		return EINVAL
   102  	}
   103  
   104  	// Unmap the memory and update m.
   105  	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
   106  		return errno
   107  	}
   108  	delete(m.active, p)
   109  	return nil
   110  }
   111  
   112  func Read(fd int, p []byte) (n int, err error) {
   113  	n, err = read(fd, p)
   114  	if raceenabled {
   115  		if n > 0 {
   116  			raceWriteRange(unsafe.Pointer(&p[0]), n)
   117  		}
   118  		if err == nil {
   119  			raceAcquire(unsafe.Pointer(&ioSync))
   120  		}
   121  	}
   122  	return
   123  }
   124  
   125  func Write(fd int, p []byte) (n int, err error) {
   126  	if raceenabled {
   127  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   128  	}
   129  	n, err = write(fd, p)
   130  	if raceenabled && n > 0 {
   131  		raceReadRange(unsafe.Pointer(&p[0]), n)
   132  	}
   133  	return
   134  }
   135  
   136  // For testing: clients can set this flag to force
   137  // creation of IPv6 sockets to return EAFNOSUPPORT.
   138  var SocketDisableIPv6 bool
   139  
   140  type Sockaddr interface {
   141  	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
   142  }
   143  
   144  type SockaddrInet4 struct {
   145  	Port int
   146  	Addr [4]byte
   147  	raw  RawSockaddrInet4
   148  }
   149  
   150  type SockaddrInet6 struct {
   151  	Port   int
   152  	ZoneId uint32
   153  	Addr   [16]byte
   154  	raw    RawSockaddrInet6
   155  }
   156  
   157  type SockaddrUnix struct {
   158  	Name string
   159  	raw  RawSockaddrUnix
   160  }
   161  
   162  func Bind(fd int, sa Sockaddr) (err error) {
   163  	ptr, n, err := sa.sockaddr()
   164  	if err != nil {
   165  		return err
   166  	}
   167  	return bind(fd, ptr, n)
   168  }
   169  
   170  func Connect(fd int, sa Sockaddr) (err error) {
   171  	ptr, n, err := sa.sockaddr()
   172  	if err != nil {
   173  		return err
   174  	}
   175  	return connect(fd, ptr, n)
   176  }
   177  
   178  func Getpeername(fd int) (sa Sockaddr, err error) {
   179  	var rsa RawSockaddrAny
   180  	var len _Socklen = SizeofSockaddrAny
   181  	if err = getpeername(fd, &rsa, &len); err != nil {
   182  		return
   183  	}
   184  	return anyToSockaddr(&rsa)
   185  }
   186  
   187  func GetsockoptInt(fd, level, opt int) (value int, err error) {
   188  	var n int32
   189  	vallen := _Socklen(4)
   190  	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
   191  	return int(n), err
   192  }
   193  
   194  func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
   195  	var rsa RawSockaddrAny
   196  	var len _Socklen = SizeofSockaddrAny
   197  	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
   198  		return
   199  	}
   200  	if rsa.Addr.Family != AF_UNSPEC {
   201  		from, err = anyToSockaddr(&rsa)
   202  	}
   203  	return
   204  }
   205  
   206  func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
   207  	ptr, n, err := to.sockaddr()
   208  	if err != nil {
   209  		return err
   210  	}
   211  	return sendto(fd, p, flags, ptr, n)
   212  }
   213  
   214  func SetsockoptByte(fd, level, opt int, value byte) (err error) {
   215  	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
   216  }
   217  
   218  func SetsockoptInt(fd, level, opt int, value int) (err error) {
   219  	var n = int32(value)
   220  	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
   221  }
   222  
   223  func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
   224  	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
   225  }
   226  
   227  func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
   228  	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
   229  }
   230  
   231  func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
   232  	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
   233  }
   234  
   235  func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
   236  	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
   237  }
   238  
   239  func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
   240  	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
   241  }
   242  
   243  func SetsockoptString(fd, level, opt int, s string) (err error) {
   244  	return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s)))
   245  }
   246  
   247  func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
   248  	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
   249  }
   250  
   251  func Socket(domain, typ, proto int) (fd int, err error) {
   252  	if domain == AF_INET6 && SocketDisableIPv6 {
   253  		return -1, EAFNOSUPPORT
   254  	}
   255  	fd, err = socket(domain, typ, proto)
   256  	return
   257  }
   258  
   259  func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
   260  	var fdx [2]int32
   261  	err = socketpair(domain, typ, proto, &fdx)
   262  	if err == nil {
   263  		fd[0] = int(fdx[0])
   264  		fd[1] = int(fdx[1])
   265  	}
   266  	return
   267  }
   268  
   269  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
   270  	if raceenabled {
   271  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   272  	}
   273  	return sendfile(outfd, infd, offset, count)
   274  }
   275  
   276  var ioSync int64
   277  
   278  func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
   279  
   280  func SetNonblock(fd int, nonblocking bool) (err error) {
   281  	flag, err := fcntl(fd, F_GETFL, 0)
   282  	if err != nil {
   283  		return err
   284  	}
   285  	if nonblocking {
   286  		flag |= O_NONBLOCK
   287  	} else {
   288  		flag &= ^O_NONBLOCK
   289  	}
   290  	_, err = fcntl(fd, F_SETFL, flag)
   291  	return err
   292  }