diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2014-07-19 08:53:52 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2014-07-19 08:53:52 +0000 |
commit | 00d86ac99f5dd6afa5bbd7c38ffe1c585edd2387 (patch) | |
tree | b988e32ea14a3dc1b4718b1fdfa47bab087ae96c /libgo/go/os | |
parent | bcf2fc6ee0a7edbe7de4299f28b66527c07bb0a2 (diff) | |
download | gcc-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.go | 2 | ||||
-rw-r--r-- | libgo/go/os/doc.go | 3 | ||||
-rw-r--r-- | libgo/go/os/error_unix.go | 2 | ||||
-rw-r--r-- | libgo/go/os/exec/exec.go | 56 | ||||
-rw-r--r-- | libgo/go/os/exec/exec_test.go | 81 | ||||
-rw-r--r-- | libgo/go/os/exec/lp_unix.go | 2 | ||||
-rw-r--r-- | libgo/go/os/exec_plan9.go | 9 | ||||
-rw-r--r-- | libgo/go/os/exec_posix.go | 2 | ||||
-rw-r--r-- | libgo/go/os/exec_unix.go | 5 | ||||
-rw-r--r-- | libgo/go/os/file_posix.go | 2 | ||||
-rw-r--r-- | libgo/go/os/file_unix.go | 42 | ||||
-rw-r--r-- | libgo/go/os/getwd.go | 28 | ||||
-rw-r--r-- | libgo/go/os/os_test.go | 43 | ||||
-rw-r--r-- | libgo/go/os/path_test.go | 5 | ||||
-rw-r--r-- | libgo/go/os/path_unix.go | 2 | ||||
-rw-r--r-- | libgo/go/os/pipe_bsd.go | 2 | ||||
-rw-r--r-- | libgo/go/os/signal/signal_unix.go | 2 | ||||
-rw-r--r-- | libgo/go/os/stat_nacl.go | 62 | ||||
-rw-r--r-- | libgo/go/os/sys_bsd.go | 2 | ||||
-rw-r--r-- | libgo/go/os/sys_darwin.go | 31 | ||||
-rw-r--r-- | libgo/go/os/sys_freebsd.go | 23 | ||||
-rw-r--r-- | libgo/go/os/sys_nacl.go | 9 | ||||
-rw-r--r-- | libgo/go/os/sys_unix.go | 11 |
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 |