github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/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  	"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  // A Signal is a number describing a process signal.
   120  // It implements the os.Signal interface.
   121  type Signal int
   122  
   123  func (s Signal) Signal() {}
   124  
   125  func (s Signal) String() string {
   126  	if 0 <= s && int(s) < len(signals) {
   127  		str := signals[s]
   128  		if str != "" {
   129  			return str
   130  		}
   131  	}
   132  	return "signal " + itoa(int(s))
   133  }
   134  
   135  func Read(fd int, p []byte) (n int, err error) {
   136  	n, err = read(fd, p)
   137  	if raceenabled {
   138  		if n > 0 {
   139  			raceWriteRange(unsafe.Pointer(&p[0]), n)
   140  		}
   141  		if err == nil {
   142  			raceAcquire(unsafe.Pointer(&ioSync))
   143  		}
   144  	}
   145  	return
   146  }
   147  
   148  func Write(fd int, p []byte) (n int, err error) {
   149  	if raceenabled {
   150  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   151  	}
   152  	n, err = write(fd, p)
   153  	if raceenabled && n > 0 {
   154  		raceReadRange(unsafe.Pointer(&p[0]), n)
   155  	}
   156  	return
   157  }
   158  
   159  // For testing: clients can set this flag to force
   160  // creation of IPv6 sockets to return EAFNOSUPPORT.
   161  var SocketDisableIPv6 bool
   162  
   163  type Sockaddr interface {
   164  	sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
   165  }
   166  
   167  type SockaddrInet4 struct {
   168  	Port int
   169  	Addr [4]byte
   170  	raw  RawSockaddrInet4
   171  }
   172  
   173  type SockaddrInet6 struct {
   174  	Port   int
   175  	ZoneId uint32
   176  	Addr   [16]byte
   177  	raw    RawSockaddrInet6
   178  }
   179  
   180  type SockaddrUnix struct {
   181  	Name string
   182  	raw  RawSockaddrUnix
   183  }
   184  
   185  func Bind(fd int, sa Sockaddr) (err error) {
   186  	ptr, n, err := sa.sockaddr()
   187  	if err != nil {
   188  		return err
   189  	}
   190  	return bind(fd, ptr, n)
   191  }
   192  
   193  func Connect(fd int, sa Sockaddr) (err error) {
   194  	ptr, n, err := sa.sockaddr()
   195  	if err != nil {
   196  		return err
   197  	}
   198  	return connect(fd, ptr, n)
   199  }
   200  
   201  func Getpeername(fd int) (sa Sockaddr, err error) {
   202  	var rsa RawSockaddrAny
   203  	var len _Socklen = SizeofSockaddrAny
   204  	if err = getpeername(fd, &rsa, &len); err != nil {
   205  		return
   206  	}
   207  	return anyToSockaddr(&rsa)
   208  }
   209  
   210  func GetsockoptInt(fd, level, opt int) (value int, err error) {
   211  	var n int32
   212  	vallen := _Socklen(4)
   213  	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
   214  	return int(n), err
   215  }
   216  
   217  func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
   218  	var rsa RawSockaddrAny
   219  	var len _Socklen = SizeofSockaddrAny
   220  	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
   221  		return
   222  	}
   223  	if rsa.Addr.Family != AF_UNSPEC {
   224  		from, err = anyToSockaddr(&rsa)
   225  	}
   226  	return
   227  }
   228  
   229  func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
   230  	ptr, n, err := to.sockaddr()
   231  	if err != nil {
   232  		return err
   233  	}
   234  	return sendto(fd, p, flags, ptr, n)
   235  }
   236  
   237  func SetsockoptByte(fd, level, opt int, value byte) (err error) {
   238  	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
   239  }
   240  
   241  func SetsockoptInt(fd, level, opt int, value int) (err error) {
   242  	var n = int32(value)
   243  	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
   244  }
   245  
   246  func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
   247  	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
   248  }
   249  
   250  func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
   251  	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
   252  }
   253  
   254  func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
   255  	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
   256  }
   257  
   258  func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
   259  	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
   260  }
   261  
   262  func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
   263  	return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
   264  }
   265  
   266  func SetsockoptString(fd, level, opt int, s string) (err error) {
   267  	return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s)))
   268  }
   269  
   270  func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
   271  	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
   272  }
   273  
   274  func Socket(domain, typ, proto int) (fd int, err error) {
   275  	if domain == AF_INET6 && SocketDisableIPv6 {
   276  		return -1, EAFNOSUPPORT
   277  	}
   278  	fd, err = socket(domain, typ, proto)
   279  	return
   280  }
   281  
   282  func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
   283  	var fdx [2]int32
   284  	err = socketpair(domain, typ, proto, &fdx)
   285  	if err == nil {
   286  		fd[0] = int(fdx[0])
   287  		fd[1] = int(fdx[1])
   288  	}
   289  	return
   290  }
   291  
   292  func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
   293  	if raceenabled {
   294  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   295  	}
   296  	return sendfile(outfd, infd, offset, count)
   297  }
   298  
   299  var ioSync int64