1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Plan 9 system calls.
6 // This file is compiled as ordinary Go code,
7 // but it is also input to mksyscall,
8 // which parses the //sys lines and generates system call stubs.
9 // Note that sometimes we use a lowercase //sys name and
10 // wrap it in our own nicer implementation.
21 const ImplementsGetwd = true
24 // ErrorString implements Error's String method by returning itself.
26 // ErrorString values can be tested against error values using errors.Is.
29 // _, _, err := syscall.Syscall(...)
30 // if errors.Is(err, fs.ErrNotExist) ...
31 type ErrorString string
33 func (e ErrorString) Error() string { return string(e) }
35 // NewError converts s to an ErrorString, which satisfies the Error interface.
36 func NewError(s string) error { return ErrorString(s) }
38 func (e ErrorString) Is(target error) bool {
40 case oserror.ErrPermission:
41 return checkErrMessageContent(e, "permission denied")
42 case oserror.ErrExist:
43 return checkErrMessageContent(e, "exists", "is a directory")
44 case oserror.ErrNotExist:
45 return checkErrMessageContent(e, "does not exist", "not found",
46 "has been removed", "no parent")
47 case errors.ErrUnsupported:
48 return checkErrMessageContent(e, "not supported")
53 // checkErrMessageContent checks if err message contains one of msgs.
54 func checkErrMessageContent(e ErrorString, msgs ...string) bool {
55 for _, msg := range msgs {
56 if contains(string(e), msg) {
63 // contains is a local version of strings.Contains. It knows len(sep) > 1.
64 func contains(s, sep string) bool {
67 for i := 0; i+n <= len(s); i++ {
68 if s[i] == c && s[i:i+n] == sep {
75 func (e ErrorString) Temporary() bool {
76 return e == EINTR || e == EMFILE || e.Timeout()
79 func (e ErrorString) Timeout() bool {
80 return e == EBUSY || e == ETIMEDOUT
83 var emptystring string
85 // A Note is a string describing a process note.
86 // It implements the os.Signal interface.
89 func (n Note) Signal() {}
91 func (n Note) String() string {
101 // For testing: clients can set this flag to force
102 // creation of IPv6 sockets to return EAFNOSUPPORT.
103 var SocketDisableIPv6 bool
105 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
106 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
107 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
108 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
111 func atoi(b []byte) (n uint) {
113 for i := 0; i < len(b); i++ {
114 n = n*10 + uint(b[i]-'0')
119 func cstring(s []byte) string {
122 return string(s[0:i])
128 func errstr() string {
131 RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
134 return cstring(buf[:])
137 func readnum(path string) (uint, error) {
140 fd, e := Open(path, O_RDONLY)
146 n, e := Pread(fd, b[:], 0)
153 for ; m < n && b[m] == ' '; m++ {
156 return atoi(b[m : n-1]), nil
159 func Getpid() (pid int) {
160 n, _ := readnum("#c/pid")
164 func Getppid() (ppid int) {
165 n, _ := readnum("#c/ppid")
169 func Read(fd int, p []byte) (n int, err error) {
170 return Pread(fd, p, -1)
173 func Write(fd int, p []byte) (n int, err error) {
174 if faketime && (fd == 1 || fd == 2) {
175 n = faketimeWrite(fd, p)
177 return 0, ErrorString("error")
182 return Pwrite(fd, p, -1)
187 //sys fd2path(fd int, buf []byte) (err error)
189 func Fd2path(fd int) (path string, err error) {
192 e := fd2path(fd, buf[:])
196 return cstring(buf[:]), nil
199 //sys pipe(p *[2]int32) (err error)
201 func Pipe(p []int) (err error) {
203 return NewError("bad arg in system call")
214 // Underlying system call writes to newoffset via pointer.
215 // Implemented in assembly to avoid allocation.
216 func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
218 func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
219 newoffset, e := seek(0, fd, offset, whence)
227 func Mkdir(path string, mode uint32) (err error) {
228 // If path exists and is not a directory, Create will fail silently.
229 // Work around this by rejecting Mkdir if path exists.
230 statbuf := make([]byte, bitSize16)
231 // Remove any trailing slashes from path, otherwise the Stat will
232 // fail with ENOTDIR.
234 for n > 1 && path[n-1] == '/' {
237 _, err = Stat(path[0:n], statbuf)
242 fd, err := Create(path, O_RDONLY, DMDIR|mode)
251 type Waitmsg struct {
257 func (w Waitmsg) Exited() bool { return true }
258 func (w Waitmsg) Signaled() bool { return false }
260 func (w Waitmsg) ExitStatus() int {
262 // a normal exit returns no message
268 //sys await(s []byte) (n int, err error)
270 func Await(w *Waitmsg) (err error) {
274 n, err := await(buf[:])
276 if err != nil || w == nil {
282 for i := 0; i < n && nf < len(f)-1; i++ {
293 return NewError("invalid wait message")
295 w.Pid = int(atoi(f[0]))
296 w.Time[0] = uint32(atoi(f[1]))
297 w.Time[1] = uint32(atoi(f[2]))
298 w.Time[2] = uint32(atoi(f[3]))
299 w.Msg = cstring(f[4])
301 // await() returns '' for no error
307 func Unmount(name, old string) (err error) {
308 if fixwd(name, old) {
309 defer runtime.UnlockOSThread()
311 oldp, err := BytePtrFromString(old)
315 oldptr := uintptr(unsafe.Pointer(oldp))
320 // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
322 r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
324 namep, err := BytePtrFromString(name)
328 r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
337 func Fchdir(fd int) (err error) {
338 path, err := Fd2path(fd)
347 type Timespec struct {
352 type Timeval struct {
357 func NsecToTimeval(nsec int64) (tv Timeval) {
358 nsec += 999 // round up to microsecond
359 tv.Usec = int32(nsec % 1e9 / 1e3)
360 tv.Sec = int32(nsec / 1e9)
367 r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
368 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
375 func Gettimeofday(tv *Timeval) error {
377 *tv = NsecToTimeval(nsec)
381 func Getegid() (egid int) { return -1 }
382 func Geteuid() (euid int) { return -1 }
383 func Getgid() (gid int) { return -1 }
384 func Getuid() (uid int) { return -1 }
386 func Getgroups() (gids []int, err error) {
387 return make([]int, 0), nil
390 //sys open(path string, mode int) (fd int, err error)
392 func Open(path string, mode int) (fd int, err error) {
394 defer runtime.UnlockOSThread()
396 return open(path, mode)
399 //sys create(path string, mode int, perm uint32) (fd int, err error)
401 func Create(path string, mode int, perm uint32) (fd int, err error) {
403 defer runtime.UnlockOSThread()
405 return create(path, mode, perm)
408 //sys remove(path string) (err error)
410 func Remove(path string) error {
412 defer runtime.UnlockOSThread()
417 //sys stat(path string, edir []byte) (n int, err error)
419 func Stat(path string, edir []byte) (n int, err error) {
421 defer runtime.UnlockOSThread()
423 return stat(path, edir)
426 //sys bind(name string, old string, flag int) (err error)
428 func Bind(name string, old string, flag int) (err error) {
429 if fixwd(name, old) {
430 defer runtime.UnlockOSThread()
432 return bind(name, old, flag)
435 //sys mount(fd int, afd int, old string, flag int, aname string) (err error)
437 func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
439 defer runtime.UnlockOSThread()
441 return mount(fd, afd, old, flag, aname)
444 //sys wstat(path string, edir []byte) (err error)
446 func Wstat(path string, edir []byte) (err error) {
448 defer runtime.UnlockOSThread()
450 return wstat(path, edir)
453 //sys chdir(path string) (err error)
454 //sys Dup(oldfd int, newfd int) (fd int, err error)
455 //sys Pread(fd int, p []byte, offset int64) (n int, err error)
456 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
457 //sys Close(fd int) (err error)
458 //sys Fstat(fd int, edir []byte) (n int, err error)
459 //sys Fwstat(fd int, edir []byte) (err error)