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