| // 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) | |
| } |