fd_unixjs.mx raw

   1  // Copyright 2023 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 unix || (js && wasm)
   6  
   7  package poll
   8  
   9  import "syscall"
  10  
  11  type SysFile struct {
  12  	// Writev cache.
  13  	iovecs *[]syscall.Iovec
  14  }
  15  
  16  func (s *SysFile) init() {}
  17  
  18  func (s *SysFile) destroy(fd int) error {
  19  	// We don't use ignoringEINTR here because POSIX does not define
  20  	// whether the descriptor is closed if close returns EINTR.
  21  	// If the descriptor is indeed closed, using a loop would race
  22  	// with some other goroutine opening a new descriptor.
  23  	// (The Linux kernel guarantees that it is closed on an EINTR error.)
  24  	return CloseFunc(fd)
  25  }
  26  
  27  // dupCloseOnExecOld is the traditional way to dup an fd and
  28  // set its O_CLOEXEC bit, using two system calls.
  29  func dupCloseOnExecOld(fd int) (int, []byte, error) {
  30  	syscall.ForkLock.RLock()
  31  	defer syscall.ForkLock.RUnlock()
  32  	newfd, err := syscall.Dup(fd)
  33  	if err != nil {
  34  		return -1, "dup", err
  35  	}
  36  	syscall.CloseOnExec(newfd)
  37  	return newfd, "", nil
  38  }
  39  
  40  // Fchdir wraps syscall.Fchdir.
  41  func (fd *FD) Fchdir() error {
  42  	if err := fd.incref(); err != nil {
  43  		return err
  44  	}
  45  	defer fd.decref()
  46  	return syscall.Fchdir(fd.Sysfd)
  47  }
  48  
  49  // ReadDirent wraps syscall.ReadDirent.
  50  // We treat this like an ordinary system call rather than a call
  51  // that tries to fill the buffer.
  52  func (fd *FD) ReadDirent(buf []byte) (int, error) {
  53  	if err := fd.incref(); err != nil {
  54  		return 0, err
  55  	}
  56  	defer fd.decref()
  57  	for {
  58  		n, err := ignoringEINTRIO(syscall.ReadDirent, fd.Sysfd, buf)
  59  		if err != nil {
  60  			n = 0
  61  			if err == syscall.EAGAIN && fd.pd.pollable() {
  62  				if err = fd.pd.waitRead(fd.isFile); err == nil {
  63  					continue
  64  				}
  65  			}
  66  		}
  67  		// Do not call eofError; caller does not expect to see io.EOF.
  68  		return n, err
  69  	}
  70  }
  71  
  72  // Seek wraps syscall.Seek.
  73  func (fd *FD) Seek(offset int64, whence int) (int64, error) {
  74  	if err := fd.incref(); err != nil {
  75  		return 0, err
  76  	}
  77  	defer fd.decref()
  78  	return syscall.Seek(fd.Sysfd, offset, whence)
  79  }
  80