summaryrefslogtreecommitdiff
path: root/src/pkg/syscall/syscall_plan9.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/syscall/syscall_plan9.go')
-rw-r--r--src/pkg/syscall/syscall_plan9.go343
1 files changed, 343 insertions, 0 deletions
diff --git a/src/pkg/syscall/syscall_plan9.go b/src/pkg/syscall/syscall_plan9.go
new file mode 100644
index 000000000..831cbddb2
--- /dev/null
+++ b/src/pkg/syscall/syscall_plan9.go
@@ -0,0 +1,343 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9 system calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates system call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package syscall
+
+import "unsafe"
+
+const OS = "plan9"
+
+const ImplementsGetwd = true
+
+// An Error can represent any printable error condition.
+type Error interface {
+ String() string
+}
+
+// ErrorString implements Error's String method by returning itself.
+type ErrorString string
+
+func (e ErrorString) String() string { return string(e) }
+
+// NewError converts s to an ErrorString, which satisfies the Error interface.
+func NewError(s string) Error { return ErrorString(s) }
+
+var (
+ Stdin = 0
+ Stdout = 1
+ Stderr = 2
+
+ EISDIR Error = NewError("file is a directory")
+)
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err string)
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err string)
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+
+func atoi(b []byte) (n uint) {
+ n = 0
+ for i := 0; i < len(b); i++ {
+ n = n*10 + uint(b[i]-'0')
+ }
+ return
+}
+
+func cstring(s []byte) string {
+ for i := range s {
+ if s[i] == 0 {
+ return string(s[0:i])
+ }
+ }
+ return string(s)
+}
+
+func errstr() string {
+ var buf [ERRMAX]byte
+
+ RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
+
+ buf[len(buf)-1] = 0
+ return cstring(buf[:])
+}
+
+func Getpagesize() int { return 4096 }
+
+//sys exits(msg *byte)
+func Exits(msg *string) {
+ if msg == nil {
+ exits(nil)
+ }
+
+ exits(StringBytePtr(*msg))
+}
+
+func Exit(code int) {
+ if code == 0 {
+ Exits(nil)
+ }
+
+ msg := itoa(code)
+ Exits(&msg)
+}
+
+func readnum(path string) (uint, Error) {
+ var b [12]byte
+
+ fd, e := Open(path, O_RDONLY)
+ if e != nil {
+ return 0, e
+ }
+ defer Close(fd)
+
+ n, e := Pread(fd, b[:], 0)
+
+ if e != nil {
+ return 0, e
+ }
+
+ m := 0
+ for ; m < n && b[m] == ' '; m++ {
+ }
+
+ return atoi(b[m : n-1]), nil
+}
+
+func Getpid() (pid int) {
+ n, _ := readnum("#c/pid")
+ return int(n)
+}
+
+func Getppid() (ppid int) {
+ n, _ := readnum("#c/ppid")
+ return int(n)
+}
+
+
+func Read(fd int, p []byte) (n int, err Error) {
+ return Pread(fd, p, -1)
+}
+
+func Write(fd int, p []byte) (n int, err Error) {
+ return Pwrite(fd, p, -1)
+}
+
+func Getwd() (wd string, err Error) {
+ fd, e := Open(".", O_RDONLY)
+
+ if e != nil {
+ return "", e
+ }
+ defer Close(fd)
+
+ return Fd2path(fd)
+}
+
+//sys fd2path(fd int, buf []byte) (err Error)
+func Fd2path(fd int) (path string, err Error) {
+ var buf [512]byte
+
+ e := fd2path(fd, buf[:])
+ if e != nil {
+ return "", e
+ }
+ return cstring(buf[:]), nil
+}
+
+//sys pipe(p *[2]_C_int) (err Error)
+func Pipe(p []int) (err Error) {
+ if len(p) != 2 {
+ return NewError("bad arg in system call")
+ }
+ var pp [2]_C_int
+ err = pipe(&pp)
+ p[0] = int(pp[0])
+ p[1] = int(pp[1])
+ return
+}
+
+
+//sys sleep(millisecs int32) (err Error)
+func Sleep(nsec int64) (err Error) {
+ return sleep(int32((nsec + 999) / 1e6)) // round up to microsecond
+}
+
+// Underlying system call writes to newoffset via pointer.
+// Implemented in assembly to avoid allocation.
+func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err Error) {
+ newoffset, e := seek(0, fd, offset, whence)
+
+ err = nil
+ if newoffset == -1 {
+ err = NewError(e)
+ }
+ return
+}
+
+func Mkdir(path string, mode uint32) (err Error) {
+ fd, err := Create(path, O_RDONLY, DMDIR|mode)
+
+ if fd != -1 {
+ Close(fd)
+ }
+
+ return
+}
+
+type Waitmsg struct {
+ Pid int
+ Time [3]uint32
+ Msg string
+}
+
+//sys await(s []byte) (n int, err Error)
+func Await(w *Waitmsg) (err Error) {
+ var buf [512]byte
+ var f [5][]byte
+
+ n, err := await(buf[:])
+
+ if err != nil || w == nil {
+ return
+ }
+
+ nf := 0
+ p := 0
+ for i := 0; i < n && nf < len(f)-1; i++ {
+ if buf[i] == ' ' {
+ f[nf] = buf[p:i]
+ p = i + 1
+ nf++
+ }
+ }
+ f[nf] = buf[p:]
+ nf++
+
+ if nf != len(f) {
+ return NewError("invalid wait message")
+ }
+ w.Pid = int(atoi(f[0]))
+ w.Time[0] = uint32(atoi(f[1]))
+ w.Time[1] = uint32(atoi(f[2]))
+ w.Time[2] = uint32(atoi(f[3]))
+ w.Msg = string(f[4])
+ return
+}
+
+func Unmount(name, old string) (err Error) {
+ oldp := uintptr(unsafe.Pointer(StringBytePtr(old)))
+
+ var r0 uintptr
+ var e string
+
+ // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
+ if name == "" {
+ r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldp, 0)
+ } else {
+ r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), oldp, 0)
+ }
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+
+func Fchdir(fd int) (err Error) {
+ path, err := Fd2path(fd)
+
+ if err != nil {
+ return
+ }
+
+ return Chdir(path)
+}
+
+type Timeval struct {
+ Sec int32
+ Usec int32
+}
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+ nsec += 999 // round up to microsecond
+ tv.Usec = int32(nsec % 1e9 / 1e3)
+ tv.Sec = int32(nsec / 1e9)
+ return
+}
+
+func DecodeBintime(b []byte) (nsec int64, err Error) {
+ if len(b) != 8 {
+ return -1, NewError("bad /dev/bintime format")
+ }
+ err = nil
+ nsec = int64(b[0])<<56 |
+ int64(b[1])<<48 |
+ int64(b[2])<<40 |
+ int64(b[3])<<32 |
+ int64(b[4])<<24 |
+ int64(b[5])<<16 |
+ int64(b[6])<<8 |
+ int64(b[7])
+ return
+}
+
+func Gettimeofday(tv *Timeval) (err Error) {
+ // TODO(paulzhol):
+ // avoid reopening a file descriptor for /dev/bintime on each call,
+ // use lower-level calls to avoid allocation.
+
+ var b [8]byte
+ var nsec int64
+
+ fd, e := Open("/dev/bintime", O_RDONLY)
+ if e != nil {
+ return e
+ }
+ defer Close(fd)
+
+ if _, e = Pread(fd, b[:], 0); e != nil {
+ return e
+ }
+
+ if nsec, e = DecodeBintime(b[:]); e != nil {
+ return e
+ }
+ *tv = NsecToTimeval(nsec)
+
+ return e
+}
+
+func Getegid() (egid int) { return -1 }
+func Geteuid() (euid int) { return -1 }
+func Getgid() (gid int) { return -1 }
+func Getuid() (uid int) { return -1 }
+
+func Getgroups() (gids []int, err Error) {
+ return make([]int, 0), nil
+}
+
+//sys Dup(oldfd int, newfd int) (fd int, err Error)
+//sys Open(path string, mode int) (fd int, err Error)
+//sys Create(path string, mode int, perm uint32) (fd int, err Error)
+//sys Remove(path string) (err Error)
+//sys Pread(fd int, p []byte, offset int64) (n int, err Error)
+//sys Pwrite(fd int, p []byte, offset int64) (n int, err Error)
+//sys Close(fd int) (err Error)
+//sys Chdir(path string) (err Error)
+//sys Bind(name string, old string, flag int) (err Error)
+//sys Mount(fd int, afd int, old string, flag int, aname string) (err Error)
+//sys Stat(path string, edir []byte) (n int, err Error)
+//sys Fstat(fd int, edir []byte) (n int, err Error)
+//sys Wstat(path string, edir []byte) (err Error)
+//sys Fwstat(fd int, edir []byte) (err Error)