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