9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: Pavel Zholkover <paulzhol@gmail.com>
To: Fans of the OS Plan 9 from Bell Labs <9fans@9fans.net>
Subject: Re: [9fans] plan9 go output faults on 9vx but ok on cpu
Date: Sat, 15 Jan 2011 13:25:09 +0200	[thread overview]
Message-ID: <AANLkTinu2xB+du_sN=AHvd8zYn5sMt_J2rEH_Bt2jH-i@mail.gmail.com> (raw)
In-Reply-To: <c629684324985d129c4a1286510b30a9@proxima.alt.za>

[-- 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
+}

  reply	other threads:[~2011-01-15 11:25 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-11  7:54 Skip Tavakkolian
2011-01-11 14:11 ` erik quanstrom
2011-01-11 15:06   ` Devon H. O'Dell
2011-01-11 17:03   ` Charles Forsyth
2011-01-11 17:51     ` ron minnich
2011-01-11 19:35       ` Pavel Zholkover
2011-01-11 23:58       ` Charles Forsyth
2011-01-11 16:25 ` ron minnich
2011-01-12  8:32   ` Skip Tavakkolian
2011-01-12 16:12     ` andrey mirtchovski
2011-01-12 22:03       ` ron minnich
2011-01-13  5:54     ` ron minnich
2011-01-14 17:32       ` Pavel Zholkover
2011-01-15  2:00         ` Anthony Martin
2011-01-15  9:47           ` Pavel Zholkover
2011-01-15  9:01         ` kokamoto
2011-01-15  9:19           ` Pavel Zholkover
2011-01-15  9:30           ` lucio
2011-01-15  9:58             ` Pavel Zholkover
2011-01-15 10:29               ` lucio
2011-01-15 10:40               ` lucio
2011-01-15 11:25                 ` Pavel Zholkover [this message]
2011-01-16  1:51                   ` kokamoto
2011-01-16  2:04                     ` kokamoto
2011-01-16  6:21                       ` kokamoto
2011-01-17 12:03                         ` kokamoto
2011-01-17 15:20                         ` [9fans] how to make hardware work? sergey.kish
2011-01-16  2:06                     ` [9fans] plan9 go output faults on 9vx but ok on cpu Skip Tavakkolian
2011-01-11 17:03 ` Pavel Zholkover
2011-01-11 18:55   ` Anthony Martin
2011-01-11 19:06     ` Anthony Martin
2011-01-11 22:58     ` ron minnich
2011-01-12 22:31       ` Anthony Martin
2011-01-12 22:36         ` erik quanstrom
2011-01-12 23:28           ` Pavel Zholkover
2011-01-12 23:29         ` Charles Forsyth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='AANLkTinu2xB+du_sN=AHvd8zYn5sMt_J2rEH_Bt2jH-i@mail.gmail.com' \
    --to=paulzhol@gmail.com \
    --cc=9fans@9fans.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).