1package sys
2
3import (
4 "io"
5 "os"
6
7 experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
8 "github.com/tetratelabs/wazero/internal/fsapi"
9 "github.com/tetratelabs/wazero/internal/sysfs"
10 "github.com/tetratelabs/wazero/sys"
11)
12
13// StdinFile is a fs.ModeDevice file for use implementing FdStdin.
14// This is safer than reading from os.DevNull as it can never overrun
15// operating system file descriptors.
16type StdinFile struct {
17 noopStdinFile
18 io.Reader
19}
20
21// Read implements the same method as documented on sys.File
22func (f *StdinFile) Read(buf []byte) (int, experimentalsys.Errno) {
23 n, err := f.Reader.Read(buf)
24 return n, experimentalsys.UnwrapOSError(err)
25}
26
27type writerFile struct {
28 noopStdoutFile
29
30 w io.Writer
31}
32
33// Write implements the same method as documented on sys.File
34func (f *writerFile) Write(buf []byte) (int, experimentalsys.Errno) {
35 n, err := f.w.Write(buf)
36 return n, experimentalsys.UnwrapOSError(err)
37}
38
39// noopStdinFile is a fs.ModeDevice file for use implementing FdStdin. This is
40// safer than reading from os.DevNull as it can never overrun operating system
41// file descriptors.
42type noopStdinFile struct {
43 noopStdioFile
44}
45
46// Read implements the same method as documented on sys.File
47func (noopStdinFile) Read([]byte) (int, experimentalsys.Errno) {
48 return 0, 0 // Always EOF
49}
50
51// Poll implements the same method as documented on fsapi.File
52func (noopStdinFile) Poll(flag fsapi.Pflag, timeoutMillis int32) (ready bool, errno experimentalsys.Errno) {
53 if flag != fsapi.POLLIN {
54 return false, experimentalsys.ENOTSUP
55 }
56 return true, 0 // always ready to read nothing
57}
58
59// noopStdoutFile is a fs.ModeDevice file for use implementing FdStdout and
60// FdStderr.
61type noopStdoutFile struct {
62 noopStdioFile
63}
64
65// Write implements the same method as documented on sys.File
66func (noopStdoutFile) Write(buf []byte) (int, experimentalsys.Errno) {
67 return len(buf), 0 // same as io.Discard
68}
69
70type noopStdioFile struct {
71 experimentalsys.UnimplementedFile
72}
73
74// Stat implements the same method as documented on sys.File
75func (noopStdioFile) Stat() (sys.Stat_t, experimentalsys.Errno) {
76 return sys.Stat_t{Mode: modeDevice, Nlink: 1}, 0
77}
78
79// IsDir implements the same method as documented on sys.File
80func (noopStdioFile) IsDir() (bool, experimentalsys.Errno) {
81 return false, 0
82}
83
84// Close implements the same method as documented on sys.File
85func (noopStdioFile) Close() (errno experimentalsys.Errno) { return }
86
87// IsNonblock implements the same method as documented on fsapi.File
88func (noopStdioFile) IsNonblock() bool {
89 return false
90}
91
92// SetNonblock implements the same method as documented on fsapi.File
93func (noopStdioFile) SetNonblock(bool) experimentalsys.Errno {
94 return experimentalsys.ENOSYS
95}
96
97// Poll implements the same method as documented on fsapi.File
98func (noopStdioFile) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) {
99 return false, experimentalsys.ENOSYS
100}
101
102func stdinFileEntry(r io.Reader) (*FileEntry, error) {
103 if r == nil {
104 return &FileEntry{Name: "stdin", IsPreopen: true, File: &noopStdinFile{}}, nil
105 } else if f, ok := r.(*os.File); ok {
106 if f, err := sysfs.NewStdioFile(true, f); err != nil {
107 return nil, err
108 } else {
109 return &FileEntry{Name: "stdin", IsPreopen: true, File: f}, nil
110 }
111 } else {
112 return &FileEntry{Name: "stdin", IsPreopen: true, File: &StdinFile{Reader: r}}, nil
113 }
114}
115
116func stdioWriterFileEntry(name string, w io.Writer) (*FileEntry, error) {
117 if w == nil {
118 return &FileEntry{Name: name, IsPreopen: true, File: &noopStdoutFile{}}, nil
119 } else if f, ok := w.(*os.File); ok {
120 if f, err := sysfs.NewStdioFile(false, f); err != nil {
121 return nil, err
122 } else {
123 return &FileEntry{Name: name, IsPreopen: true, File: f}, nil
124 }
125 } else {
126 return &FileEntry{Name: name, IsPreopen: true, File: &writerFile{w: w}}, nil
127 }
128}