1package sys
2
3import (
4 experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
5 "github.com/tetratelabs/wazero/internal/fsapi"
6 "github.com/tetratelabs/wazero/sys"
7)
8
9// compile-time check to ensure lazyDir implements sys.File.
10var _ experimentalsys.File = (*lazyDir)(nil)
11
12type lazyDir struct {
13 experimentalsys.DirFile
14
15 fs experimentalsys.FS
16 f experimentalsys.File
17}
18
19// Dev implements the same method as documented on sys.File
20func (d *lazyDir) Dev() (uint64, experimentalsys.Errno) {
21 if f, ok := d.file(); !ok {
22 return 0, experimentalsys.EBADF
23 } else {
24 return f.Dev()
25 }
26}
27
28// Ino implements the same method as documented on sys.File
29func (d *lazyDir) Ino() (sys.Inode, experimentalsys.Errno) {
30 if f, ok := d.file(); !ok {
31 return 0, experimentalsys.EBADF
32 } else {
33 return f.Ino()
34 }
35}
36
37// IsDir implements the same method as documented on sys.File
38func (d *lazyDir) IsDir() (bool, experimentalsys.Errno) {
39 // Note: we don't return a constant because we don't know if this is really
40 // backed by a dir, until the first call.
41 if f, ok := d.file(); !ok {
42 return false, experimentalsys.EBADF
43 } else {
44 return f.IsDir()
45 }
46}
47
48// IsAppend implements the same method as documented on sys.File
49func (d *lazyDir) IsAppend() bool {
50 return false
51}
52
53// SetAppend implements the same method as documented on sys.File
54func (d *lazyDir) SetAppend(bool) experimentalsys.Errno {
55 return experimentalsys.EISDIR
56}
57
58// Seek implements the same method as documented on sys.File
59func (d *lazyDir) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) {
60 if f, ok := d.file(); !ok {
61 return 0, experimentalsys.EBADF
62 } else {
63 return f.Seek(offset, whence)
64 }
65}
66
67// Stat implements the same method as documented on sys.File
68func (d *lazyDir) Stat() (sys.Stat_t, experimentalsys.Errno) {
69 if f, ok := d.file(); !ok {
70 return sys.Stat_t{}, experimentalsys.EBADF
71 } else {
72 return f.Stat()
73 }
74}
75
76// Readdir implements the same method as documented on sys.File
77func (d *lazyDir) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) {
78 if f, ok := d.file(); !ok {
79 return nil, experimentalsys.EBADF
80 } else {
81 return f.Readdir(n)
82 }
83}
84
85// Sync implements the same method as documented on sys.File
86func (d *lazyDir) Sync() experimentalsys.Errno {
87 if f, ok := d.file(); !ok {
88 return experimentalsys.EBADF
89 } else {
90 return f.Sync()
91 }
92}
93
94// Datasync implements the same method as documented on sys.File
95func (d *lazyDir) Datasync() experimentalsys.Errno {
96 if f, ok := d.file(); !ok {
97 return experimentalsys.EBADF
98 } else {
99 return f.Datasync()
100 }
101}
102
103// Utimens implements the same method as documented on sys.File
104func (d *lazyDir) Utimens(atim, mtim int64) experimentalsys.Errno {
105 if f, ok := d.file(); !ok {
106 return experimentalsys.EBADF
107 } else {
108 return f.Utimens(atim, mtim)
109 }
110}
111
112// file returns the underlying file or false if it doesn't exist.
113func (d *lazyDir) file() (experimentalsys.File, bool) {
114 if f := d.f; d.f != nil {
115 return f, true
116 }
117 var errno experimentalsys.Errno
118 d.f, errno = d.fs.OpenFile(".", experimentalsys.O_RDONLY, 0)
119 switch errno {
120 case 0:
121 return d.f, true
122 case experimentalsys.ENOENT:
123 return nil, false
124 default:
125 panic(errno) // unexpected
126 }
127}
128
129// Close implements fs.File
130func (d *lazyDir) Close() experimentalsys.Errno {
131 f := d.f
132 if f == nil {
133 return 0 // never opened
134 }
135 return f.Close()
136}
137
138// IsNonblock implements the same method as documented on fsapi.File
139func (d *lazyDir) IsNonblock() bool {
140 return false
141}
142
143// SetNonblock implements the same method as documented on fsapi.File
144func (d *lazyDir) SetNonblock(bool) experimentalsys.Errno {
145 return experimentalsys.EISDIR
146}
147
148// Poll implements the same method as documented on fsapi.File
149func (d *lazyDir) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) {
150 return false, experimentalsys.ENOSYS
151}