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