Black Lives Matter. Support the Equal Justice Initiative.

Source file src/syscall/syscall_unix.go

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

View as plain text