Source file
src/os/file_plan9.go
1
2
3
4
5 package os
6
7 import (
8 "internal/poll"
9 "io"
10 "runtime"
11 "syscall"
12 "time"
13 )
14
15
16 func fixLongPath(path string) string {
17 return path
18 }
19
20
21
22
23
24 type file struct {
25 fd int
26 name string
27 dirinfo *dirInfo
28 appendMode bool
29 }
30
31
32
33
34
35
36
37
38
39 func (f *File) Fd() uintptr {
40 if f == nil {
41 return ^(uintptr(0))
42 }
43 return uintptr(f.fd)
44 }
45
46
47
48
49 func NewFile(fd uintptr, name string) *File {
50 fdi := int(fd)
51 if fdi < 0 {
52 return nil
53 }
54 f := &File{&file{fd: fdi, name: name}}
55 runtime.SetFinalizer(f.file, (*file).close)
56 return f
57 }
58
59
60 type dirInfo struct {
61 buf [syscall.STATMAX]byte
62 nbuf int
63 bufp int
64 }
65
66 func epipecheck(file *File, e error) {
67 }
68
69
70
71 const DevNull = "/dev/null"
72
73
74 func syscallMode(i FileMode) (o uint32) {
75 o |= uint32(i.Perm())
76 if i&ModeAppend != 0 {
77 o |= syscall.DMAPPEND
78 }
79 if i&ModeExclusive != 0 {
80 o |= syscall.DMEXCL
81 }
82 if i&ModeTemporary != 0 {
83 o |= syscall.DMTMP
84 }
85 return
86 }
87
88
89 func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
90 var (
91 fd int
92 e error
93 create bool
94 excl bool
95 trunc bool
96 append bool
97 )
98
99 if flag&O_CREATE == O_CREATE {
100 flag = flag & ^O_CREATE
101 create = true
102 }
103 if flag&O_EXCL == O_EXCL {
104 excl = true
105 }
106 if flag&O_TRUNC == O_TRUNC {
107 trunc = true
108 }
109
110 if flag&O_APPEND == O_APPEND {
111 flag = flag &^ O_APPEND
112 append = true
113 }
114
115 if (create && trunc) || excl {
116 fd, e = syscall.Create(name, flag, syscallMode(perm))
117 } else {
118 fd, e = syscall.Open(name, flag)
119 if IsNotExist(e) && create {
120 fd, e = syscall.Create(name, flag, syscallMode(perm))
121 if e != nil {
122 return nil, &PathError{Op: "create", Path: name, Err: e}
123 }
124 }
125 }
126
127 if e != nil {
128 return nil, &PathError{Op: "open", Path: name, Err: e}
129 }
130
131 if append {
132 if _, e = syscall.Seek(fd, 0, io.SeekEnd); e != nil {
133 return nil, &PathError{Op: "seek", Path: name, Err: e}
134 }
135 }
136
137 return NewFile(uintptr(fd), name), nil
138 }
139
140
141
142
143
144 func (f *File) Close() error {
145 if err := f.checkValid("close"); err != nil {
146 return err
147 }
148 return f.file.close()
149 }
150
151 func (file *file) close() error {
152 if file == nil || file.fd == badFd {
153 return ErrInvalid
154 }
155 var err error
156 if e := syscall.Close(file.fd); e != nil {
157 err = &PathError{Op: "close", Path: file.name, Err: e}
158 }
159 file.fd = badFd
160
161
162 runtime.SetFinalizer(file, nil)
163 return err
164 }
165
166
167
168 func (f *File) Stat() (FileInfo, error) {
169 if f == nil {
170 return nil, ErrInvalid
171 }
172 d, err := dirstat(f)
173 if err != nil {
174 return nil, err
175 }
176 return fileInfoFromStat(d), nil
177 }
178
179
180
181
182 func (f *File) Truncate(size int64) error {
183 if f == nil {
184 return ErrInvalid
185 }
186
187 var d syscall.Dir
188 d.Null()
189 d.Length = size
190
191 var buf [syscall.STATFIXLEN]byte
192 n, err := d.Marshal(buf[:])
193 if err != nil {
194 return &PathError{Op: "truncate", Path: f.name, Err: err}
195 }
196 if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
197 return &PathError{Op: "truncate", Path: f.name, Err: err}
198 }
199 return nil
200 }
201
202 const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm)
203
204 func (f *File) chmod(mode FileMode) error {
205 if f == nil {
206 return ErrInvalid
207 }
208 var d syscall.Dir
209
210 odir, e := dirstat(f)
211 if e != nil {
212 return &PathError{Op: "chmod", Path: f.name, Err: e}
213 }
214 d.Null()
215 d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
216
217 var buf [syscall.STATFIXLEN]byte
218 n, err := d.Marshal(buf[:])
219 if err != nil {
220 return &PathError{Op: "chmod", Path: f.name, Err: err}
221 }
222 if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
223 return &PathError{Op: "chmod", Path: f.name, Err: err}
224 }
225 return nil
226 }
227
228
229
230
231 func (f *File) Sync() error {
232 if f == nil {
233 return ErrInvalid
234 }
235 var d syscall.Dir
236 d.Null()
237
238 var buf [syscall.STATFIXLEN]byte
239 n, err := d.Marshal(buf[:])
240 if err != nil {
241 return &PathError{Op: "sync", Path: f.name, Err: err}
242 }
243 if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
244 return &PathError{Op: "sync", Path: f.name, Err: err}
245 }
246 return nil
247 }
248
249
250
251 func (f *File) read(b []byte) (n int, err error) {
252 n, e := fixCount(syscall.Read(f.fd, b))
253 if n == 0 && len(b) > 0 && e == nil {
254 return 0, io.EOF
255 }
256 return n, e
257 }
258
259
260
261
262 func (f *File) pread(b []byte, off int64) (n int, err error) {
263 n, e := fixCount(syscall.Pread(f.fd, b, off))
264 if n == 0 && len(b) > 0 && e == nil {
265 return 0, io.EOF
266 }
267 return n, e
268 }
269
270
271
272
273
274 func (f *File) write(b []byte) (n int, err error) {
275 if len(b) == 0 {
276 return 0, nil
277 }
278 return fixCount(syscall.Write(f.fd, b))
279 }
280
281
282
283
284
285 func (f *File) pwrite(b []byte, off int64) (n int, err error) {
286 if len(b) == 0 {
287 return 0, nil
288 }
289 return fixCount(syscall.Pwrite(f.fd, b, off))
290 }
291
292
293
294
295
296 func (f *File) seek(offset int64, whence int) (ret int64, err error) {
297 if f.dirinfo != nil {
298
299
300 f.dirinfo = nil
301 }
302 return syscall.Seek(f.fd, offset, whence)
303 }
304
305
306
307
308 func Truncate(name string, size int64) error {
309 var d syscall.Dir
310
311 d.Null()
312 d.Length = size
313
314 var buf [syscall.STATFIXLEN]byte
315 n, err := d.Marshal(buf[:])
316 if err != nil {
317 return &PathError{Op: "truncate", Path: name, Err: err}
318 }
319 if err = syscall.Wstat(name, buf[:n]); err != nil {
320 return &PathError{Op: "truncate", Path: name, Err: err}
321 }
322 return nil
323 }
324
325
326
327 func Remove(name string) error {
328 if e := syscall.Remove(name); e != nil {
329 return &PathError{Op: "remove", Path: name, Err: e}
330 }
331 return nil
332 }
333
334
335 func hasPrefix(s, prefix string) bool {
336 return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
337 }
338
339 func rename(oldname, newname string) error {
340 dirname := oldname[:lastIndex(oldname, '/')+1]
341 if hasPrefix(newname, dirname) {
342 newname = newname[len(dirname):]
343 } else {
344 return &LinkError{"rename", oldname, newname, ErrInvalid}
345 }
346
347
348
349 if lastIndex(newname, '/') >= 0 {
350 return &LinkError{"rename", oldname, newname, ErrInvalid}
351 }
352
353 var d syscall.Dir
354
355 d.Null()
356 d.Name = newname
357
358 buf := make([]byte, syscall.STATFIXLEN+len(d.Name))
359 n, err := d.Marshal(buf[:])
360 if err != nil {
361 return &LinkError{"rename", oldname, newname, err}
362 }
363
364
365 f, err := Stat(dirname + newname)
366 if err == nil && !f.IsDir() {
367 Remove(dirname + newname)
368 }
369
370 if err = syscall.Wstat(oldname, buf[:n]); err != nil {
371 return &LinkError{"rename", oldname, newname, err}
372 }
373 return nil
374 }
375
376
377 func chmod(name string, mode FileMode) error {
378 var d syscall.Dir
379
380 odir, e := dirstat(name)
381 if e != nil {
382 return &PathError{Op: "chmod", Path: name, Err: e}
383 }
384 d.Null()
385 d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
386
387 var buf [syscall.STATFIXLEN]byte
388 n, err := d.Marshal(buf[:])
389 if err != nil {
390 return &PathError{Op: "chmod", Path: name, Err: err}
391 }
392 if err = syscall.Wstat(name, buf[:n]); err != nil {
393 return &PathError{Op: "chmod", Path: name, Err: err}
394 }
395 return nil
396 }
397
398
399
400
401
402
403
404 func Chtimes(name string, atime time.Time, mtime time.Time) error {
405 var d syscall.Dir
406
407 d.Null()
408 d.Atime = uint32(atime.Unix())
409 d.Mtime = uint32(mtime.Unix())
410
411 var buf [syscall.STATFIXLEN]byte
412 n, err := d.Marshal(buf[:])
413 if err != nil {
414 return &PathError{Op: "chtimes", Path: name, Err: err}
415 }
416 if err = syscall.Wstat(name, buf[:n]); err != nil {
417 return &PathError{Op: "chtimes", Path: name, Err: err}
418 }
419 return nil
420 }
421
422
423
424 func Pipe() (r *File, w *File, err error) {
425 var p [2]int
426
427 if e := syscall.Pipe(p[0:]); e != nil {
428 return nil, nil, NewSyscallError("pipe", e)
429 }
430
431 return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
432 }
433
434
435
436
437
438 func Link(oldname, newname string) error {
439 return &LinkError{"link", oldname, newname, syscall.EPLAN9}
440 }
441
442
443
444
445
446 func Symlink(oldname, newname string) error {
447 return &LinkError{"symlink", oldname, newname, syscall.EPLAN9}
448 }
449
450
451
452 func Readlink(name string) (string, error) {
453 return "", &PathError{Op: "readlink", Path: name, Err: syscall.EPLAN9}
454 }
455
456
457
458
459
460
461
462
463 func Chown(name string, uid, gid int) error {
464 return &PathError{Op: "chown", Path: name, Err: syscall.EPLAN9}
465 }
466
467
468
469
470 func Lchown(name string, uid, gid int) error {
471 return &PathError{Op: "lchown", Path: name, Err: syscall.EPLAN9}
472 }
473
474
475
476 func (f *File) Chown(uid, gid int) error {
477 if f == nil {
478 return ErrInvalid
479 }
480 return &PathError{Op: "chown", Path: f.name, Err: syscall.EPLAN9}
481 }
482
483 func tempDir() string {
484 dir := Getenv("TMPDIR")
485 if dir == "" {
486 dir = "/tmp"
487 }
488 return dir
489
490 }
491
492
493
494
495 func (f *File) Chdir() error {
496 if err := f.checkValid("chdir"); err != nil {
497 return err
498 }
499 if e := syscall.Fchdir(f.fd); e != nil {
500 return &PathError{Op: "chdir", Path: f.name, Err: e}
501 }
502 return nil
503 }
504
505
506 func (f *File) setDeadline(time.Time) error {
507 if err := f.checkValid("SetDeadline"); err != nil {
508 return err
509 }
510 return poll.ErrNoDeadline
511 }
512
513
514 func (f *File) setReadDeadline(time.Time) error {
515 if err := f.checkValid("SetReadDeadline"); err != nil {
516 return err
517 }
518 return poll.ErrNoDeadline
519 }
520
521
522 func (f *File) setWriteDeadline(time.Time) error {
523 if err := f.checkValid("SetWriteDeadline"); err != nil {
524 return err
525 }
526 return poll.ErrNoDeadline
527 }
528
529
530
531 func (f *File) checkValid(op string) error {
532 if f == nil {
533 return ErrInvalid
534 }
535 if f.fd == badFd {
536 return &PathError{Op: op, Path: f.name, Err: ErrClosed}
537 }
538 return nil
539 }
540
541 type rawConn struct{}
542
543 func (c *rawConn) Control(f func(uintptr)) error {
544 return syscall.EPLAN9
545 }
546
547 func (c *rawConn) Read(f func(uintptr) bool) error {
548 return syscall.EPLAN9
549 }
550
551 func (c *rawConn) Write(f func(uintptr) bool) error {
552 return syscall.EPLAN9
553 }
554
555 func newRawConn(file *File) (*rawConn, error) {
556 return nil, syscall.EPLAN9
557 }
558
559 func ignoringEINTR(fn func() error) error {
560 return fn()
561 }
562
View as plain text