* Re: [9fans] plan9 go output faults on 9vx but ok on cpu
2011-01-15 10:40 ` lucio
@ 2011-01-15 11:25 ` Pavel Zholkover
2011-01-16 1:51 ` kokamoto
0 siblings, 1 reply; 36+ messages in thread
From: Pavel Zholkover @ 2011-01-15 11:25 UTC (permalink / raw)
To: Fans of the OS Plan 9 from Bell Labs
[-- Attachment #1: Type: text/plain, Size: 536 bytes --]
On Sat, Jan 15, 2011 at 12:40 PM, <lucio@proxima.alt.za> wrote:
>> If you try applying http://codereview.appspot.com/3816043/ you can get
>> pretty far..
>
> Could you provide more detailed instructions, please? Mercurial seems
> very helpful, but the learning curve can be quite steep. I presume
> this requires hg to be involved?
>
> ++L
>
There is some trouble using patch to apply the raw patches from the
Rietveld code review site as Skip found out,
So I've attached a diff without the hg history stuff.
Pavel
[-- Attachment #2: issue3816043_43001.diff --]
[-- Type: text/x-patch, Size: 87851 bytes --]
diff -r 09ab865d875c src/pkg/os/Makefile
--- a/src/pkg/os/Makefile Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/Makefile Sat Jan 15 13:00:13 2011 +0200
@@ -19,24 +19,42 @@
types.go\
GOFILES_freebsd=\
+ error_posix.go\
env_unix.go\
+ file_posix.go\
file_unix.go\
sys_bsd.go\
+ exec_unix.go
GOFILES_darwin=\
+ error_posix.go\
env_unix.go\
+ file_posix.go\
file_unix.go\
sys_bsd.go\
+ exec_unix.go
GOFILES_linux=\
+ error_posix.go\
env_unix.go\
+ file_posix.go\
file_unix.go\
sys_linux.go\
+ exec_unix.go
GOFILES_windows=\
+ error_posix.go\
env_windows.go\
+ file_posix.go\
file_windows.go\
sys_windows.go\
+ exec_unix.go
+
+GOFILES_plan9=\
+ error_plan9.go\
+ env_plan9.go\
+ file_plan9.go\
+ sys_plan9.go\
GOFILES+=$(GOFILES_$(GOOS))
diff -r 09ab865d875c src/pkg/os/dir_plan9.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/dir_plan9.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,273 @@
+// Copyright 2009 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.
+
+package os
+
+import (
+ "syscall"
+)
+
+const (
+ blockSize = 4096 // TODO(r): use statfs
+)
+
+type dirInfo int
+
+
+// Readdir reads the contents of the directory associated with file and
+// returns an array of up to count FileInfo structures, as would be returned
+// by Lstat, in directory order. Subsequent calls on the same file will yield
+// further FileInfos.
+// A negative count means to read until EOF.
+// Readdir returns the array and an Error, if any.
+func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
+ size := count
+ if size < 0 {
+ size = 100
+ }
+
+ // ToDo: Investigate a bug in allocation/memory/slice append when more than one iteration of Read is done.
+ result := make([]FileInfo, 0, size)
+ buf := make([]byte, syscall.STATMAX /*448*/ )
+
+ var e Error = nil
+ for e == nil {
+ n, e := file.Read(buf)
+
+ if e != nil {
+ if e == EOF {
+ break
+ }
+
+ return []FileInfo{}, &PathError{"readdir", file.name, e}
+ }
+
+ if n < syscall.STATFIXLEN {
+ return []FileInfo{}, &PathError{"readdir", file.name, syscall.Etoosmall}
+ }
+
+ for i := 0; i < n; {
+ m, _ := gbit16(buf[i:])
+ m += 2
+
+ if m < syscall.STATFIXLEN {
+ return []FileInfo{}, &PathError{"readdir", file.name, syscall.Ebadstat}
+ }
+
+ d, e := UnmarshalDir(buf[i : i+int(m)])
+
+ if e != nil {
+ return []FileInfo{}, &PathError{"readdir", file.name, e}
+ }
+
+ var f FileInfo
+ fileInfoFromStat(&f, d)
+
+ result = append(result, f)
+
+ if count > 0 && len(result) >= count {
+ break
+ }
+
+ i += int(m)
+ }
+ }
+
+ if e != nil && e != EOF {
+ return []FileInfo{}, e
+ }
+
+ return result, nil
+}
+
+func (file *File) Readdirnames(count int) (names []string, err Error) {
+ fi, e := file.Readdir(count)
+
+ if e != nil {
+ return []string{}, e
+ }
+
+ names = make([]string, len(fi))
+ err = nil
+
+ for i, _ := range fi {
+ names[i] = fi[i].Name
+ }
+
+ return
+}
+
+type Dir struct {
+ Type uint16
+ Dev uint32
+ Qid Qid
+ Mode uint32
+ Atime uint32
+ Mtime uint32
+ Length uint64
+ Name string
+ Uid string
+ Gid string
+ Muid string
+}
+
+type Qid struct {
+ Path uint64
+ Vers uint32
+ Type uint8
+}
+
+
+var nullDir = Dir{
+ ^uint16(0),
+ ^uint32(0),
+ Qid{^uint64(0), ^uint32(0), ^uint8(0)},
+ ^uint32(0),
+ ^uint32(0),
+ ^uint32(0),
+ ^uint64(0),
+ "",
+ "",
+ "",
+ "",
+}
+
+func pdir(b []byte, d *Dir) []byte {
+ n := len(b)
+ b = pbit16(b, 0) // length, filled in later
+ b = pbit16(b, d.Type)
+ b = pbit32(b, d.Dev)
+ b = pqid(b, d.Qid)
+ b = pbit32(b, d.Mode)
+ b = pbit32(b, d.Atime)
+ b = pbit32(b, d.Mtime)
+ b = pbit64(b, d.Length)
+ b = pstring(b, d.Name)
+ b = pstring(b, d.Uid)
+ b = pstring(b, d.Gid)
+ b = pstring(b, d.Muid)
+ pbit16(b[0:n], uint16(len(b)-(n+2)))
+ return b
+}
+
+func UnmarshalDir(b []byte) (d *Dir, err Error) {
+ n := uint16(0)
+ n, b = gbit16(b)
+
+ if int(n) != len(b) {
+ return nil, syscall.Ebadstat
+ }
+
+ d = new(Dir)
+ d.Type, b = gbit16(b)
+ d.Dev, b = gbit32(b)
+ d.Qid, b = gqid(b)
+ d.Mode, b = gbit32(b)
+ d.Atime, b = gbit32(b)
+ d.Mtime, b = gbit32(b)
+ d.Length, b = gbit64(b)
+ d.Name, b = gstring(b)
+ d.Uid, b = gstring(b)
+ d.Gid, b = gstring(b)
+ d.Muid, b = gstring(b)
+
+ if len(b) != 0 {
+ return nil, syscall.Ebadstat
+ }
+
+ return d, nil
+}
+
+func gqid(b []byte) (Qid, []byte) {
+ var q Qid
+ q.Path, b = gbit64(b)
+ q.Vers, b = gbit32(b)
+ q.Type, b = gbit8(b)
+ return q, b
+}
+
+func pqid(b []byte, q Qid) []byte {
+ b = pbit64(b, q.Path)
+ b = pbit32(b, q.Vers)
+ b = pbit8(b, q.Type)
+ return b
+}
+
+func gbit8(b []byte) (uint8, []byte) {
+ return uint8(b[0]), b[1:]
+}
+
+func gbit16(b []byte) (uint16, []byte) {
+ return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+func gbit32(b []byte) (uint32, []byte) {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+func gbit64(b []byte) (uint64, []byte) {
+ lo, b := gbit32(b)
+ hi, b := gbit32(b)
+ return uint64(hi)<<32 | uint64(lo), b
+}
+
+func gstring(b []byte) (string, []byte) {
+ n, b := gbit16(b)
+ return string(b[0:n]), b[n:]
+}
+
+func pbit8(b []byte, x uint8) []byte {
+ n := len(b)
+ if n+1 > cap(b) {
+ nb := make([]byte, n, 100+2*cap(b))
+ copy(nb, b)
+ b = nb
+ }
+ b = b[0 : n+1]
+ b[n] = x
+ return b
+}
+
+func pbit16(b []byte, x uint16) []byte {
+ n := len(b)
+ if n+2 > cap(b) {
+ nb := make([]byte, n, 100+2*cap(b))
+ copy(nb, b)
+ b = nb
+ }
+ b = b[0 : n+2]
+ b[n] = byte(x)
+ b[n+1] = byte(x >> 8)
+ return b
+}
+
+func pbit32(b []byte, x uint32) []byte {
+ n := len(b)
+ if n+4 > cap(b) {
+ nb := make([]byte, n, 100+2*cap(b))
+ copy(nb, b)
+ b = nb
+ }
+ b = b[0 : n+4]
+ b[n] = byte(x)
+ b[n+1] = byte(x >> 8)
+ b[n+2] = byte(x >> 16)
+ b[n+3] = byte(x >> 24)
+ return b
+}
+
+func pbit64(b []byte, x uint64) []byte {
+ b = pbit32(b, uint32(x))
+ b = pbit32(b, uint32(x>>32))
+ return b
+}
+
+func pstring(b []byte, s string) []byte {
+ if len(s) >= 1<<16 {
+ panic(NewError("string too long"))
+ }
+ b = pbit16(b, uint16(len(s)))
+ b = append(b, []byte(s)...)
+ return b
+}
diff -r 09ab865d875c src/pkg/os/env_plan9.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/env_plan9.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,131 @@
+// Copyright 2010 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 environment variables.
+
+package os
+
+import (
+ "syscall"
+ "sync"
+)
+
+// ENOENV is the Error indicating that an environment variable does not exist.
+var ENOENV = NewError("no such environment variable")
+
+var env map[string]string
+var once sync.Once
+
+func copyenv() {
+ env = make(map[string]string)
+
+ f, e := Open("#e", O_RDONLY, 0)
+ if iserror(e) {
+ panic(e)
+ }
+
+ fi, e := f.Readdir(-1)
+ if iserror(e) {
+ f.Close()
+ panic(e)
+ }
+ f.Close()
+
+ buf := make([]byte, 4096)
+ for i, _ := range fi {
+ if f, e = Open("#e/"+fi[i].Name, O_RDONLY, 0); iserror(e) {
+ continue
+ }
+
+ if fi[i].Size > int64(cap(buf)) {
+ fi[i].Size = int64(cap(buf)) - 1
+ }
+
+ if fi[i].Size > 0 {
+ n, e := f.Read(buf[0:fi[i].Size])
+
+ if !iserror(e) {
+ buf[n] = 0
+ env[fi[i].Name] = string(buf[0:n])
+ }
+ } else {
+ env[fi[i].Name] = ""
+ }
+
+ f.Close()
+ }
+}
+
+// Getenverror retrieves the value of the environment variable named by the key.
+// It returns the value and an error, if any.
+func Getenverror(key string) (value string, err Error) {
+ once.Do(copyenv)
+
+ if len(key) == 0 {
+ return "", syscall.Enonexist
+ }
+ v, ok := env[key]
+ if !ok {
+ return "", ENOENV
+ }
+ return v, nil
+}
+
+// Getenv retrieves the value of the environment variable named by the key.
+// It returns the value, which will be empty if the variable is not present.
+func Getenv(key string) string {
+ v, _ := Getenverror(key)
+ return v
+}
+
+// Setenv sets the value of the environment variable named by the key.
+// It returns an Error, if any.
+func Setenv(key, value string) Error {
+ once.Do(copyenv)
+
+ if len(key) == 0 {
+ return syscall.Enonexist
+ }
+
+ f, e := Open("#e/"+key, O_WRONLY|O_CREAT, 0666)
+ if iserror(e) {
+ return e
+ }
+ defer f.Close()
+
+ _, e = f.Write(syscall.StringByteSlice(value))
+
+ env[key] = value
+ return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+ once.Do(copyenv) // prevent copyenv in Getenv/Setenv
+ env = make(map[string]string)
+
+ syscall.RawSyscall(syscall.SYS_RFORK, syscall.RFCENVG, 0, 0)
+}
+
+// Environ returns an array of strings representing the environment,
+// in the form "key=value".
+func Environ() []string {
+ once.Do(copyenv)
+ a := make([]string, len(env))
+ i := 0
+ for k, v := range env {
+ // check i < len(a) for safety,
+ // in case env is changing underfoot.
+ if i < len(a) {
+ a[i] = k + "=" + v
+ i++
+ }
+ }
+ return a[0:i]
+}
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+ return "/tmp"
+}
diff -r 09ab865d875c src/pkg/os/error.go
--- a/src/pkg/os/error.go Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/error.go Sat Jan 15 13:00:13 2011 +0200
@@ -4,8 +4,6 @@
package os
-import syscall "syscall"
-
// An Error can represent any printable error condition.
type Error interface {
String() string
@@ -26,61 +24,6 @@
// NewError converts s to an ErrorString, which satisfies the Error interface.
func NewError(s string) Error { return ErrorString(s) }
-// Errno is the Unix error number. Names such as EINVAL are simple
-// wrappers to convert the error number into an Error.
-type Errno int64
-
-func (e Errno) String() string { return syscall.Errstr(int(e)) }
-
-func (e Errno) Temporary() bool {
- return e == Errno(syscall.EINTR) || e.Timeout()
-}
-
-func (e Errno) Timeout() bool {
- return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK)
-}
-
-// Commonly known Unix errors.
-var (
- EPERM Error = Errno(syscall.EPERM)
- ENOENT Error = Errno(syscall.ENOENT)
- ESRCH Error = Errno(syscall.ESRCH)
- EINTR Error = Errno(syscall.EINTR)
- EIO Error = Errno(syscall.EIO)
- ENXIO Error = Errno(syscall.ENXIO)
- E2BIG Error = Errno(syscall.E2BIG)
- ENOEXEC Error = Errno(syscall.ENOEXEC)
- EBADF Error = Errno(syscall.EBADF)
- ECHILD Error = Errno(syscall.ECHILD)
- EDEADLK Error = Errno(syscall.EDEADLK)
- ENOMEM Error = Errno(syscall.ENOMEM)
- EACCES Error = Errno(syscall.EACCES)
- EFAULT Error = Errno(syscall.EFAULT)
- EBUSY Error = Errno(syscall.EBUSY)
- EEXIST Error = Errno(syscall.EEXIST)
- EXDEV Error = Errno(syscall.EXDEV)
- ENODEV Error = Errno(syscall.ENODEV)
- ENOTDIR Error = Errno(syscall.ENOTDIR)
- EISDIR Error = Errno(syscall.EISDIR)
- EINVAL Error = Errno(syscall.EINVAL)
- ENFILE Error = Errno(syscall.ENFILE)
- EMFILE Error = Errno(syscall.EMFILE)
- ENOTTY Error = Errno(syscall.ENOTTY)
- EFBIG Error = Errno(syscall.EFBIG)
- ENOSPC Error = Errno(syscall.ENOSPC)
- ESPIPE Error = Errno(syscall.ESPIPE)
- EROFS Error = Errno(syscall.EROFS)
- EMLINK Error = Errno(syscall.EMLINK)
- EPIPE Error = Errno(syscall.EPIPE)
- EAGAIN Error = Errno(syscall.EAGAIN)
- EDOM Error = Errno(syscall.EDOM)
- ERANGE Error = Errno(syscall.ERANGE)
- EADDRINUSE Error = Errno(syscall.EADDRINUSE)
- ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
- ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
- EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
-)
-
// PathError records an error and the operation and file path that caused it.
type PathError struct {
Op string
@@ -89,25 +32,3 @@
}
func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
-
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
- Syscall string
- Errno Errno
-}
-
-func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
-
-// Note: If the name of the function NewSyscallError changes,
-// pkg/go/doc/doc.go should be adjusted since it hardwires
-// this name in a heuristic.
-
-// NewSyscallError returns, as an Error, a new SyscallError
-// with the given system call name and error number.
-// As a convenience, if errno is 0, NewSyscallError returns nil.
-func NewSyscallError(syscall string, errno int) Error {
- if errno == 0 {
- return nil
- }
- return &SyscallError{syscall, Errno(errno)}
-}
diff -r 09ab865d875c src/pkg/os/error_plan9.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/error_plan9.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,48 @@
+// Copyright 2010 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.
+
+package os
+
+import syscall "syscall"
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+ Syscall string
+ Err string
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Err }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error number.
+// As a convenience, if errno is 0, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err syscall.Error) Error {
+ if err == nil {
+ return nil
+ }
+ return &SyscallError{syscall, err.String()}
+}
+
+var (
+ EINVAL Error = syscall.Ebadarg
+ ENOTDIR Error = syscall.Enotdir
+ ENOENT Error = syscall.Enonexist
+ ENAMETOOLONG Error = NewError("file name too long")
+ EPIPE = syscall.EPIPE
+
+ ERANGE Error = NewError("math result not representable")
+ EEXIST Error = syscall.Eexist
+
+ EPLAN9 Error = NewError("not supported by plan 9")
+)
+
+func iserror(err syscall.Error) bool {
+ return err != nil
+}
+
+func Errno(e syscall.Error) syscall.Error { return e }
diff -r 09ab865d875c src/pkg/os/error_posix.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/error_posix.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,88 @@
+// Copyright 2009 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.
+
+package os
+
+import syscall "syscall"
+
+// Errno is the Unix error number. Names such as EINVAL are simple
+// wrappers to convert the error number into an Error.
+type Errno int64
+
+func (e Errno) String() string { return syscall.Errstr(int(e)) }
+
+func (e Errno) Temporary() bool {
+ return e == Errno(syscall.EINTR) || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+ return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK)
+}
+
+// Commonly known Unix errors.
+var (
+ EPERM Error = Errno(syscall.EPERM)
+ ENOENT Error = Errno(syscall.ENOENT)
+ ESRCH Error = Errno(syscall.ESRCH)
+ EINTR Error = Errno(syscall.EINTR)
+ EIO Error = Errno(syscall.EIO)
+ ENXIO Error = Errno(syscall.ENXIO)
+ E2BIG Error = Errno(syscall.E2BIG)
+ ENOEXEC Error = Errno(syscall.ENOEXEC)
+ EBADF Error = Errno(syscall.EBADF)
+ ECHILD Error = Errno(syscall.ECHILD)
+ EDEADLK Error = Errno(syscall.EDEADLK)
+ ENOMEM Error = Errno(syscall.ENOMEM)
+ EACCES Error = Errno(syscall.EACCES)
+ EFAULT Error = Errno(syscall.EFAULT)
+ EBUSY Error = Errno(syscall.EBUSY)
+ EEXIST Error = Errno(syscall.EEXIST)
+ EXDEV Error = Errno(syscall.EXDEV)
+ ENODEV Error = Errno(syscall.ENODEV)
+ ENOTDIR Error = Errno(syscall.ENOTDIR)
+ EISDIR Error = Errno(syscall.EISDIR)
+ EINVAL Error = Errno(syscall.EINVAL)
+ ENFILE Error = Errno(syscall.ENFILE)
+ EMFILE Error = Errno(syscall.EMFILE)
+ ENOTTY Error = Errno(syscall.ENOTTY)
+ EFBIG Error = Errno(syscall.EFBIG)
+ ENOSPC Error = Errno(syscall.ENOSPC)
+ ESPIPE Error = Errno(syscall.ESPIPE)
+ EROFS Error = Errno(syscall.EROFS)
+ EMLINK Error = Errno(syscall.EMLINK)
+ EPIPE Error = Errno(syscall.EPIPE)
+ EAGAIN Error = Errno(syscall.EAGAIN)
+ EDOM Error = Errno(syscall.EDOM)
+ ERANGE Error = Errno(syscall.ERANGE)
+ EADDRINUSE Error = Errno(syscall.EADDRINUSE)
+ ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
+ ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
+ EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
+)
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+ Syscall string
+ Errno Errno
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error number.
+// As a convenience, if errno is 0, NewSyscallError returns nil.
+func NewSyscallError(syscall string, errno int) Error {
+ if errno == 0 {
+ return nil
+ }
+ return &SyscallError{syscall, Errno(errno)}
+}
+
+func iserror(errno int) bool {
+ return errno != 0
+}
diff -r 09ab865d875c src/pkg/os/exec.go
--- a/src/pkg/os/exec.go Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/exec.go Sat Jan 15 13:00:13 2011 +0200
@@ -8,145 +8,6 @@
"syscall"
)
-// ForkExec forks the current process and invokes Exec with the program, arguments,
-// and environment specified by name, argv, and envv. It returns the process
-// id of the forked process and an Error, if any. The fd array specifies the
-// file descriptors to be set up in the new process: fd[0] will be Unix file
-// descriptor 0 (standard input), fd[1] descriptor 1, and so on. A nil entry
-// will cause the child to have no open file descriptor with that index.
-// If dir is not empty, the child chdirs into the directory before execing the program.
-func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
- if envv == nil {
- envv = Environ()
- }
- // Create array of integer (system) fds.
- intfd := make([]int, len(fd))
- for i, f := range fd {
- if f == nil {
- intfd[i] = -1
- } else {
- intfd[i] = f.Fd()
- }
- }
-
- p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
- if e != 0 {
- return 0, &PathError{"fork/exec", name, Errno(e)}
- }
- return p, nil
-}
-
-// Exec replaces the current process with an execution of the
-// named binary, with arguments argv and environment envv.
-// If successful, Exec never returns. If it fails, it returns an Error.
-// ForkExec is almost always a better way to execute a program.
-func Exec(name string, argv []string, envv []string) Error {
- if envv == nil {
- envv = Environ()
- }
- e := syscall.Exec(name, argv, envv)
- if e != 0 {
- return &PathError{"exec", name, Errno(e)}
- }
- return nil
-}
-
-// TODO(rsc): Should os implement its own syscall.WaitStatus
-// wrapper with the methods, or is exposing the underlying one enough?
-//
-// TODO(rsc): Certainly need to have Rusage struct,
-// since syscall one might have different field types across
-// different OS.
-
-// Waitmsg stores the information about an exited process as reported by Wait.
-type Waitmsg struct {
- Pid int // The process's id.
- syscall.WaitStatus // System-dependent status info.
- Rusage *syscall.Rusage // System-dependent resource usage info.
-}
-
-// Options for Wait.
-const (
- WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
- WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
- WUNTRACED = WSTOPPED
- WRUSAGE = 1 << 20 // Record resource usage.
-)
-
-// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
-// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
-// the options
-
-// Wait waits for process pid to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
-// (WNOHANG etc.) affect the behavior of the Wait call.
-func Wait(pid int, options int) (w *Waitmsg, err Error) {
- var status syscall.WaitStatus
- var rusage *syscall.Rusage
- if options&WRUSAGE != 0 {
- rusage = new(syscall.Rusage)
- options ^= WRUSAGE
- }
- pid1, e := syscall.Wait4(pid, &status, options, rusage)
- if e != 0 {
- return nil, NewSyscallError("wait", e)
- }
- w = new(Waitmsg)
- w.Pid = pid1
- w.WaitStatus = status
- w.Rusage = rusage
- return w, nil
-}
-
-// Convert i to decimal string.
-func itod(i int) string {
- if i == 0 {
- return "0"
- }
-
- u := uint64(i)
- if i < 0 {
- u = -u
- }
-
- // Assemble decimal in reverse order.
- var b [32]byte
- bp := len(b)
- for ; u > 0; u /= 10 {
- bp--
- b[bp] = byte(u%10) + '0'
- }
-
- if i < 0 {
- bp--
- b[bp] = '-'
- }
-
- return string(b[bp:])
-}
-
-func (w Waitmsg) String() string {
- // TODO(austin) Use signal names when possible?
- res := ""
- switch {
- case w.Exited():
- res = "exit status " + itod(w.ExitStatus())
- case w.Signaled():
- res = "signal " + itod(w.Signal())
- case w.Stopped():
- res = "stop signal " + itod(w.StopSignal())
- if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
- res += " (trap " + itod(w.TrapCause()) + ")"
- }
- case w.Continued():
- res = "continued"
- }
- if w.CoreDump() {
- res += " (core dumped)"
- }
- return res
-}
-
// Getpid returns the process id of the caller.
func Getpid() int { return syscall.Getpid() }
diff -r 09ab865d875c src/pkg/os/exec_unix.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/exec_unix.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,148 @@
+// Copyright 2009 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.
+
+package os
+
+import (
+ "syscall"
+)
+
+// ForkExec forks the current process and invokes Exec with the program, arguments,
+// and environment specified by name, argv, and envv. It returns the process
+// id of the forked process and an Error, if any. The fd array specifies the
+// file descriptors to be set up in the new process: fd[0] will be Unix file
+// descriptor 0 (standard input), fd[1] descriptor 1, and so on. A nil entry
+// will cause the child to have no open file descriptor with that index.
+// If dir is not empty, the child chdirs into the directory before execing the program.
+func ForkExec(name string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
+ if envv == nil {
+ envv = Environ()
+ }
+ // Create array of integer (system) fds.
+ intfd := make([]int, len(fd))
+ for i, f := range fd {
+ if f == nil {
+ intfd[i] = -1
+ } else {
+ intfd[i] = f.Fd()
+ }
+ }
+
+ p, e := syscall.ForkExec(name, argv, envv, dir, intfd)
+ if e != 0 {
+ return 0, &PathError{"fork/exec", name, Errno(e)}
+ }
+ return p, nil
+}
+
+// Exec replaces the current process with an execution of the
+// named binary, with arguments argv and environment envv.
+// If successful, Exec never returns. If it fails, it returns an Error.
+// ForkExec is almost always a better way to execute a program.
+func Exec(name string, argv []string, envv []string) Error {
+ if envv == nil {
+ envv = Environ()
+ }
+ e := syscall.Exec(name, argv, envv)
+ if e != 0 {
+ return &PathError{"exec", name, Errno(e)}
+ }
+ return nil
+}
+
+// TODO(rsc): Should os implement its own syscall.WaitStatus
+// wrapper with the methods, or is exposing the underlying one enough?
+//
+// TODO(rsc): Certainly need to have Rusage struct,
+// since syscall one might have different field types across
+// different OS.
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg struct {
+ Pid int // The process's id.
+ syscall.WaitStatus // System-dependent status info.
+ Rusage *syscall.Rusage // System-dependent resource usage info.
+}
+
+// Options for Wait.
+const (
+ WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
+ WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
+ WUNTRACED = WSTOPPED
+ WRUSAGE = 1 << 20 // Record resource usage.
+)
+
+// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
+// WCLONE, WALL, and WNOTHREAD flags, which sit in the top few bits of
+// the options
+
+// Wait waits for process pid to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+ var status syscall.WaitStatus
+ var rusage *syscall.Rusage
+ if options&WRUSAGE != 0 {
+ rusage = new(syscall.Rusage)
+ options ^= WRUSAGE
+ }
+ pid1, e := syscall.Wait4(pid, &status, options, rusage)
+ if e != 0 {
+ return nil, NewSyscallError("wait", e)
+ }
+ w = new(Waitmsg)
+ w.Pid = pid1
+ w.WaitStatus = status
+ w.Rusage = rusage
+ return w, nil
+}
+
+// Convert i to decimal string.
+func itod(i int) string {
+ if i == 0 {
+ return "0"
+ }
+
+ u := uint64(i)
+ if i < 0 {
+ u = -u
+ }
+
+ // Assemble decimal in reverse order.
+ var b [32]byte
+ bp := len(b)
+ for ; u > 0; u /= 10 {
+ bp--
+ b[bp] = byte(u%10) + '0'
+ }
+
+ if i < 0 {
+ bp--
+ b[bp] = '-'
+ }
+
+ return string(b[bp:])
+}
+
+func (w Waitmsg) String() string {
+ // TODO(austin) Use signal names when possible?
+ res := ""
+ switch {
+ case w.Exited():
+ res = "exit status " + itod(w.ExitStatus())
+ case w.Signaled():
+ res = "signal " + itod(w.Signal())
+ case w.Stopped():
+ res = "stop signal " + itod(w.StopSignal())
+ if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
+ res += " (trap " + itod(w.TrapCause()) + ")"
+ }
+ case w.Continued():
+ res = "continued"
+ }
+ if w.CoreDump() {
+ res += " (core dumped)"
+ }
+ return res
+}
diff -r 09ab865d875c src/pkg/os/file.go
--- a/src/pkg/os/file.go Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/file.go Sat Jan 15 13:00:13 2011 +0200
@@ -83,10 +83,10 @@
if n < 0 {
n = 0
}
- if n == 0 && e == 0 {
+ if n == 0 && !iserror(e) {
return 0, EOF
}
- if e != 0 {
+ if iserror(e) {
err = &PathError{"read", file.name, Errno(e)}
}
return n, err
@@ -102,10 +102,10 @@
}
for len(b) > 0 {
m, e := syscall.Pread(file.fd, b, off)
- if m == 0 && e == 0 {
+ if m == 0 && !iserror(e) {
return n, EOF
}
- if e != 0 {
+ if iserror(e) {
err = &PathError{"read", file.name, Errno(e)}
break
}
@@ -127,15 +127,10 @@
if n < 0 {
n = 0
}
- if e == syscall.EPIPE {
- file.nepipe++
- if file.nepipe >= 10 {
- Exit(syscall.EPIPE)
- }
- } else {
- file.nepipe = 0
- }
- if e != 0 {
+
+ epipecheck(file, e)
+
+ if iserror(e) {
err = &PathError{"write", file.name, Errno(e)}
}
return n, err
@@ -150,7 +145,7 @@
}
for len(b) > 0 {
m, e := syscall.Pwrite(file.fd, b, off)
- if e != 0 {
+ if iserror(e) {
err = &PathError{"write", file.name, Errno(e)}
break
}
@@ -167,10 +162,10 @@
// It returns the new offset and an Error, if any.
func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
r, e := syscall.Seek(file.fd, offset, whence)
- if e == 0 && file.dirinfo != nil && r != 0 {
+ if !iserror(e) && file.dirinfo != nil && r != 0 {
e = syscall.EISDIR
}
- if e != 0 {
+ if iserror(e) {
return 0, &PathError{"seek", file.name, Errno(e)}
}
return r, nil
@@ -187,71 +182,19 @@
return file.Write(b)
}
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an Error, if any.
-func Pipe() (r *File, w *File, err Error) {
- var p [2]int
-
- // See ../syscall/exec.go for description of lock.
- syscall.ForkLock.RLock()
- e := syscall.Pipe(p[0:])
- if e != 0 {
- syscall.ForkLock.RUnlock()
- return nil, nil, NewSyscallError("pipe", e)
- }
- syscall.CloseOnExec(p[0])
- syscall.CloseOnExec(p[1])
- syscall.ForkLock.RUnlock()
-
- return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
-}
-
// Mkdir creates a new directory with the specified name and permission bits.
// It returns an error, if any.
func Mkdir(name string, perm uint32) Error {
e := syscall.Mkdir(name, perm)
- if e != 0 {
+ if iserror(e) {
return &PathError{"mkdir", name, Errno(e)}
}
return nil
}
-// Stat returns a FileInfo structure describing the named file and an error, if any.
-// If name names a valid symbolic link, the returned FileInfo describes
-// the file pointed at by the link and has fi.FollowedSymlink set to true.
-// If name names an invalid symbolic link, the returned FileInfo describes
-// the link itself and has fi.FollowedSymlink set to false.
-func Stat(name string) (fi *FileInfo, err Error) {
- var lstat, stat syscall.Stat_t
- e := syscall.Lstat(name, &lstat)
- if e != 0 {
- return nil, &PathError{"stat", name, Errno(e)}
- }
- statp := &lstat
- if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
- e := syscall.Stat(name, &stat)
- if e == 0 {
- statp = &stat
- }
- }
- return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
-}
-
-// Lstat returns the FileInfo structure describing the named file and an
-// error, if any. If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link. Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
- var stat syscall.Stat_t
- e := syscall.Lstat(name, &stat)
- if e != 0 {
- return nil, &PathError{"lstat", name, Errno(e)}
- }
- return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
-}
-
// Chdir changes the current working directory to the named directory.
func Chdir(dir string) Error {
- if e := syscall.Chdir(dir); e != 0 {
+ if e := syscall.Chdir(dir); iserror(e) {
return &PathError{"chdir", dir, Errno(e)}
}
return nil
@@ -260,179 +203,8 @@
// Chdir changes the current working directory to the file,
// which must be a directory.
func (f *File) Chdir() Error {
- if e := syscall.Fchdir(f.fd); e != 0 {
+ if e := syscall.Fchdir(f.fd); iserror(e) {
return &PathError{"chdir", f.name, Errno(e)}
}
return nil
}
-
-// Remove removes the named file or directory.
-func Remove(name string) Error {
- // System call interface forces us to know
- // whether name is a file or directory.
- // Try both: it is cheaper on average than
- // doing a Stat plus the right one.
- e := syscall.Unlink(name)
- if e == 0 {
- return nil
- }
- e1 := syscall.Rmdir(name)
- if e1 == 0 {
- return nil
- }
-
- // Both failed: figure out which error to return.
- // OS X and Linux differ on whether unlink(dir)
- // returns EISDIR, so can't use that. However,
- // both agree that rmdir(file) returns ENOTDIR,
- // so we can use that to decide which error is real.
- // Rmdir might also return ENOTDIR if given a bad
- // file path, like /etc/passwd/foo, but in that case,
- // both errors will be ENOTDIR, so it's okay to
- // use the error from unlink.
- // For windows syscall.ENOTDIR is set
- // to syscall.ERROR_DIRECTORY, hopefully it should
- // do the trick.
- if e1 != syscall.ENOTDIR {
- e = e1
- }
- return &PathError{"remove", name, Errno(e)}
-}
-
-// LinkError records an error during a link or symlink or rename
-// system call and the paths that caused it.
-type LinkError struct {
- Op string
- Old string
- New string
- Error Error
-}
-
-func (e *LinkError) String() string {
- return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
-}
-
-// Link creates a hard link.
-func Link(oldname, newname string) Error {
- e := syscall.Link(oldname, newname)
- if e != 0 {
- return &LinkError{"link", oldname, newname, Errno(e)}
- }
- return nil
-}
-
-// Symlink creates a symbolic link.
-func Symlink(oldname, newname string) Error {
- e := syscall.Symlink(oldname, newname)
- if e != 0 {
- return &LinkError{"symlink", oldname, newname, Errno(e)}
- }
- return nil
-}
-
-// Readlink reads the contents of a symbolic link: the destination of
-// the link. It returns the contents and an Error, if any.
-func Readlink(name string) (string, Error) {
- for len := 128; ; len *= 2 {
- b := make([]byte, len)
- n, e := syscall.Readlink(name, b)
- if e != 0 {
- return "", &PathError{"readlink", name, Errno(e)}
- }
- if n < len {
- return string(b[0:n]), nil
- }
- }
- // Silence 6g.
- return "", nil
-}
-
-// Rename renames a file.
-func Rename(oldname, newname string) Error {
- e := syscall.Rename(oldname, newname)
- if e != 0 {
- return &LinkError{"rename", oldname, newname, Errno(e)}
- }
- return nil
-}
-
-// Chmod changes the mode of the named file to mode.
-// If the file is a symbolic link, it changes the mode of the link's target.
-func Chmod(name string, mode uint32) Error {
- if e := syscall.Chmod(name, mode); e != 0 {
- return &PathError{"chmod", name, Errno(e)}
- }
- return nil
-}
-
-// Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) Error {
- if e := syscall.Fchmod(f.fd, mode); e != 0 {
- return &PathError{"chmod", f.name, Errno(e)}
- }
- return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link's target.
-func Chown(name string, uid, gid int) Error {
- if e := syscall.Chown(name, uid, gid); e != 0 {
- return &PathError{"chown", name, Errno(e)}
- }
- return nil
-}
-
-// Lchown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link itself.
-func Lchown(name string, uid, gid int) Error {
- if e := syscall.Lchown(name, uid, gid); e != 0 {
- return &PathError{"lchown", name, Errno(e)}
- }
- return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-func (f *File) Chown(uid, gid int) Error {
- if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
- return &PathError{"chown", f.name, Errno(e)}
- }
- return nil
-}
-
-// Truncate changes the size of the file.
-// It does not change the I/O offset.
-func (f *File) Truncate(size int64) Error {
- if e := syscall.Ftruncate(f.fd, size); e != 0 {
- return &PathError{"truncate", f.name, Errno(e)}
- }
- return nil
-}
-
-// Sync commits the current contents of the file to stable storage.
-// Typically, this means flushing the file system's in-memory copy
-// of recently written data to disk.
-func (file *File) Sync() (err Error) {
- if file == nil {
- return EINVAL
- }
- if e := syscall.Fsync(file.fd); e != 0 {
- return NewSyscallError("fsync", e)
- }
- return nil
-}
-
-// Chtimes changes the access and modification times of the named
-// file, similar to the Unix utime() or utimes() functions.
-//
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
- var utimes [2]syscall.Timeval
- utimes[0] = syscall.NsecToTimeval(atime_ns)
- utimes[1] = syscall.NsecToTimeval(mtime_ns)
- if e := syscall.Utimes(name, utimes[0:]); e != 0 {
- return &PathError{"chtimes", name, Errno(e)}
- }
- return nil
-}
diff -r 09ab865d875c src/pkg/os/file_plan9.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/file_plan9.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,204 @@
+// Copyright 20010 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.
+
+package os
+
+import (
+ "runtime"
+ "syscall"
+)
+
+func epipecheck(file *File, e syscall.Error) {
+}
+
+
+// DevNull is the name of the operating system's ``null device.''
+// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
+const DevNull = "#c/null"
+
+// Open opens the named file with specified flag (O_RDONLY etc.) and perm.
+// If successful, methods on the returned File can be used for I/O.
+// It returns the File and an Error, if any.
+func Open(name string, flag int, perm uint32) (file *File, err Error) {
+ var fd int
+ var e syscall.Error
+
+ if flag&O_CREAT == O_CREAT {
+ fd, e = syscall.Create(name, flag & ^O_CREAT, perm)
+ } else {
+ fd, e = syscall.Open(name, flag)
+ }
+
+ if e != nil {
+ return nil, &PathError{"open", name, e}
+ }
+
+ return NewFile(fd, name), nil
+}
+
+// Close closes the File, rendering it unusable for I/O.
+// It returns an Error, if any.
+func (file *File) Close() Error {
+ if file == nil || file.fd < 0 {
+ return syscall.Ebadfd
+ }
+ var err Error
+ if e := syscall.Close(file.fd); e != nil {
+ err = &PathError{"close", file.name, e}
+ }
+ file.fd = -1 // so it can't be closed again
+
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(file, nil)
+ return err
+}
+
+// Stat returns the FileInfo structure describing file.
+// It returns the FileInfo and an error, if any.
+func (file *File) Stat() (fi *FileInfo, err Error) {
+ return dirstat(file)
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+ d := nullDir
+
+ d.Length = uint64(size)
+
+ if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+ return &PathError{"truncate", f.name, e}
+ }
+ return nil
+}
+
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (f *File) Sync() (err Error) {
+ if f == nil {
+ return EINVAL
+ }
+
+ d := nullDir
+
+ if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+ return NewSyscallError("fsync", e)
+ }
+
+ return nil
+}
+
+// Truncate changes the size of the named file.
+// If the file is a symbolic link, it changes the size of the link's target.
+func Truncate(name string, size int64) Error {
+ d := nullDir
+
+ d.Length = uint64(size)
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"truncate", name, e}
+ }
+ return nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+ if e := syscall.Remove(name); iserror(e) {
+ return &PathError{"remove", name, e}
+ }
+ return nil
+}
+
+func Rename(oldname, newname string) Error {
+ d := nullDir
+
+ d.Name = newname
+
+ if e := syscall.Wstat(oldname, pdir(nil, &d)); iserror(e) {
+ return &PathError{"rename", oldname, e}
+ }
+ return nil
+}
+
+func Chmod(name string, mode uint32) Error {
+ d := nullDir
+
+ d.Mode = mode & 0777
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chmod", name, e}
+ }
+ return nil
+}
+
+func ChownPlan9(name, uid, gid string) Error {
+ d := nullDir
+
+ d.Uid = uid
+ d.Gid = gid
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chown_plan9", name, e}
+ }
+ return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
+ d := nullDir
+
+ d.Atime = uint32(atime_ns / 1e9)
+ d.Mtime = uint32(mtime_ns / 1e9)
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chtimes", name, e}
+ }
+ return nil
+}
+
+func Pipe() (r *File, w *File, err Error) {
+ var p [2]int
+
+ if e := syscall.Pipe(p[0:]); iserror(e) {
+ return nil, nil, NewSyscallError("pipe", e)
+ }
+
+ return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+
+// not supported on Plan 9
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+ return EPLAN9
+}
+
+func Symlink(oldname, newname string) Error {
+ return EPLAN9
+}
+
+func Readlink(name string) (string, Error) {
+ return "", EPLAN9
+}
+
+func Chown(name string, uid, gid int) Error {
+ return EPLAN9
+}
+
+func Lchown(name string, uid, gid int) Error {
+ return EPLAN9
+}
+
+// Chown changes the numeric uid and gid of the named file.
+func (f *File) Chown(uid, gid int) Error {
+ return EPLAN9
+}
diff -r 09ab865d875c src/pkg/os/file_posix.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/file_posix.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,246 @@
+// Copyright 2009 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.
+
+// The os package provides a platform-independent interface to operating
+// system functionality. The design is Unix-like.
+package os
+
+import (
+ "syscall"
+)
+
+func epipecheck(file *File, e int) {
+ if e == syscall.EPIPE {
+ file.nepipe++
+ if file.nepipe >= 10 {
+ Exit(syscall.EPIPE)
+ }
+ } else {
+ file.nepipe = 0
+ }
+}
+
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an Error, if any.
+func Pipe() (r *File, w *File, err Error) {
+ var p [2]int
+
+ // See ../syscall/exec.go for description of lock.
+ syscall.ForkLock.RLock()
+ e := syscall.Pipe(p[0:])
+ if iserror(e) {
+ syscall.ForkLock.RUnlock()
+ return nil, nil, NewSyscallError("pipe", e)
+ }
+ syscall.CloseOnExec(p[0])
+ syscall.CloseOnExec(p[1])
+ syscall.ForkLock.RUnlock()
+
+ return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+// If name names a valid symbolic link, the returned FileInfo describes
+// the file pointed at by the link and has fi.FollowedSymlink set to true.
+// If name names an invalid symbolic link, the returned FileInfo describes
+// the link itself and has fi.FollowedSymlink set to false.
+func Stat(name string) (fi *FileInfo, err Error) {
+ var lstat, stat syscall.Stat_t
+ e := syscall.Lstat(name, &lstat)
+ if iserror(e) {
+ return nil, &PathError{"stat", name, Errno(e)}
+ }
+ statp := &lstat
+ if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
+ e := syscall.Stat(name, &stat)
+ if !iserror(e) {
+ statp = &stat
+ }
+ }
+ return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any. If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link. Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+ var stat syscall.Stat_t
+ e := syscall.Lstat(name, &stat)
+ if iserror(e) {
+ return nil, &PathError{"lstat", name, Errno(e)}
+ }
+ return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+ // System call interface forces us to know
+ // whether name is a file or directory.
+ // Try both: it is cheaper on average than
+ // doing a Stat plus the right one.
+ e := syscall.Unlink(name)
+ if !iserror(e) {
+ return nil
+ }
+ e1 := syscall.Rmdir(name)
+ if !iserror(e1) {
+ return nil
+ }
+
+ // Both failed: figure out which error to return.
+ // OS X and Linux differ on whether unlink(dir)
+ // returns EISDIR, so can't use that. However,
+ // both agree that rmdir(file) returns ENOTDIR,
+ // so we can use that to decide which error is real.
+ // Rmdir might also return ENOTDIR if given a bad
+ // file path, like /etc/passwd/foo, but in that case,
+ // both errors will be ENOTDIR, so it's okay to
+ // use the error from unlink.
+ // For windows syscall.ENOTDIR is set
+ // to syscall.ERROR_DIRECTORY, hopefully it should
+ // do the trick.
+ if e1 != syscall.ENOTDIR {
+ e = e1
+ }
+ return &PathError{"remove", name, Errno(e)}
+}
+
+// LinkError records an error during a link or symlink or rename
+// system call and the paths that caused it.
+type LinkError struct {
+ Op string
+ Old string
+ New string
+ Error Error
+}
+
+func (e *LinkError) String() string {
+ return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
+}
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+ e := syscall.Link(oldname, newname)
+ if iserror(e) {
+ return &LinkError{"link", oldname, newname, Errno(e)}
+ }
+ return nil
+}
+
+// Symlink creates a symbolic link.
+func Symlink(oldname, newname string) Error {
+ e := syscall.Symlink(oldname, newname)
+ if iserror(e) {
+ return &LinkError{"symlink", oldname, newname, Errno(e)}
+ }
+ return nil
+}
+
+// Readlink reads the contents of a symbolic link: the destination of
+// the link. It returns the contents and an Error, if any.
+func Readlink(name string) (string, Error) {
+ for len := 128; ; len *= 2 {
+ b := make([]byte, len)
+ n, e := syscall.Readlink(name, b)
+ if iserror(e) {
+ return "", &PathError{"readlink", name, Errno(e)}
+ }
+ if n < len {
+ return string(b[0:n]), nil
+ }
+ }
+ // Silence 6g.
+ return "", nil
+}
+
+// Rename renames a file.
+func Rename(oldname, newname string) Error {
+ e := syscall.Rename(oldname, newname)
+ if iserror(e) {
+ return &LinkError{"rename", oldname, newname, Errno(e)}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
+func Chmod(name string, mode uint32) Error {
+ if e := syscall.Chmod(name, mode); iserror(e) {
+ return &PathError{"chmod", name, Errno(e)}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the file to mode.
+func (f *File) Chmod(mode uint32) Error {
+ if e := syscall.Fchmod(f.fd, mode); iserror(e) {
+ return &PathError{"chmod", f.name, Errno(e)}
+ }
+ return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+func Chown(name string, uid, gid int) Error {
+ if e := syscall.Chown(name, uid, gid); iserror(e) {
+ return &PathError{"chown", name, Errno(e)}
+ }
+ return nil
+}
+
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+func Lchown(name string, uid, gid int) Error {
+ if e := syscall.Lchown(name, uid, gid); iserror(e) {
+ return &PathError{"lchown", name, Errno(e)}
+ }
+ return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+func (f *File) Chown(uid, gid int) Error {
+ if e := syscall.Fchown(f.fd, uid, gid); iserror(e) {
+ return &PathError{"chown", f.name, Errno(e)}
+ }
+ return nil
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+ if e := syscall.Ftruncate(f.fd, size); iserror(e) {
+ return &PathError{"truncate", f.name, Errno(e)}
+ }
+ return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (file *File) Sync() (err Error) {
+ if file == nil {
+ return EINVAL
+ }
+ if e := syscall.Fsync(file.fd); iserror(e) {
+ return NewSyscallError("fsync", e)
+ }
+ return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
+ var utimes [2]syscall.Timeval
+ utimes[0] = syscall.NsecToTimeval(atime_ns)
+ utimes[1] = syscall.NsecToTimeval(mtime_ns)
+ if e := syscall.Utimes(name, utimes[0:]); iserror(e) {
+ return &PathError{"chtimes", name, Errno(e)}
+ }
+ return nil
+}
diff -r 09ab865d875c src/pkg/os/proc.go
--- a/src/pkg/os/proc.go Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/proc.go Sat Jan 15 13:00:13 2011 +0200
@@ -26,8 +26,8 @@
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
func Getgroups() ([]int, Error) {
- gids, errno := syscall.Getgroups()
- return gids, NewSyscallError("getgroups", errno)
+ gids, e := syscall.Getgroups()
+ return gids, NewSyscallError("getgroups", e)
}
// Exit causes the current program to exit with the given status code.
diff -r 09ab865d875c src/pkg/os/stat_plan9.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/stat_plan9.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,81 @@
+// Copyright 2010 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.
+
+package os
+
+import "syscall"
+
+func fileInfoFromStat(fi *FileInfo, d *Dir) *FileInfo {
+ fi.Dev = uint64(d.Qid.Vers) | uint64(d.Qid.Type<<32)
+ fi.Ino = d.Qid.Path
+
+ fi.Mode = uint32(d.Mode) & 0777
+ if (d.Mode & syscall.DMDIR) == syscall.DMDIR {
+ fi.Mode |= syscall.S_IFDIR
+ } else {
+ fi.Mode |= syscall.S_IFREG
+ }
+
+ fi.Size = int64(d.Length)
+ fi.Atime_ns = 1e9 * int64(d.Atime)
+ fi.Mtime_ns = 1e9 * int64(d.Mtime)
+ fi.Name = d.Name
+ fi.FollowedSymlink = false
+ return fi
+}
+
+// arg is an open *File or a path string.
+func dirstat(arg interface{}) (fi *FileInfo, err Error) {
+ var name string
+ nd := syscall.STATFIXLEN + 16*4
+
+ for i := 0; i < 2; i++ { /* should work by the second try */
+ buf := make([]byte, nd)
+
+ var n int
+ var e syscall.Error
+
+ switch syscall_arg := arg.(type) {
+ case *File:
+ name = syscall_arg.name
+ n, e = syscall.Fstat(syscall_arg.fd, buf)
+ case string:
+ name = syscall_arg
+ n, e = syscall.Stat(name, buf)
+ }
+
+ if e != nil {
+ return nil, &PathError{"stat", name, e}
+ }
+
+ if n < syscall.STATFIXLEN {
+ return nil, &PathError{"stat", name, syscall.Etoosmall}
+ }
+
+ ntmp, _ := gbit16(buf)
+ nd = int(ntmp)
+
+ if nd <= n {
+ d, e := UnmarshalDir(buf[:n])
+
+ if e != nil {
+ return nil, &PathError{"stat", name, e}
+ }
+
+ return fileInfoFromStat(new(FileInfo), d), nil
+ }
+ }
+
+ return nil, &PathError{"stat", name, syscall.Ebadstat}
+}
+
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+func Stat(name string) (fi *FileInfo, err Error) {
+ return dirstat(name)
+}
+
+func Lstat(name string) (fi *FileInfo, err Error) {
+ return dirstat(name)
+}
diff -r 09ab865d875c src/pkg/os/sys_plan9.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/sys_plan9.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,27 @@
+// Copyright 2009 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-specific
+
+package os
+
+
+func Hostname() (name string, err Error) {
+ f, err := Open("#e/sysname", O_RDONLY, 0)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ var buf [512]byte // Enough for a DNS name.
+ n, err := f.Read(buf[0:])
+ if err != nil {
+ return "", err
+ }
+
+ if n > 0 && buf[n-1] == '\n' {
+ n--
+ }
+ return string(buf[0:n]), nil
+}
diff -r 09ab865d875c src/pkg/os/time.go
--- a/src/pkg/os/time.go Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/os/time.go Sat Jan 15 13:00:13 2011 +0200
@@ -13,8 +13,8 @@
// time is the Unix epoch.
func Time() (sec int64, nsec int64, err Error) {
var tv syscall.Timeval
- if errno := syscall.Gettimeofday(&tv); errno != 0 {
- return 0, 0, NewSyscallError("gettimeofday", errno)
+ if e := syscall.Gettimeofday(&tv); iserror(e) {
+ return 0, 0, NewSyscallError("gettimeofday", e)
}
return int64(tv.Sec), int64(tv.Usec) * 1000, err
}
diff -r 09ab865d875c src/pkg/runtime/plan9/386/rt0.s
--- a/src/pkg/runtime/plan9/386/rt0.s Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/runtime/plan9/386/rt0.s Sat Jan 15 13:00:13 2011 +0200
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
TEXT _rt0_386_plan9(SB),7, $0
- MOVL AX, _tos(SB)
+ MOVL AX, syscall路_tos(SB)
// move arguments down to make room for
// m and g at top of stack, right before Tos.
@@ -29,4 +29,4 @@
DATA runtime路isplan9(SB)/4, $1
GLOBL runtime路isplan9(SB), $4
-GLOBL _tos(SB), $4
+GLOBL syscall路_tos(SB), $4
diff -r 09ab865d875c src/pkg/syscall/Makefile
--- a/src/pkg/syscall/Makefile Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/syscall/Makefile Sat Jan 15 13:00:13 2011 +0200
@@ -32,6 +32,8 @@
GOFILES_windows=\
exec_windows.go
+
+GOFILES_plan9=
OFILES=\
asm_$(GOOS)_$(GOARCH).$O\
diff -r 09ab865d875c src/pkg/syscall/asm_plan9_386.s
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/asm_plan9_386.s Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,176 @@
+// Copyright 2009 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.
+
+//
+// System call support for 386, Plan 9
+//
+
+// func Syscall(trap int32, a1, a2, a3 int32) (r1, r2, err uintptr);
+// func SyscallErrstr(trap uintptr, a1, a2, a3 uintptr) (r uintptr, err string);
+// func Syscall6(trap int32, a1, a2, a3, a4, a5, a6 int32) (r1, r2, err uintptr);
+// func SyscallErrstr6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r uintptr, err string);
+// Trap # in AX, args on stack above caller pc.
+
+TEXT 路Syscall(SB),7,$0
+ CALL runtime路entersyscall(SB)
+ MOVL 4(SP), AX // syscall entry
+ // slide args down on top of system call number
+ LEAL 8(SP), SI
+ LEAL 4(SP), DI
+ CLD
+ MOVSL
+ MOVSL
+ MOVSL
+ INT $64
+ MOVL AX, r1+20(SP)
+ MOVL $0, r2+24(SP)
+ MOVL $0, err+28(SP)
+ CALL runtime路exitsyscall(SB)
+ RET
+
+
+TEXT 路Syscall6(SB),7,$0
+ CALL runtime路entersyscall(SB)
+ MOVL 4(SP), AX // syscall entry
+ // slide args down on top of system call number
+ LEAL 8(SP), SI
+ LEAL 4(SP), DI
+ CLD
+ MOVSL
+ MOVSL
+ MOVSL
+ MOVSL
+ MOVSL
+ MOVSL
+ INT $64
+ MOVL AX, r1+32(SP)
+ MOVL $0, r2+36(SP)
+ MOVL $0, err+40(SP)
+ CALL runtime路exitsyscall(SB)
+ RET
+
+TEXT 路SyscallErrstr(SB),7,$0
+ CALL runtime路entersyscall(SB)
+ MOVL 4(SP), AX // syscall entry
+ // slide args down on top of system call number
+ LEAL 8(SP), SI
+ LEAL 4(SP), DI
+ CLD
+ MOVSL
+ MOVSL
+ MOVSL
+ INT $64
+ MOVL AX, r+20(SP)
+ CMPL AX, $-1
+ JNE ok3
+
+ SUBL $8, SP
+ CALL syscall路errstr(SB)
+ MOVL SP, SI
+ ADDL $8, SP
+ JMP copyresult3
+
+ok3:
+ LEAL runtime路emptystring(SB), SI
+
+copyresult3:
+ LEAL err+24(SP), DI
+
+ CLD
+ MOVSL
+ MOVSL
+
+ CALL runtime路exitsyscall(SB)
+ RET
+
+
+TEXT 路SyscallErrstr6(SB),7,$0
+ CALL runtime路entersyscall(SB)
+ MOVL 4(SP), AX // syscall entry
+ // slide args down on top of system call number
+ LEAL 8(SP), SI
+ LEAL 4(SP), DI
+ CLD
+ MOVSL
+ MOVSL
+ MOVSL
+ MOVSL
+ MOVSL
+ MOVSL
+ INT $64
+ MOVL AX, r+32(SP)
+ CMPL AX, $-1
+ JNE ok4
+
+ SUBL $8, SP
+ CALL syscall路errstr(SB)
+ MOVL SP, SI
+ ADDL $8, SP
+ JMP copyresult4
+
+ok4:
+ LEAL runtime路emptystring(SB), SI
+
+copyresult4:
+ LEAL err+36(SP), DI
+
+ CLD
+ MOVSL
+ MOVSL
+
+ CALL runtime路exitsyscall(SB)
+ RET
+
+
+TEXT 路RawSyscall(SB),7,$0
+ MOVL 4(SP), AX // syscall entry
+ // slide args down on top of system call number
+ LEAL 8(SP), SI
+ LEAL 4(SP), DI
+ CLD
+ MOVSL
+ MOVSL
+ MOVSL
+ INT $64
+ MOVL AX, r1+20(SP)
+ MOVL $0, r2+24(SP)
+ MOVL $0, err+28(SP)
+ RET
+
+
+#define SYS_SEEK 39 /* from zsysnum_plan9_386.go */
+
+//func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
+TEXT 路seek(SB),7,$0
+ CALL runtime路entersyscall(SB)
+
+ LEAL newoffset+24(SP), AX
+ MOVL AX, placeholder+4(SP)
+
+ MOVL $SYS_SEEK, AX // syscall entry
+ INT $64
+
+ CMPL AX, $-1
+ JNE ok6
+ MOVL AX, 24(SP) // newoffset low
+ MOVL AX, 28(SP) // newoffset high
+
+ SUBL $8, SP
+ CALL syscall路errstr(SB)
+ MOVL SP, SI
+ ADDL $8, SP
+ JMP copyresult6
+
+ok6:
+ LEAL runtime路emptystring(SB), SI
+
+copyresult6:
+ LEAL err+32(SP), DI
+
+ CLD
+ MOVSL
+ MOVSL
+
+ CALL runtime路exitsyscall(SB)
+ RET
diff -r 09ab865d875c src/pkg/syscall/mkall.sh
--- a/src/pkg/syscall/mkall.sh Fri Jan 14 23:00:02 2011 -0800
+++ b/src/pkg/syscall/mkall.sh Sat Jan 15 13:00:13 2011 +0200
@@ -154,6 +154,12 @@
mktypes=
mkerrors="./mkerrors_windows.sh -f -m32"
;;
+plan9_386)
+ mkerrors=
+ mksyscall="./mksyscall_plan9.sh -l32"
+ mksysnum="./mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h"
+ mktypes="godefs -gsyscall -f -m32"
+ ;;
*)
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
exit 1
diff -r 09ab865d875c src/pkg/syscall/mksyscall_plan9.awk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/mksyscall_plan9.awk Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,205 @@
+function parse_line(line) {
+
+ inargs_begin = match(line, /\(([^()]*)\)/)
+
+ if(inargs_begin == 0)
+ return 0
+
+ fname = substr(line, 1, inargs_begin-1)
+ sub(/func[ \t]+/, "", fname)
+
+ inargs_tmp = substr(line, inargs_begin+1, RLENGTH-2)
+ outargs_tmp = substr(line, inargs_begin+RLENGTH, length(line))
+
+ outargs_begin = match(outargs_tmp, /\(([^()]*)\)/)
+ if(outargs_begin == 0)
+ outargs_tmp = ""
+ else
+ outargs_tmp = substr(outargs_tmp, outargs_begin+1, RLENGTH-2)
+
+ parse_arg_types(inargs_tmp, inargs, inarg_types)
+ parse_arg_types(outargs_tmp, outargs, outarg_types)
+
+ return 1
+}
+
+function parse_arg_types(args_str, args, arg_types) {
+ arg_index = 1
+
+ delete args_tmp
+ delete args
+ delete arg_types
+
+ split(args_str, args_tmp, /[ \t]*,[ \t]*/)
+ for(i=1; i <= length(args_tmp); i++) {
+ argname = args_tmp[i]
+
+ type_begin = match(args_tmp[i], /[ \t]+/)
+ if (type_begin == 0) {
+ arg_types[argname] = ""
+ } else {
+ argname = substr(args_tmp[i], 1, type_begin-1)
+ type = substr(args_tmp[i], type_begin+RLENGTH, length(args_tmp[i]))
+ sub(/^[ \t]+/, "", type)
+ sub(/[ \t]+$/, "", type)
+ arg_types[argname] = type
+
+ for (j = arg_index; j > 0; j--) {
+ if (arg_types[args[j]] != "")
+ break
+
+ arg_types[args[j]] = arg_types[argname]
+ }
+ }
+
+ sub(/^[ \t]+/, "", argname)
+ sub(/[ \t]+$/, "", argname)
+
+ if (argname == "")
+ continue
+
+ args[arg_index++] = argname
+ }
+}
+
+BEGIN {
+ printf("// %s\n", cmdline)
+ print "// MACHINE GENERATED BY THE COMMAND ABOVE DO NOT EDIT\n"
+ print "package syscall\n"
+ print "import \"unsafe\"\n"
+}
+
+
+/^\/\/sys[ \t]+/ {
+
+ print "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT\n\n"
+
+ sub(/^\/\/sys[ \t]+/, "func ", $0)
+ printf("%s {\n", $0)
+
+ if (!parse_line($0))
+ next
+
+ # Prepare arguments to Syscall.
+ delete syscall_args
+ syscall_arg_index = 1
+ ptrindex = 0
+
+ for (i=1; i <= length(inargs); i++) {
+ name = inargs[i]
+ type = inarg_types[name]
+
+ if (type ~ /^\*/) {
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(unsafe.Pointer(%s))", name)
+ } else if (type == "string") {
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(unsafe.Pointer(StringBytePtr(%s)))", name)
+ } else if (type ~ /\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass nil in that case.
+
+ printf("\tvar _p%d unsafe.Pointer\n", ptrindex)
+ printf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}\n", name, ptrindex, name)
+
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(_p%d)", ptrindex)
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(len(%s))", name)
+ ptrindex++
+ } else if (type == "int64" && _32bit != "") {
+ if (_32bit == "big-endian") {
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(%s>>32)", name)
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(%s)", name)
+ } else {
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(%s)", name)
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(%s>>32)", name)
+ }
+ } else {
+ syscall_args[syscall_arg_index++] = sprintf("uintptr(%s)", name)
+ }
+ }
+
+ # Determine which form to use; pad args with zeros.
+ asm = "Syscall"
+
+ errstr = 0
+ if ("err" in outarg_types && outarg_types["err"] == "Error") {
+ asm = asm "Errstr"
+ errstr = 1
+ }
+
+ if (syscall_arg_index <= 4) {
+ for (; syscall_arg_index <= 3; syscall_arg_index++)
+ syscall_args[syscall_arg_index] = "0"
+ } else if (syscall_arg_index <= 7) {
+ asm = asm "6"
+ for (; syscall_arg_index <= 6; syscall_arg_index++)
+ syscall_args[syscall_arg_index] = "0"
+ } else {
+ print "too many arguments to system call\n"
+ exit 1
+ }
+
+ syscall_ret = ""
+
+ if (length(outargs) > 0) {
+ if (errstr) {
+ syscall_ret = syscall_ret "r0,e"
+ } else {
+# if(outarg_types[outargs[1]] == "int64" && _32bit != "") {
+# # 64-bit number in r1:r0 or r0:r1.
+# syscall_ret = "r0,r1,_"
+# } else {
+ syscall_ret = "r0,_,_"
+# }
+ }
+ }
+
+ sysname = "SYS_" toupper(fname)
+
+ # Actuall call.
+ if (syscall_ret == "")
+ printf("\t%s(%s", asm, sysname)
+ else
+ printf("\t%s := %s(%s", syscall_ret, asm, sysname)
+
+ for (i=1; i <= length(syscall_args); i++) {
+ printf(", %s", syscall_args[i])
+ }
+
+ print ")\n"
+
+ # set Return values.
+ for (i=1; i <= length(outargs); i++) {
+ name = outargs[i]
+ type = outarg_types[name]
+
+ # Should be the last output variable.
+ if (name == "err" && type == "Error")
+ break
+
+ if(type == "int64" && _32bit != "") {
+ print "system call returning 64 bit value\n"
+ exit 1
+# # 64-bit number in r1:r0 or r0:r1.
+# if(_32bit == "big-endian") {
+# printf("\t%s = int64(r0)<<32 | int64(r1)", name);
+# } else {
+# printf("\t%s = int64(r1)<<32 | int64(r0)", name);
+# }
+# break
+ } else if (type == "bool") {
+ printf("\t%s = r%d != 0\n", name, i-1)
+ } else {
+ printf("\t%s = %s(r%d)\n", name, type, i-1)
+ }
+ }
+
+ if (errstr) {
+ print "\terr = nil"
+ print "\tif int(r0) == -1 {"
+ print "\t\terr = NewError(e)"
+ print "\t}"
+ }
+
+ print "\treturn\n}"
+
+}
diff -r 09ab865d875c src/pkg/syscall/mksyscall_plan9.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/mksyscall_plan9.sh Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Copyright 2010 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.
+
+# This program reads a file containing function prototypes
+# (like syscall_plan9.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * If the return parameter is an error string,
+# as returned by errstr. It must be named err, of type Error
+# and be the last return parameter.
+
+cmdline="mksyscall_plan9.sh $@"
+_32bit=""
+
+if [ "$1" == '-b32' ]; then
+ _32bit="big-endian"
+elif [ "$1" == '-l32' ]; then
+ _32bit="little-endian"
+fi
+
+awk -v _32bit="${_32bit}" -v cmdline="${cmdline}" -f mksyscall_plan9.awk "$2"
+
+#if($ARGV[0] =~ /^-/) {
+# print STDERR "usage: mksyscall.sh [-b32 | -l32] [file ...]\n";
+# exit 1;
+#}
+
+
diff -r 09ab865d875c src/pkg/syscall/mksysnum_plan9.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/mksysnum_plan9.sh Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Copyright 2009 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.# Copyright 2009 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.
+
+COMMAND="mksysnum_plan9.sh $@"
+
+cat <<EOF
+// $COMMAND
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const(
+EOF
+
+cat $1 | sed -r 's/^#define[ \t]([A-Z0-9_]+)[ \t]+([0-9]+)/\tSYS_\1=\2/g' | grep -v SYS__
+
+cat <<EOF
+)
+EOF
diff -r 09ab865d875c src/pkg/syscall/syscall_plan9.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/syscall_plan9.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,368 @@
+// Copyright 2010 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
+
+// shamelessly copied from os.error.
+// An Error can represent any printable error condition.
+type Error interface {
+ String() string
+}
+
+// A helper type that can be embedded or wrapped to simplify satisfying
+// Error.
+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
+)
+
+func SyscallErrstr(trap, a1, a2, a3 uintptr) (r uintptr, err string)
+func SyscallErrstr6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r uintptr, err string)
+
+// Plan 9 errors
+var (
+ Enoerror Error = NewError("no error")
+ Emount Error = NewError("inconsistent mount")
+ Eunmount Error = NewError("not mounted")
+ Eismtpt Error = NewError("is a mount point")
+ Eunion Error = NewError("not in union")
+ Emountrpc Error = NewError("mount rpc error")
+ Eshutdown Error = NewError("device shut down")
+ Enocreate Error = NewError("mounted directory forbids creation")
+ Enonexist Error = NewError("file does not exist")
+ Eexist Error = NewError("file already exists")
+ Ebadsharp Error = NewError("unknown device in # filename")
+ Enotdir Error = NewError("not a directory")
+ Eisdir Error = NewError("file is a directory")
+ Ebadchar Error = NewError("bad character in file name")
+ Efilename Error = NewError("file name syntax")
+ Eperm Error = NewError("permission denied")
+ Ebadusefd Error = NewError("inappropriate use of fd")
+ Ebadarg Error = NewError("bad arg in system call")
+ Einuse Error = NewError("device or object already in use")
+ Eio Error = NewError("i/o error")
+ Etoobig Error = NewError("read or write too large")
+ Etoosmall Error = NewError("read or write too small")
+ Enoport Error = NewError("network port not available")
+ Ehungup Error = NewError("i/o on hungup channel")
+ Ebadctl Error = NewError("bad process or channel control request")
+ Enodev Error = NewError("no free devices")
+ Eprocdied Error = NewError("process exited")
+ Enochild Error = NewError("no living children")
+ Eioload Error = NewError("i/o error in demand load")
+ Enovmem Error = NewError("virtual memory allocation failed")
+ Ebadfd Error = NewError("fd out of range or not open")
+ Enofd Error = NewError("no free file descriptors")
+ Eisstream Error = NewError("seek on a stream")
+ Ebadexec Error = NewError("exec header invalid")
+ Etimedout Error = NewError("connection timed out")
+ Econrefused Error = NewError("connection refused")
+ Econinuse Error = NewError("connection in use")
+ Eintr Error = NewError("interrupted")
+ Enomem Error = NewError("kernel allocate failed")
+ Enoswap Error = NewError("swap space full")
+ Esoverlap Error = NewError("segments overlap")
+ Emouseset Error = NewError("mouse type already set")
+ Eshort Error = NewError("i/o count too small")
+ Egreg Error = NewError("jmk added reentrancy for threads")
+ Ebadspec Error = NewError("bad attach specifier")
+ Enoreg Error = NewError("process has no saved registers")
+ Enoattach Error = NewError("mount/attach disallowed")
+ Eshortstat Error = NewError("stat buffer too small")
+ Ebadstat Error = NewError("malformed stat buffer")
+ Enegoff Error = NewError("negative i/o offset")
+ Ecmdargs Error = NewError("wrong #args in control message")
+ Ebadip Error = NewError("bad ip address syntax")
+ Edirseek Error = NewError("seek in directory")
+)
+
+var (
+ EISDIR Error = Eisdir
+ EPIPE Error = Eio
+)
+
+func atoi(buf []byte) int {
+ res := 0
+
+ for i := 0; i < len(buf); i++ {
+ res *= 10
+ res += int(buf[i] - '0')
+ }
+
+ return res
+}
+
+func findnull(s []byte) int {
+ l := 0
+ for ; (l < len(s)) && (s[l] != 0); l++ {
+ }
+
+ return l
+}
+
+
+/*
+ * Wrapped
+ */
+
+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 := str(code)
+ Exits(&msg)
+}
+
+var _tos *Tos // provided by runtime rt0.s
+func Getpid() (pid int) {
+ return int(_tos.Pid)
+}
+
+func Getppid() (ppid int) {
+ var b [12]byte
+
+ fd, e := Open("#c/ppid", O_RDONLY)
+ if e != nil {
+ return -1
+ }
+ defer Close(fd)
+
+ n, e := Pread(fd, b[:], 0)
+
+ m := 0
+ for ; m < n && b[m] == ' '; m++ {
+ }
+
+ return atoi(b[m : n-1])
+}
+
+
+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
+ }
+
+ buf[len(buf)-1] = 0
+ return string(buf[:findnull(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))
+}
+
+// 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(msg *Waitmsg) (err Error) {
+ var s [512]byte
+
+ end, err := await(s[:])
+
+ if err != nil || msg == nil {
+ return
+ }
+
+ sep := make([]int, 0, 7)
+
+ for i := 0; i < end; i++ {
+ if s[i] == ' ' {
+ sep = append(sep, i)
+ }
+ }
+ sep = append(sep, end)
+
+ msg.Pid = atoi(s[0:sep[0]])
+
+ for i := 0; i < 3; i++ {
+ msg.Time[i] = uint32(atoi(s[sep[i]+1 : sep[i+1]]))
+ }
+
+ msg.Msg = string(s[sep[3]+2 : sep[len(sep)-1]-1])
+
+ 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 Gettimeofday(tv *Timeval) (err Error) {
+ var b [8]byte
+ var nsec int64
+
+ fd, e := Open("#c/bintime", O_RDONLY)
+ if e != nil {
+ return e
+ }
+ defer Close(fd)
+
+ _, e = Pread(fd, b[:], 0)
+
+ if e != nil {
+ return e
+ }
+
+ 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])
+
+ *tv = NsecToTimeval(nsec)
+
+ return e
+}
+
+func errstr() string {
+ err_buffer := make([]byte, ERRMAX)
+
+ RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&err_buffer[0])), uintptr(len(err_buffer)), 0)
+
+ err_buffer[len(err_buffer)-1] = 0
+ return string(err_buffer[:findnull(err_buffer)])
+}
+
+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, old string, flag int) (err Error)
+//sys Mount(fd, afd int, old string, flag int, aname string) (err Error)
+//sys Unmount(name, old 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)
diff -r 09ab865d875c src/pkg/syscall/syscall_plan9_386.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/syscall_plan9_386.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,5 @@
+// Copyright 2009 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.
+
+package syscall
diff -r 09ab865d875c src/pkg/syscall/types_plan9.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/types_plan9.c Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,116 @@
+// Copyright 2009 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.
+
+/*
+Input to godefs. See also mkerrors.sh and mkall.sh
+*/
+
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+typedef long long vlong;
+typedef unsigned long long uvlong;
+
+typedef int $_C_int;
+
+enum {
+ OREAD = 0, /* open for read */
+ OWRITE = 1, /* write */
+ ORDWR = 2, /* read and write */
+
+ $O_RDONLY = OREAD,
+ $O_WRONLY = OWRITE,
+ $O_RDWR = ORDWR,
+
+ OEXEC = 3, /* execute, == read but check execute permission */
+ OTRUNC = 16, /* or'ed in (except for exec), truncate file first */
+ OCEXEC = 32, /* or'ed in, close on exec */
+
+ $O_CLOEXEC = OCEXEC,
+
+ ORCLOSE = 64, /* or'ed in, remove on close */
+ OEXCL = 0x1000, /* or'ed in, exclusive use (create only) */
+ $O_EXCL = OEXCL,
+
+ $STATMAX = 65535U,
+ $ERRMAX = 128,
+
+ $MORDER = 0x0003, /* mask for bits defining order of mounting */
+ $MREPL = 0x0000, /* mount replaces object */
+ $MBEFORE = 0x0001, /* mount goes before others in union directory */
+ $MAFTER = 0x0002, /* mount goes after others in union directory */
+ $MCREATE = 0x0004, /* permit creation in mounted directory */
+ $MCACHE = 0x0010, /* cache some data */
+ $MMASK = 0x0017, /* all bits on */
+
+ $RFNAMEG = (1<<0),
+ $RFENVG = (1<<1),
+ $RFFDG = (1<<2),
+ $RFNOTEG = (1<<3),
+ $RFPROC = (1<<4),
+ $RFMEM = (1<<5),
+ $RFNOWAIT = (1<<6),
+ $RFCNAMEG = (1<<10),
+ $RFCENVG = (1<<11),
+ $RFCFDG = (1<<12),
+ $RFREND = (1<<13),
+ $RFNOMNT = (1<<14),
+
+/* bits in Qid.type */
+ $QTDIR = 0x80, /* type bit for directories */
+ $QTAPPEND = 0x40, /* type bit for append only files */
+ $QTEXCL = 0x20, /* type bit for exclusive use files */
+ $QTMOUNT = 0x10, /* type bit for mounted channel */
+ $QTAUTH = 0x08, /* type bit for authentication file */
+ $QTTMP = 0x04, /* type bit for not-backed-up file */
+ $QTFILE = 0x00, /* plain file */
+
+
+ /* bits in Dir.mode */
+ $DMDIR = 0x80000000, /* mode bit for directories */
+ $DMAPPEND = 0x40000000, /* mode bit for append only files */
+ $DMEXCL = 0x20000000, /* mode bit for exclusive use files */
+ $DMMOUNT = 0x10000000, /* mode bit for mounted channel */
+ $DMAUTH = 0x08000000, /* mode bit for authentication file */
+ $DMTMP = 0x04000000, /* mode bit for non-backed-up files */
+ $DMREAD = 0x4, /* mode bit for read permission */
+ $DMWRITE = 0x2, /* mode bit for write permission */
+ $DMEXEC = 0x1, /* mode bit for execute permission */
+
+ BIT8SZ = 1,
+ BIT16SZ = 2,
+ BIT32SZ = 4,
+ BIT64SZ = 8,
+ QIDSZ = (BIT8SZ+BIT32SZ+BIT64SZ),
+
+ /* STATFIXLEN includes leading 16-bit count */
+ /* The count, however, excludes itself; total size is BIT16SZ+count */
+ $STATFIXLEN = (BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+1*BIT64SZ), /* amount of fixed length data in a stat buffer */
+
+};
+
+
+struct Prof /* Per process profiling */
+{
+ struct Plink *pp; /* known to be 0(ptr) */
+ struct Plink *next; /* known to be 4(ptr) */
+ struct Plink *last;
+ struct Plink *first;
+ ulong pid;
+ ulong what;
+};
+
+struct Tos {
+ struct Prof prof;
+ uvlong cyclefreq; /* cycle clock frequency if there is one, 0 otherwise */
+ vlong kcycles; /* cycles spent in kernel */
+ vlong pcycles; /* cycles spent in process (kernel + user) */
+ ulong pid; /* might as well put the pid here */
+ ulong clock;
+ /* top of stack is here */
+};
+
+typedef struct Prof $Prof;
+typedef struct Tos $Tos;
diff -r 09ab865d875c src/pkg/syscall/zerrors_plan9_386.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/zerrors_plan9_386.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,25 @@
+package syscall
+
+// Constants
+const (
+ // Invented values to support what package os expects.
+ O_CREAT = 0x02000
+ O_NOCTTY = 0x00000
+ O_TRUNC = 0x00000
+ O_NONBLOCK = 0x00000
+ O_APPEND = 0x00000
+ O_SYNC = 0x00000
+ O_ASYNC = 0x00000
+
+
+ S_IFMT = 0x1f000
+ S_IFIFO = 0x1000
+ S_IFCHR = 0x2000
+ S_IFDIR = 0x4000
+ S_IFBLK = 0x6000
+ S_IFREG = 0x8000
+ S_IFLNK = 0xa000
+ S_IFSOCK = 0xc000
+)
+
+// Error table
diff -r 09ab865d875c src/pkg/syscall/zsyscall_plan9_386.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/zsyscall_plan9_386.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,283 @@
+// mksyscall_plan9.sh -l32 syscall_plan9.go syscall_plan9_386.go
+// MACHINE GENERATED BY THE COMMAND ABOVE DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func exits(msg *byte) {
+ Syscall(SYS_EXITS, uintptr(unsafe.Pointer(msg)), 0, 0)
+
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func fd2path(fd int, buf []byte) (err Error) {
+ var _p0 unsafe.Pointer
+ if len(buf) > 0 {
+ _p0 = unsafe.Pointer(&buf[0])
+ }
+ r0, e := SyscallErrstr(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func pipe(p *[2]_C_int) (err Error) {
+ r0, e := SyscallErrstr(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func sleep(millisecs int32) (err Error) {
+ r0, e := SyscallErrstr(SYS_SLEEP, uintptr(millisecs), 0, 0)
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func await(s []byte) (n int, err Error) {
+ var _p0 unsafe.Pointer
+ if len(s) > 0 {
+ _p0 = unsafe.Pointer(&s[0])
+ }
+ r0, e := SyscallErrstr(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
+
+ n = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Dup(oldfd int, newfd int) (fd int, err Error) {
+ r0, e := SyscallErrstr(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
+
+ fd = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Open(path string, mode int) (fd int, err Error) {
+ r0, e := SyscallErrstr(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+
+ fd = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Create(path string, mode int, perm uint32) (fd int, err Error) {
+ r0, e := SyscallErrstr(SYS_CREATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+
+ fd = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Remove(path string) (err Error) {
+ r0, e := SyscallErrstr(SYS_REMOVE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Pread(fd int, p []byte, offset int64) (n int, err Error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ }
+ r0, e := SyscallErrstr6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+
+ n = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err Error) {
+ var _p0 unsafe.Pointer
+ if len(p) > 0 {
+ _p0 = unsafe.Pointer(&p[0])
+ }
+ r0, e := SyscallErrstr6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
+
+ n = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Close(fd int) (err Error) {
+ r0, e := SyscallErrstr(SYS_CLOSE, uintptr(fd), 0, 0)
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Chdir(path string) (err Error) {
+ r0, e := SyscallErrstr(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Bind(name, old string, flag int) (err Error) {
+ r0, e := SyscallErrstr(SYS_BIND, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag))
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Mount(fd, afd int, old string, flag int, aname string) (err Error) {
+ r0, e := SyscallErrstr6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag), uintptr(unsafe.Pointer(StringBytePtr(aname))), 0)
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Unmount(name, old string) (err Error) {
+ r0, e := SyscallErrstr(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(old))), 0)
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Stat(path string, edir []byte) (n int, err Error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ }
+ r0, e := SyscallErrstr(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
+
+ n = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Fstat(fd int, edir []byte) (n int, err Error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ }
+ r0, e := SyscallErrstr(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+
+ n = int(r0)
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Wstat(path string, edir []byte) (err Error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ }
+ r0, e := SyscallErrstr(SYS_WSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP DO NOT EDIT
+
+
+func Fwstat(fd int, edir []byte) (err Error) {
+ var _p0 unsafe.Pointer
+ if len(edir) > 0 {
+ _p0 = unsafe.Pointer(&edir[0])
+ }
+ r0, e := SyscallErrstr(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
+
+ err = nil
+ if int(r0) == -1 {
+ err = NewError(e)
+ }
+ return
+}
diff -r 09ab865d875c src/pkg/syscall/zsysnum_plan9_386.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/zsysnum_plan9_386.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,47 @@
+// mksysnum_plan9.sh /media/sys/src/libc/9syscall/sys.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+ SYS_SYSR1 = 0
+ SYS_BIND = 2
+ SYS_CHDIR = 3
+ SYS_CLOSE = 4
+ SYS_DUP = 5
+ SYS_ALARM = 6
+ SYS_EXEC = 7
+ SYS_EXITS = 8
+ SYS_FAUTH = 10
+ SYS_SEGBRK = 12
+ SYS_OPEN = 14
+ SYS_OSEEK = 16
+ SYS_SLEEP = 17
+ SYS_RFORK = 19
+ SYS_PIPE = 21
+ SYS_CREATE = 22
+ SYS_FD2PATH = 23
+ SYS_BRK_ = 24
+ SYS_REMOVE = 25
+ SYS_NOTIFY = 28
+ SYS_NOTED = 29
+ SYS_SEGATTACH = 30
+ SYS_SEGDETACH = 31
+ SYS_SEGFREE = 32
+ SYS_SEGFLUSH = 33
+ SYS_RENDEZVOUS = 34
+ SYS_UNMOUNT = 35
+ SYS_SEMACQUIRE = 37
+ SYS_SEMRELEASE = 38
+ SYS_SEEK = 39
+ SYS_FVERSION = 40
+ SYS_ERRSTR = 41
+ SYS_STAT = 42
+ SYS_FSTAT = 43
+ SYS_WSTAT = 44
+ SYS_FWSTAT = 45
+ SYS_MOUNT = 46
+ SYS_AWAIT = 47
+ SYS_PREAD = 50
+ SYS_PWRITE = 51
+)
diff -r 09ab865d875c src/pkg/syscall/ztypes_plan9_386.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/syscall/ztypes_plan9_386.go Sat Jan 15 13:00:13 2011 +0200
@@ -0,0 +1,74 @@
+// godefs -gsyscall -f -m32 types_plan9.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+package syscall
+
+// Constants
+const (
+ O_RDONLY = 0
+ O_WRONLY = 0x1
+ O_RDWR = 0x2
+ O_CLOEXEC = 0x20
+ O_EXCL = 0x1000
+ STATMAX = 0xffff
+ ERRMAX = 0x80
+ MORDER = 0x3
+ MREPL = 0
+ MBEFORE = 0x1
+ MAFTER = 0x2
+ MCREATE = 0x4
+ MCACHE = 0x10
+ MMASK = 0x17
+ RFNAMEG = 0x1
+ RFENVG = 0x2
+ RFFDG = 0x4
+ RFNOTEG = 0x8
+ RFPROC = 0x10
+ RFMEM = 0x20
+ RFNOWAIT = 0x40
+ RFCNAMEG = 0x400
+ RFCENVG = 0x800
+ RFCFDG = 0x1000
+ RFREND = 0x2000
+ RFNOMNT = 0x4000
+ QTDIR = 0x80
+ QTAPPEND = 0x40
+ QTEXCL = 0x20
+ QTMOUNT = 0x10
+ QTAUTH = 0x8
+ QTTMP = 0x4
+ QTFILE = 0
+ DMDIR = 0x80000000
+ DMAPPEND = 0x40000000
+ DMEXCL = 0x20000000
+ DMMOUNT = 0x10000000
+ DMAUTH = 0x8000000
+ DMTMP = 0x4000000
+ DMREAD = 0x4
+ DMWRITE = 0x2
+ DMEXEC = 0x1
+ STATFIXLEN = 0x31
+)
+
+// Types
+
+type _C_int int32
+
+type Prof struct {
+ Pp *[0]byte /* sPlink */
+ Next *[0]byte /* sPlink */
+ Last *[0]byte /* sPlink */
+ First *[0]byte /* sPlink */
+ Pid uint32
+ What uint32
+}
+
+type Tos struct {
+ Prof Prof
+ Cyclefreq uint64
+ Kcycles int64
+ Pcycles int64
+ Pid uint32
+ Clock uint32
+}
^ permalink raw reply [flat|nested] 36+ messages in thread