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