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