summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/internal/sys/lazy.go
blob: fe233d29ea004c395cad8935192ade4d5f3db21b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package sys

import (
	experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
	"github.com/tetratelabs/wazero/internal/fsapi"
	"github.com/tetratelabs/wazero/sys"
)

// compile-time check to ensure lazyDir implements sys.File.
var _ experimentalsys.File = (*lazyDir)(nil)

type lazyDir struct {
	experimentalsys.DirFile

	fs experimentalsys.FS
	f  experimentalsys.File
}

// Dev implements the same method as documented on sys.File
func (d *lazyDir) Dev() (uint64, experimentalsys.Errno) {
	if f, ok := d.file(); !ok {
		return 0, experimentalsys.EBADF
	} else {
		return f.Dev()
	}
}

// Ino implements the same method as documented on sys.File
func (d *lazyDir) Ino() (sys.Inode, experimentalsys.Errno) {
	if f, ok := d.file(); !ok {
		return 0, experimentalsys.EBADF
	} else {
		return f.Ino()
	}
}

// IsDir implements the same method as documented on sys.File
func (d *lazyDir) IsDir() (bool, experimentalsys.Errno) {
	// Note: we don't return a constant because we don't know if this is really
	// backed by a dir, until the first call.
	if f, ok := d.file(); !ok {
		return false, experimentalsys.EBADF
	} else {
		return f.IsDir()
	}
}

// IsAppend implements the same method as documented on sys.File
func (d *lazyDir) IsAppend() bool {
	return false
}

// SetAppend implements the same method as documented on sys.File
func (d *lazyDir) SetAppend(bool) experimentalsys.Errno {
	return experimentalsys.EISDIR
}

// Seek implements the same method as documented on sys.File
func (d *lazyDir) Seek(offset int64, whence int) (newOffset int64, errno experimentalsys.Errno) {
	if f, ok := d.file(); !ok {
		return 0, experimentalsys.EBADF
	} else {
		return f.Seek(offset, whence)
	}
}

// Stat implements the same method as documented on sys.File
func (d *lazyDir) Stat() (sys.Stat_t, experimentalsys.Errno) {
	if f, ok := d.file(); !ok {
		return sys.Stat_t{}, experimentalsys.EBADF
	} else {
		return f.Stat()
	}
}

// Readdir implements the same method as documented on sys.File
func (d *lazyDir) Readdir(n int) (dirents []experimentalsys.Dirent, errno experimentalsys.Errno) {
	if f, ok := d.file(); !ok {
		return nil, experimentalsys.EBADF
	} else {
		return f.Readdir(n)
	}
}

// Sync implements the same method as documented on sys.File
func (d *lazyDir) Sync() experimentalsys.Errno {
	if f, ok := d.file(); !ok {
		return experimentalsys.EBADF
	} else {
		return f.Sync()
	}
}

// Datasync implements the same method as documented on sys.File
func (d *lazyDir) Datasync() experimentalsys.Errno {
	if f, ok := d.file(); !ok {
		return experimentalsys.EBADF
	} else {
		return f.Datasync()
	}
}

// Utimens implements the same method as documented on sys.File
func (d *lazyDir) Utimens(atim, mtim int64) experimentalsys.Errno {
	if f, ok := d.file(); !ok {
		return experimentalsys.EBADF
	} else {
		return f.Utimens(atim, mtim)
	}
}

// file returns the underlying file or false if it doesn't exist.
func (d *lazyDir) file() (experimentalsys.File, bool) {
	if f := d.f; d.f != nil {
		return f, true
	}
	var errno experimentalsys.Errno
	d.f, errno = d.fs.OpenFile(".", experimentalsys.O_RDONLY, 0)
	switch errno {
	case 0:
		return d.f, true
	case experimentalsys.ENOENT:
		return nil, false
	default:
		panic(errno) // unexpected
	}
}

// Close implements fs.File
func (d *lazyDir) Close() experimentalsys.Errno {
	f := d.f
	if f == nil {
		return 0 // never opened
	}
	return f.Close()
}

// IsNonblock implements the same method as documented on fsapi.File
func (d *lazyDir) IsNonblock() bool {
	return false
}

// SetNonblock implements the same method as documented on fsapi.File
func (d *lazyDir) SetNonblock(bool) experimentalsys.Errno {
	return experimentalsys.EISDIR
}

// Poll implements the same method as documented on fsapi.File
func (d *lazyDir) Poll(fsapi.Pflag, int32) (ready bool, errno experimentalsys.Errno) {
	return false, experimentalsys.ENOSYS
}