// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build unix || (js && wasm) package poll import "syscall" type SysFile struct { // Writev cache. iovecs *[]syscall.Iovec } func (s *SysFile) init() {} func (s *SysFile) destroy(fd int) error { // We don't use ignoringEINTR here because POSIX does not define // whether the descriptor is closed if close returns EINTR. // If the descriptor is indeed closed, using a loop would race // with some other goroutine opening a new descriptor. // (The Linux kernel guarantees that it is closed on an EINTR error.) return CloseFunc(fd) } // dupCloseOnExecOld is the traditional way to dup an fd and // set its O_CLOEXEC bit, using two system calls. func dupCloseOnExecOld(fd int) (int, string, error) { syscall.ForkLock.RLock() defer syscall.ForkLock.RUnlock() newfd, err := syscall.Dup(fd) if err != nil { return -1, "dup", err } syscall.CloseOnExec(newfd) return newfd, "", nil } // Fchdir wraps syscall.Fchdir. func (fd *FD) Fchdir() error { if err := fd.incref(); err != nil { return err } defer fd.decref() return syscall.Fchdir(fd.Sysfd) } // ReadDirent wraps syscall.ReadDirent. // We treat this like an ordinary system call rather than a call // that tries to fill the buffer. func (fd *FD) ReadDirent(buf []byte) (int, error) { if err := fd.incref(); err != nil { return 0, err } defer fd.decref() for { n, err := ignoringEINTRIO(syscall.ReadDirent, fd.Sysfd, buf) if err != nil { n = 0 if err == syscall.EAGAIN && fd.pd.pollable() { if err = fd.pd.waitRead(fd.isFile); err == nil { continue } } } // Do not call eofError; caller does not expect to see io.EOF. return n, err } } // Seek wraps syscall.Seek. func (fd *FD) Seek(offset int64, whence int) (int64, error) { if err := fd.incref(); err != nil { return 0, err } defer fd.decref() return syscall.Seek(fd.Sysfd, offset, whence) }