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