aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/os
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/os')
-rw-r--r--libgo/go/os/dir_plan9.go300
-rw-r--r--libgo/go/os/dir_unix.go54
-rw-r--r--libgo/go/os/env_plan9.go91
-rw-r--r--libgo/go/os/error.go81
-rw-r--r--libgo/go/os/error_plan9.go57
-rw-r--r--libgo/go/os/error_posix.go90
-rw-r--r--libgo/go/os/exec.go120
-rw-r--r--libgo/go/os/exec_plan9.go114
-rw-r--r--libgo/go/os/exec_posix.go127
-rw-r--r--libgo/go/os/file.go277
-rw-r--r--libgo/go/os/file_plan9.go233
-rw-r--r--libgo/go/os/file_posix.go246
-rw-r--r--libgo/go/os/file_unix.go8
-rw-r--r--libgo/go/os/getwd.go2
-rw-r--r--libgo/go/os/inotify/inotify_linux_test.go2
-rw-r--r--libgo/go/os/os_test.go31
-rw-r--r--libgo/go/os/path.go4
-rw-r--r--libgo/go/os/path_test.go27
-rw-r--r--libgo/go/os/proc.go4
-rw-r--r--libgo/go/os/stat_plan9.go84
-rw-r--r--libgo/go/os/sys_linux.go2
-rw-r--r--libgo/go/os/sys_plan9.go27
-rw-r--r--libgo/go/os/time.go4
23 files changed, 1511 insertions, 474 deletions
diff --git a/libgo/go/os/dir_plan9.go b/libgo/go/os/dir_plan9.go
new file mode 100644
index 0000000..7bb0642
--- /dev/null
+++ b/libgo/go/os/dir_plan9.go
@@ -0,0 +1,300 @@
+// 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"
+)
+
+type dirInfo int
+
+var markDirectory dirInfo = ^0
+
+// 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 the entire directory.
+// Readdir returns the array and an Error, if any.
+func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
+ // If this file has no dirinfo, create one.
+ if file.dirinfo == nil {
+ file.dirinfo = &markDirectory
+ }
+
+ size := count
+ if size < 0 {
+ size = 100
+ }
+
+ result := make([]FileInfo, 0, size)
+ var buf [syscall.STATMAX]byte
+
+ for {
+ 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, Eshortstat}
+ }
+
+ for i := 0; i < n; {
+ m, _ := gbit16(buf[i:])
+ m += 2
+
+ if m < syscall.STATFIXLEN {
+ return []FileInfo{}, &PathError{"readdir", file.name, Eshortstat}
+ }
+
+ 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)
+
+ // a negative count means to read until EOF.
+ if count > 0 && len(result) >= count {
+ break
+ }
+
+ i += int(m)
+ }
+ }
+
+ return result, nil
+}
+
+// Readdirnames returns an array of up to count file names residing in the
+// directory associated with file. A negative count will return all of them.
+// Readdir returns the array and an Error, if any.
+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 {
+ // system-modified data
+ Type uint16 // server type
+ Dev uint32 // server subtype
+ // file data
+ Qid Qid // unique id from server
+ Mode uint32 // permissions
+ Atime uint32 // last read time
+ Mtime uint32 // last write time
+ Length uint64 // file length
+ Name string // last element of path
+ Uid string // owner name
+ Gid string // group name
+ Muid string // last modifier name
+}
+
+type Qid struct {
+ Path uint64 // the file server's unique identification for the file
+ Vers uint32 // version number for given Path
+ Type uint8 // the type of the file (syscall.QTDIR for example)
+}
+
+var nullDir = Dir{
+ ^uint16(0),
+ ^uint32(0),
+ Qid{^uint64(0), ^uint32(0), ^uint8(0)},
+ ^uint32(0),
+ ^uint32(0),
+ ^uint32(0),
+ ^uint64(0),
+ "",
+ "",
+ "",
+ "",
+}
+
+// Null assigns members of d with special "don't care" values indicating
+// they should not be written by syscall.Wstat.
+func (d *Dir) Null() {
+ *d = nullDir
+}
+
+// pdir appends a 9P Stat message based on the contents of Dir d to a byte slice b.
+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
+}
+
+// UnmarshalDir reads a 9P Stat message from a 9P protocol message strored in b,
+// returning the corresponding Dir struct.
+func UnmarshalDir(b []byte) (d *Dir, err Error) {
+ n := uint16(0)
+ n, b = gbit16(b)
+
+ if int(n) != len(b) {
+ return nil, 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, Ebadstat
+ }
+
+ return d, nil
+}
+
+// gqid reads the qid part of a 9P Stat message from a 9P protocol message strored in b,
+// returning the corresponding Qid struct and the remaining slice of b.
+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
+}
+
+// pqid appends a Qid struct q to a 9P message 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
+}
+
+// gbit8 reads a byte-sized numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit8(b []byte) (uint8, []byte) {
+ return uint8(b[0]), b[1:]
+}
+
+// gbit16 reads a 16-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit16(b []byte) (uint16, []byte) {
+ return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+// gbit32 reads a 32-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit32(b []byte) (uint32, []byte) {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+// gbit64 reads a 64-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit64(b []byte) (uint64, []byte) {
+ lo, b := gbit32(b)
+ hi, b := gbit32(b)
+ return uint64(hi)<<32 | uint64(lo), b
+}
+
+// gstring reads a string from a 9P protocol message strored in b,
+// returning the value as a Go string and the remaining slice of b.
+func gstring(b []byte) (string, []byte) {
+ n, b := gbit16(b)
+ return string(b[0:n]), b[n:]
+}
+
+// pbit8 appends a byte-sized numeric value x to a 9P message b.
+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
+}
+
+// pbit16 appends a 16-bit numeric value x to a 9P message 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
+}
+
+// pbit32 appends a 32-bit numeric value x to a 9P message 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
+}
+
+// pbit64 appends a 64-bit numeric value x to a 9P message b.
+func pbit64(b []byte, x uint64) []byte {
+ b = pbit32(b, uint32(x))
+ b = pbit32(b, uint32(x>>32))
+ return b
+}
+
+// pstring appends a Go string s to a 9P message 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 --git a/libgo/go/os/dir_unix.go b/libgo/go/os/dir_unix.go
new file mode 100644
index 0000000..f5b8223
--- /dev/null
+++ b/libgo/go/os/dir_unix.go
@@ -0,0 +1,54 @@
+// 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
+)
+
+// Readdirnames reads the contents of the directory associated with file and
+// returns an array of up to count names, in directory order. Subsequent
+// calls on the same file will yield further names.
+// A negative count means to read until EOF.
+// Readdirnames returns the array and an Error, if any.
+func (file *File) Readdirnames(count int) (names []string, err Error) {
+ // If this file has no dirinfo, create one.
+ if file.dirinfo == nil {
+ file.dirinfo = new(dirInfo)
+ // The buffer must be at least a block long.
+ file.dirinfo.buf = make([]byte, blockSize)
+ }
+ d := file.dirinfo
+ size := count
+ if size < 0 {
+ size = 100
+ }
+ names = make([]string, 0, size) // Empty with room to grow.
+ for count != 0 {
+ // Refill the buffer if necessary
+ if d.bufp >= d.nbuf {
+ d.bufp = 0
+ var errno int
+ d.nbuf, errno = syscall.ReadDirent(file.fd, d.buf)
+ if errno != 0 {
+ return names, NewSyscallError("readdirent", errno)
+ }
+ if d.nbuf <= 0 {
+ break // EOF
+ }
+ }
+
+ // Drain the buffer
+ var nb, nc int
+ nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], count, names)
+ d.bufp += nb
+ count -= nc
+ }
+ return names, nil
+}
diff --git a/libgo/go/os/env_plan9.go b/libgo/go/os/env_plan9.go
new file mode 100644
index 0000000..14df55e
--- /dev/null
+++ b/libgo/go/os/env_plan9.go
@@ -0,0 +1,91 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9 environment variables.
+
+package os
+
+import "syscall"
+
+// ENOENV is the Error indicating that an environment variable does not exist.
+var ENOENV = NewError("no such environment variable")
+
+// 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) {
+ if len(key) == 0 {
+ return "", EINVAL
+ }
+ f, e := Open("/env/" + key)
+ if iserror(e) {
+ return "", ENOENV
+ }
+ defer f.Close()
+
+ var buf [4096]byte
+ n, e := f.Read(buf[:len(buf)-1])
+ if iserror(e) {
+ return "", ENOENV
+ }
+ buf[n] = 0
+ return string(buf[0:n]), 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 {
+ if len(key) == 0 {
+ return EINVAL
+ }
+
+ f, e := Create("/env/" + key)
+ if iserror(e) {
+ return e
+ }
+ defer f.Close()
+
+ _, e = f.Write(syscall.StringByteSlice(value))
+ return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+ 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 {
+ env := make([]string, 0, 100)
+
+ f, e := Open("/env")
+ if iserror(e) {
+ panic(e)
+ }
+ defer f.Close()
+
+ names, e := f.Readdirnames(-1)
+ if iserror(e) {
+ panic(e)
+ }
+
+ for _, k := range names {
+ if v, e := Getenverror(k); !iserror(e) {
+ env = append(env, k+"="+v)
+ }
+ }
+ return env[0:len(env)]
+}
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+ return "/tmp"
+}
diff --git a/libgo/go/os/error.go b/libgo/go/os/error.go
index 635a3fe..2c4516c 100644
--- a/libgo/go/os/error.go
+++ b/libgo/go/os/error.go
@@ -4,8 +4,6 @@
package os
-import syscall "syscall"
-
// An Error can represent any printable error condition.
type Error interface {
String() string
@@ -26,63 +24,6 @@ func (e ErrorString) Timeout() bool { return false }
// 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) || e == Errno(syscall.ETIMEDOUT)
-}
-
-// 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)
- ETIMEDOUT Error = Errno(syscall.ETIMEDOUT)
- ENOTCONN Error = Errno(syscall.ENOTCONN)
-)
-
// PathError records an error and the operation and file path that caused it.
type PathError struct {
Op string
@@ -91,25 +32,3 @@ type PathError struct {
}
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 --git a/libgo/go/os/error_plan9.go b/libgo/go/os/error_plan9.go
new file mode 100644
index 0000000..d657586
--- /dev/null
+++ b/libgo/go/os/error_plan9.go
@@ -0,0 +1,57 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+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 details.
+// As a convenience, if err is nil, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err syscall.Error) Error {
+ if err == nil {
+ return nil
+ }
+ return &SyscallError{syscall, err.String()}
+}
+
+var (
+ Eshortstat = NewError("stat buffer too small")
+ Ebadstat = NewError("malformed stat buffer")
+ Ebadfd = NewError("fd out of range or not open")
+ Ebadarg = NewError("bad arg in system call")
+ Enotdir = NewError("not a directory")
+ Enonexist = NewError("file does not exist")
+ Eexist = NewError("file already exists")
+ Eio = NewError("i/o error")
+
+ EINVAL = Ebadarg
+ ENOTDIR = Enotdir
+ ENOENT = Enonexist
+ EEXIST = Eexist
+ EIO = Eio
+
+ ENAMETOOLONG = NewError("file name too long")
+ ERANGE = NewError("math result not representable")
+ EPIPE = NewError("Broken Pipe")
+ EPLAN9 = 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 --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go
new file mode 100644
index 0000000..0ee34e4
--- /dev/null
+++ b/libgo/go/os/error_posix.go
@@ -0,0 +1,90 @@
+// 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) || e == Errno(syscall.ETIMEDOUT)
+}
+
+// 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)
+ ETIMEDOUT Error = Errno(syscall.ETIMEDOUT)
+ ENOTCONN Error = Errno(syscall.ENOTCONN)
+)
+
+// 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 details.
+// 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 --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go
index 9d80ccf..f62caf9 100644
--- a/libgo/go/os/exec.go
+++ b/libgo/go/os/exec.go
@@ -39,126 +39,6 @@ type ProcAttr struct {
Files []*File
}
-// StartProcess starts a new process with the program, arguments and attributes
-// specified by name, argv and attr.
-func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
- sysattr := &syscall.ProcAttr{
- Dir: attr.Dir,
- Env: attr.Env,
- }
- if sysattr.Env == nil {
- sysattr.Env = Environ()
- }
- // Create array of integer (system) fds.
- intfd := make([]int, len(attr.Files))
- for i, f := range attr.Files {
- if f == nil {
- intfd[i] = -1
- } else {
- intfd[i] = f.Fd()
- }
- }
- sysattr.Files = intfd
-
- pid, h, e := syscall.StartProcess(name, argv, sysattr)
- if e != 0 {
- return nil, &PathError{"fork/exec", name, Errno(e)}
- }
- return newProcess(pid, h), 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.
-// StartProcess 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.
-}
-
-// 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.
-// Wait is equivalent to calling FindProcess and then Wait
-// and Release on the result.
-func Wait(pid int, options int) (w *Waitmsg, err Error) {
- p, e := FindProcess(pid)
- if e != nil {
- return nil, e
- }
- defer p.Release()
- return p.Wait(options)
-}
-
-// 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 --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go
new file mode 100644
index 0000000..11874ab
--- /dev/null
+++ b/libgo/go/os/exec_plan9.go
@@ -0,0 +1,114 @@
+// 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 (
+ "runtime"
+ "syscall"
+)
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+ sysattr := &syscall.ProcAttr{
+ Dir: attr.Dir,
+ Env: attr.Env,
+ }
+
+ // Create array of integer (system) fds.
+ intfd := make([]int, len(attr.Files))
+ for i, f := range attr.Files {
+ if f == nil {
+ intfd[i] = -1
+ } else {
+ intfd[i] = f.Fd()
+ }
+ }
+
+ sysattr.Files = intfd
+
+ pid, h, e := syscall.StartProcess(name, argv, sysattr)
+ if iserror(e) {
+ return nil, &PathError{"fork/exec", name, e}
+ }
+
+ return newProcess(pid, h), 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 {
+ e := syscall.Exec(name, argv, envv)
+ if iserror(e) {
+ return &PathError{"exec", name, e}
+ }
+
+ return nil
+}
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg syscall.Waitmsg
+
+// Wait waits for the Process 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 (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+ var waitmsg syscall.Waitmsg
+
+ if p.Pid == -1 {
+ return nil, EINVAL
+ }
+
+ for true {
+ err = syscall.Await(&waitmsg)
+
+ if iserror(err) {
+ return nil, NewSyscallError("wait", err)
+ }
+
+ if waitmsg.Pid == p.Pid {
+ break
+ }
+ }
+
+ return (*Waitmsg)(&waitmsg), nil
+}
+
+// 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.
+// Wait is equivalent to calling FindProcess and then Wait
+// and Release on the result.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+ p, e := FindProcess(pid)
+ if e != nil {
+ return nil, e
+ }
+ defer p.Release()
+ return p.Wait(options)
+}
+
+// Release releases any resources associated with the Process.
+func (p *Process) Release() Error {
+ // NOOP for Plan 9.
+ p.Pid = -1
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(p, nil)
+ return nil
+}
+
+// FindProcess looks for a running process by its pid.
+// The Process it returns can be used to obtain information
+// about the underlying operating system process.
+func FindProcess(pid int) (p *Process, err Error) {
+ // NOOP for Plan 9.
+ return newProcess(pid, 0), nil
+}
+
+func (w Waitmsg) String() string {
+ return "exit status: " + w.Msg
+}
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
new file mode 100644
index 0000000..9102dc0
--- /dev/null
+++ b/libgo/go/os/exec_posix.go
@@ -0,0 +1,127 @@
+// 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"
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+ sysattr := &syscall.ProcAttr{
+ Dir: attr.Dir,
+ Env: attr.Env,
+ }
+ if sysattr.Env == nil {
+ sysattr.Env = Environ()
+ }
+ // Create array of integer (system) fds.
+ intfd := make([]int, len(attr.Files))
+ for i, f := range attr.Files {
+ if f == nil {
+ intfd[i] = -1
+ } else {
+ intfd[i] = f.Fd()
+ }
+ }
+ sysattr.Files = intfd
+
+ pid, h, e := syscall.StartProcess(name, argv, sysattr)
+ if iserror(e) {
+ return nil, &PathError{"fork/exec", name, Errno(e)}
+ }
+ return newProcess(pid, h), 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.
+// StartProcess 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 iserror(e) {
+ 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.
+}
+
+// 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.
+// Wait is equivalent to calling FindProcess and then Wait
+// and Release on the result.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+ p, e := FindProcess(pid)
+ if e != nil {
+ return nil, e
+ }
+ defer p.Release()
+ return p.Wait(options)
+}
+
+// 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 --git a/libgo/go/os/file.go b/libgo/go/os/file.go
index 3f73f1d..3aad802 100644
--- a/libgo/go/os/file.go
+++ b/libgo/go/os/file.go
@@ -51,14 +51,20 @@ const (
O_RDWR int = syscall.O_RDWR // open the file read-write.
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
O_ASYNC int = syscall.O_ASYNC // generate a signal when I/O is available.
- O_CREAT int = syscall.O_CREAT // create a new file if none exists.
- O_EXCL int = syscall.O_EXCL // used with O_CREAT, file must not exist
+ O_CREATE int = syscall.O_CREAT // create a new file if none exists.
+ O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist
O_NOCTTY int = syscall.O_NOCTTY // do not make file the controlling tty.
O_NONBLOCK int = syscall.O_NONBLOCK // open in non-blocking mode.
O_NDELAY int = O_NONBLOCK // synonym for O_NONBLOCK
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
O_TRUNC int = syscall.O_TRUNC // if possible, truncate file when opened.
- O_CREATE int = O_CREAT // create a new file if none exists.
+)
+
+// Seek whence values.
+const (
+ SEEK_SET int = 0 // seek relative to the origin of the file
+ SEEK_CUR int = 1 // seek relative to the current offset
+ SEEK_END int = 2 // seek relative to the end
)
type eofError int
@@ -83,10 +89,10 @@ func (file *File) Read(b []byte) (n int, err Error) {
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 +108,10 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
}
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 +133,10 @@ func (file *File) Write(b []byte) (n int, err Error) {
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 +151,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
}
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 +168,10 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
// 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 +188,19 @@ func (file *File) WriteString(s string) (ret int, err Error) {
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 +209,25 @@ func Chdir(dir string) Error {
// 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()
+// Open opens the named file for reading. If successful, methods on
+// the returned file can be used for reading; the associated file
+// descriptor has mode O_RDONLY.
+// It returns the File and an Error, if any.
+func Open(name string) (file *File, err Error) {
+ return OpenFile(name, O_RDONLY, 0)
}
-// 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
+// Create creates the named file mode 0666 (before umask), truncating
+// it if it already exists. If successful, methods on the returned
+// File can be used for I/O; the associated file descriptor has mode
+// O_RDWR.
+// It returns the File and an Error, if any.
+func Create(name string) (file *File, err Error) {
+ return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go
new file mode 100644
index 0000000..b79256c5
--- /dev/null
+++ b/libgo/go/os/file_plan9.go
@@ -0,0 +1,233 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+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 = "/dev/null"
+
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead. It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful,
+// methods on the returned File can be used for I/O.
+// It returns the File and an Error, if any.
+func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
+ var fd int
+ var e syscall.Error
+
+ syscall.ForkLock.RLock()
+ if flag&O_CREATE == O_CREATE {
+ fd, e = syscall.Create(name, flag & ^O_CREATE, perm)
+ } else {
+ fd, e = syscall.Open(name, flag)
+ }
+ syscall.ForkLock.RUnlock()
+
+ 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 Ebadfd
+ }
+ var err Error
+ syscall.ForkLock.RLock()
+ if e := syscall.Close(file.fd); e != nil {
+ err = &PathError{"close", file.name, e}
+ }
+ syscall.ForkLock.RUnlock()
+ 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 {
+ var d Dir
+ d.Null()
+
+ d.Length = uint64(size)
+
+ if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+ return &PathError{"truncate", f.name, e}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the file to mode.
+func (f *File) Chmod(mode uint32) Error {
+ var d Dir
+ d.Null()
+
+ d.Mode = mode & 0777
+
+ if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chmod", 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
+ }
+
+ var d Dir
+ d.Null()
+
+ 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 {
+ var d Dir
+ d.Null()
+
+ 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
+}
+
+// Rename renames a file.
+func Rename(oldname, newname string) Error {
+ var d Dir
+ d.Null()
+
+ d.Name = newname
+
+ if e := syscall.Wstat(oldname, pdir(nil, &d)); iserror(e) {
+ return &PathError{"rename", oldname, e}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+func Chmod(name string, mode uint32) Error {
+ var d Dir
+ d.Null()
+
+ d.Mode = mode & 0777
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chmod", name, e}
+ }
+ return nil
+}
+
+// ChownPlan9 changes the uid and gid strings of the named file.
+func ChownPlan9(name, uid, gid string) Error {
+ var d Dir
+ d.Null()
+
+ 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, atimeNs int64, mtimeNs int64) Error {
+ var d Dir
+ d.Null()
+
+ d.Atime = uint32(atimeNs / 1e9)
+ d.Mtime = uint32(mtimeNs / 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
+
+ syscall.ForkLock.RLock()
+ if e := syscall.Pipe(p[0:]); iserror(e) {
+ syscall.ForkLock.RUnlock()
+ return nil, nil, NewSyscallError("pipe", e)
+ }
+ syscall.ForkLock.RUnlock()
+
+ 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
+}
+
+func (f *File) Chown(uid, gid int) Error {
+ return EPLAN9
+}
diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go
new file mode 100644
index 0000000..5151df4
--- /dev/null
+++ b/libgo/go/os/file_posix.go
@@ -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 --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index 01268e5..f80f1d5 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -19,10 +19,12 @@ type dirInfo struct {
// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
const DevNull = "/dev/null"
-// Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.)
-// if applicable. If successful, methods on the returned File can be used for I/O.
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead. It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. 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) {
+func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm)
if e != 0 {
return nil, &PathError{"open", name, Errno(e)}
diff --git a/libgo/go/os/getwd.go b/libgo/go/os/getwd.go
index 49aaea8..4c142ad 100644
--- a/libgo/go/os/getwd.go
+++ b/libgo/go/os/getwd.go
@@ -54,7 +54,7 @@ func Getwd() (string, Error) {
if len(parent) >= 1024 { // Sanity check
return "", ENAMETOOLONG
}
- fd, err := Open(parent, O_RDONLY, 0)
+ fd, err := Open(parent)
if err != nil {
return "", err
}
diff --git a/libgo/go/os/inotify/inotify_linux_test.go b/libgo/go/os/inotify/inotify_linux_test.go
index 79c3bfa..f5d1f83 100644
--- a/libgo/go/os/inotify/inotify_linux_test.go
+++ b/libgo/go/os/inotify/inotify_linux_test.go
@@ -51,7 +51,7 @@ func TestInotifyEvents(t *testing.T) {
// Create a file
// This should add at least one event to the inotify event queue
- _, err = os.Open(testFile, os.O_WRONLY|os.O_CREAT, 0666)
+ _, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index bb1b8e3..607a11b 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -17,6 +17,7 @@ import (
)
var dot = []string{
+ "dir_unix.go",
"env_unix.go",
"error.go",
"file.go",
@@ -56,7 +57,7 @@ var sysdir = func() (sd *sysDir) {
}()
func size(name string, t *testing.T) int64 {
- file, err := Open(name, O_RDONLY, 0)
+ file, err := Open(name)
defer file.Close()
if err != nil {
t.Fatal("open failed:", err)
@@ -121,7 +122,7 @@ func TestStat(t *testing.T) {
func TestFstat(t *testing.T) {
path := sfdir + "/" + sfname
- file, err1 := Open(path, O_RDONLY, 0)
+ file, err1 := Open(path)
defer file.Close()
if err1 != nil {
t.Fatal("open failed:", err1)
@@ -155,7 +156,7 @@ func TestLstat(t *testing.T) {
}
func testReaddirnames(dir string, contents []string, t *testing.T) {
- file, err := Open(dir, O_RDONLY, 0)
+ file, err := Open(dir)
defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
@@ -184,7 +185,7 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
}
func testReaddir(dir string, contents []string, t *testing.T) {
- file, err := Open(dir, O_RDONLY, 0)
+ file, err := Open(dir)
defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
@@ -245,7 +246,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
if syscall.OS == "windows" {
dir = Getenv("SystemRoot") + "\\system32"
}
- file, err := Open(dir, O_RDONLY, 0)
+ file, err := Open(dir)
defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
@@ -254,7 +255,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
if err1 != nil {
t.Fatalf("readdirnames %q failed: %v", dir, err1)
}
- file1, err2 := Open(dir, O_RDONLY, 0)
+ file1, err2 := Open(dir)
if err2 != nil {
t.Fatalf("open %q failed: %v", dir, err2)
}
@@ -273,7 +274,7 @@ func TestHardLink(t *testing.T) {
}
from, to := "hardlinktestfrom", "hardlinktestto"
Remove(from) // Just in case.
- file, err := Open(to, O_CREAT|O_WRONLY, 0666)
+ file, err := Create(to)
if err != nil {
t.Fatalf("open %q failed: %v", to, err)
}
@@ -306,7 +307,7 @@ func TestSymLink(t *testing.T) {
}
from, to := "symlinktestfrom", "symlinktestto"
Remove(from) // Just in case.
- file, err := Open(to, O_CREAT|O_WRONLY, 0666)
+ file, err := Create(to)
if err != nil {
t.Fatalf("open %q failed: %v", to, err)
}
@@ -354,7 +355,7 @@ func TestSymLink(t *testing.T) {
if s != to {
t.Fatalf("after symlink %q != %q", s, to)
}
- file, err = Open(from, O_RDONLY, 0)
+ file, err = Open(from)
if err != nil {
t.Fatalf("open %q failed: %v", from, err)
}
@@ -388,7 +389,7 @@ func TestLongSymlink(t *testing.T) {
func TestRename(t *testing.T) {
from, to := "renamefrom", "renameto"
Remove(to) // Just in case.
- file, err := Open(from, O_CREAT|O_WRONLY, 0666)
+ file, err := Create(from)
if err != nil {
t.Fatalf("open %q failed: %v", to, err)
}
@@ -615,7 +616,7 @@ func TestChdirAndGetwd(t *testing.T) {
if syscall.OS == "windows" {
return
}
- fd, err := Open(".", O_RDONLY, 0)
+ fd, err := Open(".")
if err != nil {
t.Fatalf("Open .: %s", err)
}
@@ -627,7 +628,7 @@ func TestChdirAndGetwd(t *testing.T) {
if mode == 0 {
err = Chdir(d)
} else {
- fd1, err := Open(d, O_RDONLY, 0)
+ fd1, err := Open(d)
if err != nil {
t.Errorf("Open %s: %s", d, err)
continue
@@ -736,7 +737,7 @@ var openErrorTests = []openErrorTest{
func TestOpenError(t *testing.T) {
for _, tt := range openErrorTests {
- f, err := Open(tt.path, tt.mode, 0)
+ f, err := OpenFile(tt.path, tt.mode, 0)
if err == nil {
t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
f.Close()
@@ -842,7 +843,7 @@ func TestWriteAt(t *testing.T) {
}
func writeFile(t *testing.T, fname string, flag int, text string) string {
- f, err := Open(fname, flag, 0666)
+ f, err := OpenFile(fname, flag, 0666)
if err != nil {
t.Fatalf("Open: %v", err)
}
@@ -861,7 +862,7 @@ func writeFile(t *testing.T, fname string, flag int, text string) string {
func TestAppend(t *testing.T) {
const f = "append.txt"
defer Remove(f)
- s := writeFile(t, f, O_CREAT|O_TRUNC|O_RDWR, "new")
+ s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
if s != "new" {
t.Fatalf("writeFile: have %q want %q", s, "new")
}
diff --git a/libgo/go/os/path.go b/libgo/go/os/path.go
index b762971..0eb3ee5 100644
--- a/libgo/go/os/path.go
+++ b/libgo/go/os/path.go
@@ -33,7 +33,7 @@ func MkdirAll(path string, perm uint32) Error {
j--
}
- if j > 0 {
+ if j > 1 {
// Create parent
err = MkdirAll(path[0:j-1], perm)
if err != nil {
@@ -80,7 +80,7 @@ func RemoveAll(path string) Error {
}
// Directory.
- fd, err := Open(path, O_RDONLY, 0)
+ fd, err := Open(path)
if err != nil {
return err
}
diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go
index 799e3ec..483bb63 100644
--- a/libgo/go/os/path_test.go
+++ b/libgo/go/os/path_test.go
@@ -29,7 +29,7 @@ func TestMkdirAll(t *testing.T) {
// Make file.
fpath := path + "/file"
- _, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
+ _, err = Create(fpath)
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
@@ -72,7 +72,7 @@ func TestRemoveAll(t *testing.T) {
if err := MkdirAll(path, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", path, err)
}
- fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
+ fd, err := Create(fpath)
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
@@ -88,12 +88,12 @@ func TestRemoveAll(t *testing.T) {
if err = MkdirAll(dpath, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", dpath, err)
}
- fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
+ fd, err = Create(fpath)
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
fd.Close()
- fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
+ fd, err = Create(dpath + "/file")
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
@@ -121,7 +121,7 @@ func TestRemoveAll(t *testing.T) {
}
for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
- fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
+ fd, err = Create(s)
if err != nil {
t.Fatalf("create %q: %s", s, err)
}
@@ -179,3 +179,20 @@ func TestMkdirAllWithSymlink(t *testing.T) {
t.Errorf("MkdirAll %q: %s", path, err)
}
}
+
+func TestMkdirAllAtSlash(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ return
+ }
+ RemoveAll("/_go_os_test")
+ err := MkdirAll("/_go_os_test/dir", 0777)
+ if err != nil {
+ pathErr, ok := err.(*PathError)
+ // common for users not to be able to write to /
+ if ok && pathErr.Error == EACCES {
+ return
+ }
+ t.Fatalf(`MkdirAll "/_go_os_test/dir": %v`, err)
+ }
+ RemoveAll("/_go_os_test")
+}
diff --git a/libgo/go/os/proc.go b/libgo/go/os/proc.go
index dfddab6..481ef60 100644
--- a/libgo/go/os/proc.go
+++ b/libgo/go/os/proc.go
@@ -26,8 +26,8 @@ func Getegid() int { return syscall.Getegid() }
// 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 --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go
new file mode 100644
index 0000000..e96749d
--- /dev/null
+++ b/libgo/go/os/stat_plan9.go
@@ -0,0 +1,84 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+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 syscallArg := arg.(type) {
+ case *File:
+ name = syscallArg.name
+ n, e = syscall.Fstat(syscallArg.fd, buf)
+ case string:
+ name = syscallArg
+ n, e = syscall.Stat(name, buf)
+ }
+
+ if e != nil {
+ return nil, &PathError{"stat", name, e}
+ }
+
+ if n < syscall.STATFIXLEN {
+ return nil, &PathError{"stat", name, Eshortstat}
+ }
+
+ 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, 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)
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any. If the file is a symbolic link (though Plan 9 does not have symbolic links),
+// the returned FileInfo describes the symbolic link. Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+ return dirstat(name)
+}
diff --git a/libgo/go/os/sys_linux.go b/libgo/go/os/sys_linux.go
index b82d295..408d667 100644
--- a/libgo/go/os/sys_linux.go
+++ b/libgo/go/os/sys_linux.go
@@ -9,7 +9,7 @@ package os
// Hostname returns the host name reported by the kernel.
func Hostname() (name string, err Error) {
- f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0)
+ f, err := Open("/proc/sys/kernel/hostname")
if err != nil {
return "", err
}
diff --git a/libgo/go/os/sys_plan9.go b/libgo/go/os/sys_plan9.go
new file mode 100644
index 0000000..f6af28b
--- /dev/null
+++ b/libgo/go/os/sys_plan9.go
@@ -0,0 +1,27 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9-specific
+
+package os
+
+
+func Hostname() (name string, err Error) {
+ f, err := Open("#c/sysname")
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ var buf [128]byte
+ n, err := f.Read(buf[:len(buf)-1])
+
+ if err != nil {
+ return "", err
+ }
+ if n > 0 {
+ buf[n] = 0
+ }
+ return string(buf[0:n]), nil
+}
diff --git a/libgo/go/os/time.go b/libgo/go/os/time.go
index 380345f..8e87a49 100644
--- a/libgo/go/os/time.go
+++ b/libgo/go/os/time.go
@@ -13,8 +13,8 @@ import "syscall"
// 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
}