Source file
src/os/file_plan9.go
1
2
3
4
5 package os
6
7 import (
8 "internal/bytealg"
9 "internal/poll"
10 "internal/stringslite"
11 "io"
12 "runtime"
13 "sync"
14 "sync/atomic"
15 "syscall"
16 "time"
17 )
18
19
20 func fixLongPath(path string) string {
21 return path
22 }
23
24
25
26
27
28 type file struct {
29 fdmu poll.FDMutex
30 sysfd int
31 name string
32 dirinfo atomic.Pointer[dirInfo]
33 appendMode bool
34 }
35
36
37 func (f *File) fd() uintptr {
38 if f == nil {
39 return ^(uintptr(0))
40 }
41 return uintptr(f.sysfd)
42 }
43
44
45 func newFileFromNewFile(fd uintptr, name string) *File {
46 fdi := int(fd)
47 if fdi < 0 {
48 return nil
49 }
50 f := &File{&file{sysfd: fdi, name: name}}
51 runtime.SetFinalizer(f.file, (*file).close)
52 return f
53 }
54
55
56 type dirInfo struct {
57 mu sync.Mutex
58 buf [syscall.STATMAX]byte
59 nbuf int
60 bufp int
61 }
62
63 func epipecheck(file *File, e error) {
64 }
65
66
67
68 const DevNull = "/dev/null"
69
70
71 func syscallMode(i FileMode) (o uint32) {
72 o |= uint32(i.Perm())
73 if i&ModeAppend != 0 {
74 o |= syscall.DMAPPEND
75 }
76 if i&ModeExclusive != 0 {
77 o |= syscall.DMEXCL
78 }
79 if i&ModeTemporary != 0 {
80 o |= syscall.DMTMP
81 }
82 return
83 }
84
85
86 func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
87 var (
88 fd int
89 e error
90 create bool
91 excl bool
92 trunc bool
93 append bool
94 )
95
96 if flag&O_CREATE == O_CREATE {
97 flag = flag & ^O_CREATE
98 create = true
99 }
100 if flag&O_EXCL == O_EXCL {
101 excl = true
102 }
103 if flag&O_TRUNC == O_TRUNC {
104 trunc = true
105 }
106
107 if flag&O_APPEND == O_APPEND {
108 flag = flag &^ O_APPEND
109 append = true
110 }
111
112 if (create && trunc) || excl {
113 fd, e = syscall.Create(name, flag, syscallMode(perm))
114 } else {
115 fd, e = syscall.Open(name, flag)
116 if IsNotExist(e) && create {
117 fd, e = syscall.Create(name, flag, syscallMode(perm))
118 if e != nil {
119 return nil, &PathError{Op: "create", Path: name, Err: e}
120 }
121 }
122 }
123
124 if e != nil {
125 return nil, &PathError{Op: "open", Path: name, Err: e}
126 }
127
128 if append {
129 if _, e = syscall.Seek(fd, 0, io.SeekEnd); e != nil {
130 return nil, &PathError{Op: "seek", Path: name, Err: e}
131 }
132 }
133
134 return NewFile(uintptr(fd), name), nil
135 }
136
137 func openDirNolog(name string) (*File, error) {
138 f, e := openFileNolog(name, O_RDONLY, 0)
139 if e != nil {
140 return nil, e
141 }
142 d, e := f.Stat()
143 if e != nil {
144 f.Close()
145 return nil, e
146 }
147 if !d.IsDir() {
148 f.Close()
149 return nil, &PathError{Op: "open", Path: name, Err: syscall.ENOTDIR}
150 }
151 return f, nil
152 }
153
154
155
156
157
158 func (f *File) Close() error {
159 if f == nil {
160 return ErrInvalid
161 }
162 return f.file.close()
163 }
164
165 func (file *file) close() error {
166 if !file.fdmu.IncrefAndClose() {
167 return &PathError{Op: "close", Path: file.name, Err: ErrClosed}
168 }
169
170
171
172
173 err := file.decref()
174
175
176 runtime.SetFinalizer(file, nil)
177 return err
178 }
179
180
181
182
183 func (file *file) destroy() error {
184 var err error
185 if e := syscall.Close(file.sysfd); e != nil {
186 err = &PathError{Op: "close", Path: file.name, Err: e}
187 }
188 return err
189 }
190
191
192
193 func (f *File) Stat() (FileInfo, error) {
194 if f == nil {
195 return nil, ErrInvalid
196 }
197 d, err := dirstat(f)
198 if err != nil {
199 return nil, err
200 }
201 return fileInfoFromStat(d), nil
202 }
203
204
205
206
207 func (f *File) Truncate(size int64) error {
208 if f == nil {
209 return ErrInvalid
210 }
211
212 var d syscall.Dir
213 d.Null()
214 d.Length = size
215
216 var buf [syscall.STATFIXLEN]byte
217 n, err := d.Marshal(buf[:])
218 if err != nil {
219 return &PathError{Op: "truncate", Path: f.name, Err: err}
220 }
221
222 if err := f.incref("truncate"); err != nil {
223 return err
224 }
225 defer f.decref()
226
227 if err = syscall.Fwstat(f.sysfd, buf[:n]); err != nil {
228 return &PathError{Op: "truncate", Path: f.name, Err: err}
229 }
230 return nil
231 }
232
233 const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm)
234
235 func (f *File) chmod(mode FileMode) error {
236 if f == nil {
237 return ErrInvalid
238 }
239 var d syscall.Dir
240
241 odir, e := dirstat(f)
242 if e != nil {
243 return &PathError{Op: "chmod", Path: f.name, Err: e}
244 }
245 d.Null()
246 d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
247
248 var buf [syscall.STATFIXLEN]byte
249 n, err := d.Marshal(buf[:])
250 if err != nil {
251 return &PathError{Op: "chmod", Path: f.name, Err: err}
252 }
253
254 if err := f.incref("chmod"); err != nil {
255 return err
256 }
257 defer f.decref()
258
259 if err = syscall.Fwstat(f.sysfd, buf[:n]); err != nil {
260 return &PathError{Op: "chmod", Path: f.name, Err: err}
261 }
262 return nil
263 }
264
265
266
267
268 func (f *File) Sync() error {
269 if f == nil {
270 return ErrInvalid
271 }
272 var d syscall.Dir
273 d.Null()
274
275 var buf [syscall.STATFIXLEN]byte
276 n, err := d.Marshal(buf[:])
277 if err != nil {
278 return &PathError{Op: "sync", Path: f.name, Err: err}
279 }
280
281 if err := f.incref("sync"); err != nil {
282 return err
283 }
284 defer f.decref()
285
286 if err = syscall.Fwstat(f.sysfd, buf[:n]); err != nil {
287 return &PathError{Op: "sync", Path: f.name, Err: err}
288 }
289 return nil
290 }
291
292
293
294 func (f *File) read(b []byte) (n int, err error) {
295 if err := f.readLock(); err != nil {
296 return 0, err
297 }
298 defer f.readUnlock()
299 n, e := fixCount(syscall.Read(f.sysfd, b))
300 if n == 0 && len(b) > 0 && e == nil {
301 return 0, io.EOF
302 }
303 return n, e
304 }
305
306
307
308
309 func (f *File) pread(b []byte, off int64) (n int, err error) {
310 if err := f.readLock(); err != nil {
311 return 0, err
312 }
313 defer f.readUnlock()
314 n, e := fixCount(syscall.Pread(f.sysfd, b, off))
315 if n == 0 && len(b) > 0 && e == nil {
316 return 0, io.EOF
317 }
318 return n, e
319 }
320
321
322
323
324
325 func (f *File) write(b []byte) (n int, err error) {
326 if err := f.writeLock(); err != nil {
327 return 0, err
328 }
329 defer f.writeUnlock()
330 if len(b) == 0 {
331 return 0, nil
332 }
333 return fixCount(syscall.Write(f.sysfd, b))
334 }
335
336
337
338
339
340 func (f *File) pwrite(b []byte, off int64) (n int, err error) {
341 if err := f.writeLock(); err != nil {
342 return 0, err
343 }
344 defer f.writeUnlock()
345 if len(b) == 0 {
346 return 0, nil
347 }
348 return fixCount(syscall.Pwrite(f.sysfd, b, off))
349 }
350
351
352
353
354
355 func (f *File) seek(offset int64, whence int) (ret int64, err error) {
356 if err := f.incref(""); err != nil {
357 return 0, err
358 }
359 defer f.decref()
360
361
362 f.dirinfo.Store(nil)
363 return syscall.Seek(f.sysfd, offset, whence)
364 }
365
366
367
368
369 func Truncate(name string, size int64) error {
370 var d syscall.Dir
371
372 d.Null()
373 d.Length = size
374
375 var buf [syscall.STATFIXLEN]byte
376 n, err := d.Marshal(buf[:])
377 if err != nil {
378 return &PathError{Op: "truncate", Path: name, Err: err}
379 }
380 if err = syscall.Wstat(name, buf[:n]); err != nil {
381 return &PathError{Op: "truncate", Path: name, Err: err}
382 }
383 return nil
384 }
385
386
387
388 func Remove(name string) error {
389 if e := syscall.Remove(name); e != nil {
390 return &PathError{Op: "remove", Path: name, Err: e}
391 }
392 return nil
393 }
394
395 func rename(oldname, newname string) error {
396 dirname := oldname[:bytealg.LastIndexByteString(oldname, '/')+1]
397 if stringslite.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.sysfd); 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
625 func ignoringEINTR2[T any](fn func() (T, error)) (T, error) {
626 return fn()
627 }
628
View as plain text