aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/os
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-07-19 08:53:52 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-07-19 08:53:52 +0000
commit00d86ac99f5dd6afa5bbd7c38ffe1c585edd2387 (patch)
treeb988e32ea14a3dc1b4718b1fdfa47bab087ae96c /libgo/go/os
parentbcf2fc6ee0a7edbe7de4299f28b66527c07bb0a2 (diff)
downloadgcc-00d86ac99f5dd6afa5bbd7c38ffe1c585edd2387.zip
gcc-00d86ac99f5dd6afa5bbd7c38ffe1c585edd2387.tar.gz
gcc-00d86ac99f5dd6afa5bbd7c38ffe1c585edd2387.tar.bz2
libgo: Update to Go 1.3 release.
From-SVN: r212837
Diffstat (limited to 'libgo/go/os')
-rw-r--r--libgo/go/os/dir_unix.go2
-rw-r--r--libgo/go/os/doc.go3
-rw-r--r--libgo/go/os/error_unix.go2
-rw-r--r--libgo/go/os/exec/exec.go56
-rw-r--r--libgo/go/os/exec/exec_test.go81
-rw-r--r--libgo/go/os/exec/lp_unix.go2
-rw-r--r--libgo/go/os/exec_plan9.go9
-rw-r--r--libgo/go/os/exec_posix.go2
-rw-r--r--libgo/go/os/exec_unix.go5
-rw-r--r--libgo/go/os/file_posix.go2
-rw-r--r--libgo/go/os/file_unix.go42
-rw-r--r--libgo/go/os/getwd.go28
-rw-r--r--libgo/go/os/os_test.go43
-rw-r--r--libgo/go/os/path_test.go5
-rw-r--r--libgo/go/os/path_unix.go2
-rw-r--r--libgo/go/os/pipe_bsd.go2
-rw-r--r--libgo/go/os/signal/signal_unix.go2
-rw-r--r--libgo/go/os/stat_nacl.go62
-rw-r--r--libgo/go/os/sys_bsd.go2
-rw-r--r--libgo/go/os/sys_darwin.go31
-rw-r--r--libgo/go/os/sys_freebsd.go23
-rw-r--r--libgo/go/os/sys_nacl.go9
-rw-r--r--libgo/go/os/sys_unix.go11
23 files changed, 339 insertions, 87 deletions
diff --git a/libgo/go/os/dir_unix.go b/libgo/go/os/dir_unix.go
index 67c3902..d353e40 100644
--- a/libgo/go/os/dir_unix.go
+++ b/libgo/go/os/dir_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os
diff --git a/libgo/go/os/doc.go b/libgo/go/os/doc.go
index a954e31..389a8eb 100644
--- a/libgo/go/os/doc.go
+++ b/libgo/go/os/doc.go
@@ -39,11 +39,14 @@ func (p *Process) Kill() error {
// Wait waits for the Process to exit, and then returns a
// ProcessState describing its status and an error, if any.
// Wait releases any resources associated with the Process.
+// On most operating systems, the Process must be a child
+// of the current process or an error will be returned.
func (p *Process) Wait() (*ProcessState, error) {
return p.wait()
}
// Signal sends a signal to the Process.
+// Sending Interrupt on Windows is not implemented.
func (p *Process) Signal(sig Signal) error {
return p.signal(sig)
}
diff --git a/libgo/go/os/error_unix.go b/libgo/go/os/error_unix.go
index f281495..f2aabbb 100644
--- a/libgo/go/os/error_unix.go
+++ b/libgo/go/os/error_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os
diff --git a/libgo/go/os/exec/exec.go b/libgo/go/os/exec/exec.go
index 4680036..a70ed0d 100644
--- a/libgo/go/os/exec/exec.go
+++ b/libgo/go/os/exec/exec.go
@@ -13,7 +13,9 @@ import (
"io"
"os"
"path/filepath"
+ "runtime"
"strconv"
+ "strings"
"sync"
"syscall"
)
@@ -237,13 +239,51 @@ func (c *Cmd) Run() error {
return c.Wait()
}
+// lookExtensions finds windows executable by its dir and path.
+// It uses LookPath to try appropriate extensions.
+// lookExtensions does not search PATH, instead it converts `prog` into `.\prog`.
+func lookExtensions(path, dir string) (string, error) {
+ if filepath.Base(path) == path {
+ path = filepath.Join(".", path)
+ }
+ if dir == "" {
+ return LookPath(path)
+ }
+ if filepath.VolumeName(path) != "" {
+ return LookPath(path)
+ }
+ if len(path) > 1 && os.IsPathSeparator(path[0]) {
+ return LookPath(path)
+ }
+ dirandpath := filepath.Join(dir, path)
+ // We assume that LookPath will only add file extension.
+ lp, err := LookPath(dirandpath)
+ if err != nil {
+ return "", err
+ }
+ ext := strings.TrimPrefix(lp, dirandpath)
+ return path + ext, nil
+}
+
// Start starts the specified command but does not wait for it to complete.
+//
+// The Wait method will return the exit code and release associated resources
+// once the command exits.
func (c *Cmd) Start() error {
if c.lookPathErr != nil {
c.closeDescriptors(c.closeAfterStart)
c.closeDescriptors(c.closeAfterWait)
return c.lookPathErr
}
+ if runtime.GOOS == "windows" {
+ lp, err := lookExtensions(c.Path, c.Dir)
+ if err != nil {
+ c.closeDescriptors(c.closeAfterStart)
+ c.closeDescriptors(c.closeAfterWait)
+ return err
+ }
+ c.Path = lp
+ }
if c.Process != nil {
return errors.New("exec: already started")
}
@@ -304,6 +344,8 @@ func (e *ExitError) Error() string {
// If the command fails to run or doesn't complete successfully, the
// error is of type *ExitError. Other error types may be
// returned for I/O problems.
+//
+// Wait releases any resources associated with the Cmd.
func (c *Cmd) Wait() error {
if c.Process == nil {
return errors.New("exec: not started")
@@ -387,15 +429,17 @@ func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
type closeOnce struct {
*os.File
- close sync.Once
- closeErr error
+ once sync.Once
+ err error
}
func (c *closeOnce) Close() error {
- c.close.Do(func() {
- c.closeErr = c.File.Close()
- })
- return c.closeErr
+ c.once.Do(c.close)
+ return c.err
+}
+
+func (c *closeOnce) close() {
+ c.err = c.File.Close()
}
// StdoutPipe returns a pipe that will be connected to the command's
diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go
index 0624892..8521bfd 100644
--- a/libgo/go/os/exec/exec_test.go
+++ b/libgo/go/os/exec/exec_test.go
@@ -13,6 +13,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "log"
"net"
"net/http"
"net/http/httptest"
@@ -26,7 +27,10 @@ import (
"time"
)
-func helperCommand(s ...string) *exec.Cmd {
+func helperCommand(t *testing.T, s ...string) *exec.Cmd {
+ if runtime.GOOS == "nacl" {
+ t.Skip("skipping on nacl")
+ }
cs := []string{"-test.run=TestHelperProcess", "--"}
cs = append(cs, s...)
cmd := exec.Command(os.Args[0], cs...)
@@ -39,7 +43,7 @@ func helperCommand(s ...string) *exec.Cmd {
}
func TestEcho(t *testing.T) {
- bs, err := helperCommand("echo", "foo bar", "baz").Output()
+ bs, err := helperCommand(t, "echo", "foo bar", "baz").Output()
if err != nil {
t.Errorf("echo: %v", err)
}
@@ -78,7 +82,7 @@ func TestCommandRelativeName(t *testing.T) {
func TestCatStdin(t *testing.T) {
// Cat, testing stdin and stdout.
input := "Input string\nLine 2"
- p := helperCommand("cat")
+ p := helperCommand(t, "cat")
p.Stdin = strings.NewReader(input)
bs, err := p.Output()
if err != nil {
@@ -92,7 +96,7 @@ func TestCatStdin(t *testing.T) {
func TestCatGoodAndBadFile(t *testing.T) {
// Testing combined output and error values.
- bs, err := helperCommand("cat", "/bogus/file.foo", "exec_test.go").CombinedOutput()
+ bs, err := helperCommand(t, "cat", "/bogus/file.foo", "exec_test.go").CombinedOutput()
if _, ok := err.(*exec.ExitError); !ok {
t.Errorf("expected *exec.ExitError from cat combined; got %T: %v", err, err)
}
@@ -120,7 +124,7 @@ func TestNoExistBinary(t *testing.T) {
func TestExitStatus(t *testing.T) {
// Test that exit values are returned correctly
- cmd := helperCommand("exit", "42")
+ cmd := helperCommand(t, "exit", "42")
err := cmd.Run()
want := "exit status 42"
switch runtime.GOOS {
@@ -143,7 +147,7 @@ func TestPipes(t *testing.T) {
}
}
// Cat, testing stdin and stdout.
- c := helperCommand("pipetest")
+ c := helperCommand(t, "pipetest")
stdin, err := c.StdinPipe()
check("StdinPipe", err)
stdout, err := c.StdoutPipe()
@@ -196,7 +200,7 @@ func TestStdinClose(t *testing.T) {
t.Fatalf("%s: %v", what, err)
}
}
- cmd := helperCommand("stdinClose")
+ cmd := helperCommand(t, "stdinClose")
stdin, err := cmd.StdinPipe()
check("StdinPipe", err)
// Check that we can access methods of the underlying os.File.`
@@ -217,7 +221,7 @@ func TestStdinClose(t *testing.T) {
// Issue 5071
func TestPipeLookPathLeak(t *testing.T) {
- fd0 := numOpenFDS(t)
+ fd0, lsof0 := numOpenFDS(t)
for i := 0; i < 4; i++ {
cmd := exec.Command("something-that-does-not-exist-binary")
cmd.StdoutPipe()
@@ -227,19 +231,30 @@ func TestPipeLookPathLeak(t *testing.T) {
t.Fatal("unexpected success")
}
}
- fdGrowth := numOpenFDS(t) - fd0
- if fdGrowth > 2 {
- t.Errorf("leaked %d fds; want ~0", fdGrowth)
+ for triesLeft := 3; triesLeft >= 0; triesLeft-- {
+ open, lsof := numOpenFDS(t)
+ fdGrowth := open - fd0
+ if fdGrowth > 2 {
+ if triesLeft > 0 {
+ // Work around what appears to be a race with Linux's
+ // proc filesystem (as used by lsof). It seems to only
+ // be eventually consistent. Give it awhile to settle.
+ // See golang.org/issue/7808
+ time.Sleep(100 * time.Millisecond)
+ continue
+ }
+ t.Errorf("leaked %d fds; want ~0; have:\n%s\noriginally:\n%s", fdGrowth, lsof, lsof0)
+ }
+ break
}
}
-func numOpenFDS(t *testing.T) int {
+func numOpenFDS(t *testing.T) (n int, lsof []byte) {
lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
if err != nil {
t.Skip("skipping test; error finding or running lsof")
- return 0
}
- return bytes.Count(lsof, []byte("\n"))
+ return bytes.Count(lsof, []byte("\n")), lsof
}
var testedAlreadyLeaked = false
@@ -305,7 +320,7 @@ func TestExtraFilesFDShuffle(t *testing.T) {
// Moving this test case around within the overall tests may
// affect the FDs obtained and hence the checks to catch these cases.
npipes := 2
- c := helperCommand("extraFilesAndPipes", strconv.Itoa(npipes+1))
+ c := helperCommand(t, "extraFilesAndPipes", strconv.Itoa(npipes+1))
rd, wr, _ := os.Pipe()
defer rd.Close()
if rd.Fd() != 3 {
@@ -405,11 +420,15 @@ func TestExtraFiles(t *testing.T) {
// Force TLS root certs to be loaded (which might involve
// cgo), to make sure none of that potential C code leaks fds.
- ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("Hello"))
- }))
+ ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
+ // quiet expected TLS handshake error "remote error: bad certificate"
+ ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+ ts.StartTLS()
defer ts.Close()
- http.Get(ts.URL) // ignore result; just calling to force root cert loading
+ _, err = http.Get(ts.URL)
+ if err == nil {
+ t.Errorf("success trying to fetch %s; want an error", ts.URL)
+ }
tf, err := ioutil.TempFile("", "")
if err != nil {
@@ -428,7 +447,7 @@ func TestExtraFiles(t *testing.T) {
t.Fatalf("Seek: %v", err)
}
- c := helperCommand("read3")
+ c := helperCommand(t, "read3")
var stdout, stderr bytes.Buffer
c.Stdout = &stdout
c.Stderr = &stderr
@@ -471,10 +490,10 @@ func TestExtraFilesRace(t *testing.T) {
for i := 0; i < 10; i++ {
la := listen()
- ca := helperCommand("describefiles")
+ ca := helperCommand(t, "describefiles")
ca.ExtraFiles = []*os.File{listenerFile(la)}
lb := listen()
- cb := helperCommand("describefiles")
+ cb := helperCommand(t, "describefiles")
cb.ExtraFiles = []*os.File{listenerFile(lb)}
ares := make(chan string)
bres := make(chan string)
@@ -686,6 +705,24 @@ func TestHelperProcess(*testing.T) {
}
fmt.Fprintf(os.Stderr, "child: %s", response)
os.Exit(0)
+ case "exec":
+ cmd := exec.Command(args[1])
+ cmd.Dir = args[0]
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Child: %s %s", err, string(output))
+ os.Exit(1)
+ }
+ fmt.Printf("%s", string(output))
+ os.Exit(0)
+ case "lookpath":
+ p, err := exec.LookPath(args[0])
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "LookPath failed: %v\n", err)
+ os.Exit(1)
+ }
+ fmt.Print(p)
+ os.Exit(0)
default:
fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
os.Exit(2)
diff --git a/libgo/go/os/exec/lp_unix.go b/libgo/go/os/exec/lp_unix.go
index 7b9dec7..3f895d5 100644
--- a/libgo/go/os/exec/lp_unix.go
+++ b/libgo/go/os/exec/lp_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package exec
diff --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go
index 2bd5b68..676be36 100644
--- a/libgo/go/os/exec_plan9.go
+++ b/libgo/go/os/exec_plan9.go
@@ -52,10 +52,6 @@ func (p *Process) signal(sig Signal) error {
if p.done() {
return errors.New("os: process already finished")
}
- if sig == Kill {
- // Special-case the kill signal since it doesn't use /proc/$pid/note.
- return p.Kill()
- }
if e := p.writeProcFile("note", sig.String()); e != nil {
return NewSyscallError("signal", e)
}
@@ -63,10 +59,7 @@ func (p *Process) signal(sig Signal) error {
}
func (p *Process) kill() error {
- if e := p.writeProcFile("ctl", "kill"); e != nil {
- return NewSyscallError("kill", e)
- }
- return nil
+ return p.signal(Kill)
}
func (p *Process) wait() (ps *ProcessState, err error) {
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
index 8a4d019..fb9d291 100644
--- a/libgo/go/os/exec_posix.go
+++ b/libgo/go/os/exec_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package os
diff --git a/libgo/go/os/exec_unix.go b/libgo/go/os/exec_unix.go
index 3c05b8f..1b1e335 100644
--- a/libgo/go/os/exec_unix.go
+++ b/libgo/go/os/exec_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os
@@ -38,6 +38,9 @@ func (p *Process) signal(sig Signal) error {
if p.done() {
return errors.New("os: process already finished")
}
+ if p.Pid == -1 {
+ return errors.New("os: process already released")
+ }
s, ok := sig.(syscall.Signal)
if !ok {
return errors.New("os: unsupported signal type")
diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go
index 441ad53..b3466b1 100644
--- a/libgo/go/os/file_posix.go
+++ b/libgo/go/os/file_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package os
diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index 3358842..7959091 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os
@@ -80,12 +80,7 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
// There's a race here with fork/exec, which we are
// content to live with. See ../syscall/exec_unix.go.
- // On OS X 10.6, the O_CLOEXEC flag is not respected.
- // On OS X 10.7, the O_CLOEXEC flag works.
- // Without a cheap & reliable way to detect 10.6 vs 10.7 at
- // runtime, we just always call syscall.CloseOnExec on Darwin.
- // Once >=10.7 is prevalent, this extra call can removed.
- if syscall.O_CLOEXEC == 0 || runtime.GOOS == "darwin" { // O_CLOEXEC not supported
+ if !supportsCloseOnExec {
syscall.CloseOnExec(r)
}
@@ -188,16 +183,31 @@ func (f *File) readdir(n int) (fi []FileInfo, err error) {
return fi, err
}
+// Darwin and FreeBSD can't read or write 2GB+ at a time,
+// even on 64-bit systems. See golang.org/issue/7812.
+// Use 1GB instead of, say, 2GB-1, to keep subsequent
+// reads aligned.
+const (
+ needsMaxRW = runtime.GOOS == "darwin" || runtime.GOOS == "freebsd"
+ maxRW = 1 << 30
+)
+
// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func (f *File) read(b []byte) (n int, err error) {
+ if needsMaxRW && len(b) > maxRW {
+ b = b[:maxRW]
+ }
return syscall.Read(f.fd, b)
}
// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
-// EOF is signaled by a zero count with err set to 0.
+// EOF is signaled by a zero count with err set to nil.
func (f *File) pread(b []byte, off int64) (n int, err error) {
+ if needsMaxRW && len(b) > maxRW {
+ b = b[:maxRW]
+ }
return syscall.Pread(f.fd, b, off)
}
@@ -205,13 +215,22 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
// It returns the number of bytes written and an error, if any.
func (f *File) write(b []byte) (n int, err error) {
for {
- m, err := syscall.Write(f.fd, b)
+ bcap := b
+ if needsMaxRW && len(bcap) > maxRW {
+ bcap = bcap[:maxRW]
+ }
+ m, err := syscall.Write(f.fd, bcap)
n += m
// If the syscall wrote some data but not all (short write)
// or it returned EINTR, then assume it stopped early for
// reasons that are uninteresting to the caller, and try again.
- if 0 < m && m < len(b) || err == syscall.EINTR {
+ if 0 < m && m < len(bcap) || err == syscall.EINTR {
+ b = b[m:]
+ continue
+ }
+
+ if needsMaxRW && len(bcap) != len(b) && err == nil {
b = b[m:]
continue
}
@@ -223,6 +242,9 @@ func (f *File) write(b []byte) (n int, err error) {
// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func (f *File) pwrite(b []byte, off int64) (n int, err error) {
+ if needsMaxRW && len(b) > maxRW {
+ b = b[:maxRW]
+ }
return syscall.Pwrite(f.fd, b, off)
}
diff --git a/libgo/go/os/getwd.go b/libgo/go/os/getwd.go
index 8c5ff7f..a72edea 100644
--- a/libgo/go/os/getwd.go
+++ b/libgo/go/os/getwd.go
@@ -22,7 +22,7 @@ var useSyscallwd = func(error) bool { return true }
// current directory. If the current directory can be
// reached via multiple paths (due to symbolic links),
// Getwd may return any one of them.
-func Getwd() (pwd string, err error) {
+func Getwd() (dir string, err error) {
// If the operating system provides a Getwd call, use it.
if syscall.ImplementsGetwd {
s, e := syscall.Getwd()
@@ -39,22 +39,22 @@ func Getwd() (pwd string, err error) {
// Clumsy but widespread kludge:
// if $PWD is set and matches ".", use it.
- pwd = Getenv("PWD")
- if len(pwd) > 0 && pwd[0] == '/' {
- d, err := Stat(pwd)
+ dir = Getenv("PWD")
+ if len(dir) > 0 && dir[0] == '/' {
+ d, err := Stat(dir)
if err == nil && SameFile(dot, d) {
- return pwd, nil
+ return dir, nil
}
}
// Apply same kludge but to cached dir instead of $PWD.
getwdCache.Lock()
- pwd = getwdCache.dir
+ dir = getwdCache.dir
getwdCache.Unlock()
- if len(pwd) > 0 {
- d, err := Stat(pwd)
+ if len(dir) > 0 {
+ d, err := Stat(dir)
if err == nil && SameFile(dot, d) {
- return pwd, nil
+ return dir, nil
}
}
@@ -71,8 +71,8 @@ func Getwd() (pwd string, err error) {
// General algorithm: find name in parent
// and then find name of parent. Each iteration
- // adds /name to the beginning of pwd.
- pwd = ""
+ // adds /name to the beginning of dir.
+ dir = ""
for parent := ".."; ; parent = "../" + parent {
if len(parent) >= 1024 { // Sanity check
return "", syscall.ENAMETOOLONG
@@ -91,7 +91,7 @@ func Getwd() (pwd string, err error) {
for _, name := range names {
d, _ := Lstat(parent + "/" + name)
if SameFile(d, dot) {
- pwd = "/" + name + pwd
+ dir = "/" + name + dir
goto Found
}
}
@@ -112,8 +112,8 @@ func Getwd() (pwd string, err error) {
// Save answer as hint to avoid the expensive path next time.
getwdCache.Lock()
- getwdCache.dir = pwd
+ getwdCache.dir = dir
getwdCache.Unlock()
- return pwd, nil
+ return dir, nil
}
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index 0392b06..a34e328 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -494,10 +494,10 @@ func TestHardLink(t *testing.T) {
}
}
-func TestSymLink(t *testing.T) {
- // Symlinks are not supported under windows or Plan 9.
- if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
- return
+func TestSymlink(t *testing.T) {
+ switch runtime.GOOS {
+ case "windows", "plan9", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
from, to := "symlinktestfrom", "symlinktestto"
Remove(from) // Just in case.
@@ -557,9 +557,9 @@ func TestSymLink(t *testing.T) {
}
func TestLongSymlink(t *testing.T) {
- // Symlinks are not supported under windows or Plan 9.
- if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
- return
+ switch runtime.GOOS {
+ case "windows", "plan9", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
s := "0123456789abcdef"
// Long, but not too long: a common limit is 255.
@@ -628,6 +628,10 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
}
func TestStartProcess(t *testing.T) {
+ if runtime.GOOS == "nacl" {
+ t.Skip("skipping on nacl")
+ }
+
var dir, cmd string
var args []string
if runtime.GOOS == "windows" {
@@ -701,8 +705,10 @@ func TestFTruncate(t *testing.T) {
checkSize(t, f, 1024)
f.Truncate(0)
checkSize(t, f, 0)
- f.Write([]byte("surprise!"))
- checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
+ _, err := f.Write([]byte("surprise!"))
+ if err == nil {
+ checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
+ }
}
func TestTruncate(t *testing.T) {
@@ -719,8 +725,10 @@ func TestTruncate(t *testing.T) {
checkSize(t, f, 1024)
Truncate(f.Name(), 0)
checkSize(t, f, 0)
- f.Write([]byte("surprise!"))
- checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
+ _, err := f.Write([]byte("surprise!"))
+ if err == nil {
+ checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
+ }
}
// Use TempDir() to make sure we're on a local file system,
@@ -755,13 +763,13 @@ func TestChtimes(t *testing.T) {
}
postStat := st
- /* Plan 9:
+ /* Plan 9, NaCl:
Mtime is the time of the last change of content. Similarly, atime is set whenever the
contents are accessed; also, it is set whenever mtime is set.
*/
pat := Atime(postStat)
pmt := postStat.ModTime()
- if !pat.Before(at) && runtime.GOOS != "plan9" {
+ if !pat.Before(at) && runtime.GOOS != "plan9" && runtime.GOOS != "nacl" {
t.Errorf("AccessTime didn't go backwards; was=%d, after=%d", at, pat)
}
@@ -963,8 +971,9 @@ func run(t *testing.T, cmd []string) string {
func TestHostname(t *testing.T) {
// There is no other way to fetch hostname on windows, but via winapi.
// On Plan 9 it is can be taken from #c/sysname as Hostname() does.
- if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
- return
+ switch runtime.GOOS {
+ case "windows", "plan9", "nacl":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
// Check internal Hostname() against the output of /bin/hostname.
@@ -1224,6 +1233,10 @@ func TestReadAtEOF(t *testing.T) {
func testKillProcess(t *testing.T, processKiller func(p *Process)) {
t.Skip("gccgo does not have a go command")
+ if runtime.GOOS == "nacl" {
+ t.Skip("skipping on nacl")
+ }
+
dir, err := ioutil.TempDir("", "go-build")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go
index 27abf59..3af21cd 100644
--- a/libgo/go/os/path_test.go
+++ b/libgo/go/os/path_test.go
@@ -167,8 +167,9 @@ func TestRemoveAll(t *testing.T) {
}
func TestMkdirAllWithSymlink(t *testing.T) {
- if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
- t.Skip("Skipping test: symlinks don't exist under Windows/Plan 9")
+ switch runtime.GOOS {
+ case "nacl", "plan9", "windows":
+ t.Skipf("skipping on %s", runtime.GOOS)
}
tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
diff --git a/libgo/go/os/path_unix.go b/libgo/go/os/path_unix.go
index bdf9fe6..0211107 100644
--- a/libgo/go/os/path_unix.go
+++ b/libgo/go/os/path_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os
diff --git a/libgo/go/os/pipe_bsd.go b/libgo/go/os/pipe_bsd.go
index 0ea8e4b..3b81ed2 100644
--- a/libgo/go/os/pipe_bsd.go
+++ b/libgo/go/os/pipe_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd netbsd openbsd solaris
+// +build darwin dragonfly freebsd nacl netbsd openbsd solaris
package os
diff --git a/libgo/go/os/signal/signal_unix.go b/libgo/go/os/signal/signal_unix.go
index 80dc430..94b8ab3 100644
--- a/libgo/go/os/signal/signal_unix.go
+++ b/libgo/go/os/signal/signal_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package signal
diff --git a/libgo/go/os/stat_nacl.go b/libgo/go/os/stat_nacl.go
new file mode 100644
index 0000000..a503b59
--- /dev/null
+++ b/libgo/go/os/stat_nacl.go
@@ -0,0 +1,62 @@
+// 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"
+ "time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+ stat1 := fs1.sys.(*syscall.Stat_t)
+ stat2 := fs2.sys.(*syscall.Stat_t)
+ return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+ fs := &fileStat{
+ name: basename(name),
+ size: int64(st.Size),
+ modTime: timespecToTime(st.Mtime, st.MtimeNsec),
+ sys: st,
+ }
+ fs.mode = FileMode(st.Mode & 0777)
+ switch st.Mode & syscall.S_IFMT {
+ case syscall.S_IFBLK:
+ fs.mode |= ModeDevice
+ case syscall.S_IFCHR:
+ fs.mode |= ModeDevice | ModeCharDevice
+ case syscall.S_IFDIR:
+ fs.mode |= ModeDir
+ case syscall.S_IFIFO:
+ fs.mode |= ModeNamedPipe
+ case syscall.S_IFLNK:
+ fs.mode |= ModeSymlink
+ case syscall.S_IFREG:
+ // nothing to do
+ case syscall.S_IFSOCK:
+ fs.mode |= ModeSocket
+ }
+ if st.Mode&syscall.S_ISGID != 0 {
+ fs.mode |= ModeSetgid
+ }
+ if st.Mode&syscall.S_ISUID != 0 {
+ fs.mode |= ModeSetuid
+ }
+ if st.Mode&syscall.S_ISVTX != 0 {
+ fs.mode |= ModeSticky
+ }
+ return fs
+}
+
+func timespecToTime(sec, nsec int64) time.Time {
+ return time.Unix(sec, nsec)
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+ st := fi.Sys().(*syscall.Stat_t)
+ return timespecToTime(st.Atime, st.AtimeNsec)
+}
diff --git a/libgo/go/os/sys_bsd.go b/libgo/go/os/sys_bsd.go
index 9ad2f85..8ad5e21 100644
--- a/libgo/go/os/sys_bsd.go
+++ b/libgo/go/os/sys_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd netbsd openbsd
+// +build darwin dragonfly freebsd nacl netbsd openbsd
// os code shared between *BSD systems including OS X (Darwin)
// and FreeBSD.
diff --git a/libgo/go/os/sys_darwin.go b/libgo/go/os/sys_darwin.go
new file mode 100644
index 0000000..7a8330a
--- /dev/null
+++ b/libgo/go/os/sys_darwin.go
@@ -0,0 +1,31 @@
+// Copyright 2014 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"
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+var supportsCloseOnExec bool
+
+func init() {
+ // Seems like kern.osreldate is veiled on latest OS X. We use
+ // kern.osrelease instead.
+ osver, err := syscall.Sysctl("kern.osrelease")
+ if err != nil {
+ return
+ }
+ var i int
+ for i = range osver {
+ if osver[i] != '.' {
+ continue
+ }
+ }
+ // The O_CLOEXEC flag was introduced in OS X 10.7 (Darwin
+ // 11.0.0). See http://support.apple.com/kb/HT1633.
+ if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '1' {
+ supportsCloseOnExec = true
+ }
+}
diff --git a/libgo/go/os/sys_freebsd.go b/libgo/go/os/sys_freebsd.go
new file mode 100644
index 0000000..273c2df
--- /dev/null
+++ b/libgo/go/os/sys_freebsd.go
@@ -0,0 +1,23 @@
+// Copyright 2014 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"
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+var supportsCloseOnExec bool
+
+func init() {
+ osrel, err := syscall.SysctlUint32("kern.osreldate")
+ if err != nil {
+ return
+ }
+ // The O_CLOEXEC flag was introduced in FreeBSD 8.3.
+ // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
+ if osrel >= 803000 {
+ supportsCloseOnExec = true
+ }
+}
diff --git a/libgo/go/os/sys_nacl.go b/libgo/go/os/sys_nacl.go
new file mode 100644
index 0000000..07907c8
--- /dev/null
+++ b/libgo/go/os/sys_nacl.go
@@ -0,0 +1,9 @@
+// Copyright 2014 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
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+const supportsCloseOnExec = false
diff --git a/libgo/go/os/sys_unix.go b/libgo/go/os/sys_unix.go
new file mode 100644
index 0000000..39c20dc
--- /dev/null
+++ b/libgo/go/os/sys_unix.go
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+// +build dragonfly linux netbsd openbsd solaris
+
+package os
+
+// supportsCloseOnExec reports whether the platform supports the
+// O_CLOEXEC flag.
+const supportsCloseOnExec = true