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

View as plain text