lazy.go

  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}