Source file src/syscall/fd_nacl.go
1
2
3
4
5
6
7
8
9
10 package syscall
11
12 import (
13 "io"
14 "sync"
15 )
16
17
18 var files struct {
19 sync.RWMutex
20 tab []*file
21 }
22
23
24
25 type file struct {
26 fdref int
27 impl fileImpl
28 }
29
30
31 type fileImpl interface {
32
33
34 stat(*Stat_t) error
35 read([]byte) (int, error)
36 write([]byte) (int, error)
37 seek(int64, int) (int64, error)
38 pread([]byte, int64) (int, error)
39 pwrite([]byte, int64) (int, error)
40
41
42
43
44 close() error
45 }
46
47
48
49
50 func newFD(impl fileImpl) int {
51 files.Lock()
52 defer files.Unlock()
53 f := &file{impl: impl, fdref: 1}
54 for fd, oldf := range files.tab {
55 if oldf == nil {
56 files.tab[fd] = f
57 return fd
58 }
59 }
60 fd := len(files.tab)
61 files.tab = append(files.tab, f)
62 return fd
63 }
64
65
66 func init() {
67 newFD(&naclFile{naclFD: 0})
68 newFD(&naclFile{naclFD: 1})
69 newFD(&naclFile{naclFD: 2})
70 }
71
72
73 func fdToFile(fd int) (*file, error) {
74 files.Lock()
75 defer files.Unlock()
76 if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil {
77 return nil, EBADF
78 }
79 return files.tab[fd], nil
80 }
81
82 func Close(fd int) error {
83 files.Lock()
84 if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil {
85 files.Unlock()
86 return EBADF
87 }
88 f := files.tab[fd]
89 files.tab[fd] = nil
90 f.fdref--
91 fdref := f.fdref
92 files.Unlock()
93 if fdref > 0 {
94 return nil
95 }
96 return f.impl.close()
97 }
98
99 func CloseOnExec(fd int) {
100
101 }
102
103 func Dup(fd int) (int, error) {
104 files.Lock()
105 defer files.Unlock()
106 if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil {
107 return -1, EBADF
108 }
109 f := files.tab[fd]
110 f.fdref++
111 for newfd, oldf := range files.tab {
112 if oldf == nil {
113 files.tab[newfd] = f
114 return newfd, nil
115 }
116 }
117 newfd := len(files.tab)
118 files.tab = append(files.tab, f)
119 return newfd, nil
120 }
121
122 func Dup2(fd, newfd int) error {
123 files.Lock()
124 if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil || newfd < 0 || newfd >= len(files.tab)+100 {
125 files.Unlock()
126 return EBADF
127 }
128 f := files.tab[fd]
129 f.fdref++
130 for cap(files.tab) <= newfd {
131 files.tab = append(files.tab[:cap(files.tab)], nil)
132 }
133 oldf := files.tab[newfd]
134 var oldfdref int
135 if oldf != nil {
136 oldf.fdref--
137 oldfdref = oldf.fdref
138 }
139 files.tab[newfd] = f
140 files.Unlock()
141 if oldf != nil {
142 if oldfdref == 0 {
143 oldf.impl.close()
144 }
145 }
146 return nil
147 }
148
149 func Fstat(fd int, st *Stat_t) error {
150 f, err := fdToFile(fd)
151 if err != nil {
152 return err
153 }
154 return f.impl.stat(st)
155 }
156
157 func Read(fd int, b []byte) (int, error) {
158 f, err := fdToFile(fd)
159 if err != nil {
160 return 0, err
161 }
162 return f.impl.read(b)
163 }
164
165 var zerobuf [0]byte
166
167 func Write(fd int, b []byte) (int, error) {
168 if b == nil {
169
170 b = zerobuf[:]
171 }
172 f, err := fdToFile(fd)
173 if err != nil {
174 return 0, err
175 }
176 return f.impl.write(b)
177 }
178
179 func Pread(fd int, b []byte, offset int64) (int, error) {
180 f, err := fdToFile(fd)
181 if err != nil {
182 return 0, err
183 }
184 return f.impl.pread(b, offset)
185 }
186
187 func Pwrite(fd int, b []byte, offset int64) (int, error) {
188 f, err := fdToFile(fd)
189 if err != nil {
190 return 0, err
191 }
192 return f.impl.pwrite(b, offset)
193 }
194
195 func Seek(fd int, offset int64, whence int) (int64, error) {
196 f, err := fdToFile(fd)
197 if err != nil {
198 return 0, err
199 }
200 return f.impl.seek(offset, whence)
201 }
202
203
204
205 type defaultFileImpl struct{}
206
207 func (*defaultFileImpl) close() error { return nil }
208 func (*defaultFileImpl) stat(*Stat_t) error { return ENOSYS }
209 func (*defaultFileImpl) read([]byte) (int, error) { return 0, ENOSYS }
210 func (*defaultFileImpl) write([]byte) (int, error) { return 0, ENOSYS }
211 func (*defaultFileImpl) seek(int64, int) (int64, error) { return 0, ENOSYS }
212 func (*defaultFileImpl) pread([]byte, int64) (int, error) { return 0, ENOSYS }
213 func (*defaultFileImpl) pwrite([]byte, int64) (int, error) { return 0, ENOSYS }
214
215
216 type naclFile struct {
217 defaultFileImpl
218 naclFD int
219 }
220
221 func (f *naclFile) stat(st *Stat_t) error {
222 return naclFstat(f.naclFD, st)
223 }
224
225 func (f *naclFile) read(b []byte) (int, error) {
226 n, err := naclRead(f.naclFD, b)
227 if err != nil {
228 n = 0
229 }
230 return n, err
231 }
232
233
234 func naclWrite(fd int, b []byte) int
235
236 func (f *naclFile) write(b []byte) (int, error) {
237 n := naclWrite(f.naclFD, b)
238 if n < 0 {
239 return 0, Errno(-n)
240 }
241 return n, nil
242 }
243
244 func (f *naclFile) seek(off int64, whence int) (int64, error) {
245 old := off
246 err := naclSeek(f.naclFD, &off, whence)
247 if err != nil {
248 return old, err
249 }
250 return off, nil
251 }
252
253 func (f *naclFile) prw(b []byte, offset int64, rw func([]byte) (int, error)) (int, error) {
254
255 old, err := f.seek(0, io.SeekCurrent)
256 if err != nil {
257 return 0, err
258 }
259 if _, err := f.seek(offset, io.SeekStart); err != nil {
260 return 0, err
261 }
262 n, err := rw(b)
263 f.seek(old, io.SeekStart)
264 return n, err
265 }
266
267 func (f *naclFile) pread(b []byte, offset int64) (int, error) {
268 return f.prw(b, offset, f.read)
269 }
270
271 func (f *naclFile) pwrite(b []byte, offset int64) (int, error) {
272 return f.prw(b, offset, f.write)
273 }
274
275 func (f *naclFile) close() error {
276 err := naclClose(f.naclFD)
277 f.naclFD = -1
278 return err
279 }
280
281
282
283 type pipeFile struct {
284 defaultFileImpl
285 rd *byteq
286 wr *byteq
287 }
288
289 func (f *pipeFile) close() error {
290 if f.rd != nil {
291 f.rd.close()
292 }
293 if f.wr != nil {
294 f.wr.close()
295 }
296 return nil
297 }
298
299 func (f *pipeFile) read(b []byte) (int, error) {
300 if f.rd == nil {
301 return 0, EINVAL
302 }
303 n, err := f.rd.read(b, 0)
304 if err == EAGAIN {
305 err = nil
306 }
307 return n, err
308 }
309
310 func (f *pipeFile) write(b []byte) (int, error) {
311 if f.wr == nil {
312 return 0, EINVAL
313 }
314 n, err := f.wr.write(b, 0)
315 if err == EAGAIN {
316 err = EPIPE
317 }
318 return n, err
319 }
320
321 func Pipe(fd []int) error {
322 q := newByteq()
323 fd[0] = newFD(&pipeFile{rd: q})
324 fd[1] = newFD(&pipeFile{wr: q})
325 return nil
326 }
327
View as plain text