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 7package poll 8 9import "syscall" 10 11type SysFile struct { 12 // Writev cache. 13 iovecs *[]syscall.Iovec 14} 15 16func (s *SysFile) init() {} 17 18func (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. 29func dupCloseOnExecOld(fd int) (int, string, 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. 41func (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. 52func (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. 73func (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