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