aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/os
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-01-17 14:20:29 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-01-17 14:20:29 +0000
commitc6d6367f848cfd8381aba41e035c5e7e873667c5 (patch)
treea218e98243463fc27f5053b4444e2544c63cd57a /libgo/go/os
parent9bff0086915f544fa648ea81131f035cb9ce79a4 (diff)
downloadgcc-c6d6367f848cfd8381aba41e035c5e7e873667c5.zip
gcc-c6d6367f848cfd8381aba41e035c5e7e873667c5.tar.gz
gcc-c6d6367f848cfd8381aba41e035c5e7e873667c5.tar.bz2
libgo: update to Go1.10beta2 release
Reviewed-on: https://go-review.googlesource.com/87897 From-SVN: r256794
Diffstat (limited to 'libgo/go/os')
-rw-r--r--libgo/go/os/env.go7
-rw-r--r--libgo/go/os/exec.go5
-rw-r--r--libgo/go/os/exec/exec_test.go13
-rw-r--r--libgo/go/os/executable_test.go2
-rw-r--r--libgo/go/os/file.go21
-rw-r--r--libgo/go/os/file_plan9.go8
-rw-r--r--libgo/go/os/file_unix.go10
-rw-r--r--libgo/go/os/getwd.go12
-rw-r--r--libgo/go/os/os_test.go20
-rw-r--r--libgo/go/os/path.go2
-rw-r--r--libgo/go/os/pipe_test.go85
-rw-r--r--libgo/go/os/stat.go69
-rw-r--r--libgo/go/os/stat_plan9.go14
-rw-r--r--libgo/go/os/stat_unix.go12
14 files changed, 178 insertions, 102 deletions
diff --git a/libgo/go/os/env.go b/libgo/go/os/env.go
index a03b8f6..4e0171f 100644
--- a/libgo/go/os/env.go
+++ b/libgo/go/os/env.go
@@ -6,7 +6,10 @@
package os
-import "syscall"
+import (
+ "internal/testlog"
+ "syscall"
+)
// Expand replaces ${var} or $var in the string based on the mapping function.
// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv).
@@ -78,6 +81,7 @@ func getShellName(s string) (string, int) {
// It returns the value, which will be empty if the variable is not present.
// To distinguish between an empty value and an unset value, use LookupEnv.
func Getenv(key string) string {
+ testlog.Getenv(key)
v, _ := syscall.Getenv(key)
return v
}
@@ -88,6 +92,7 @@ func Getenv(key string) string {
// Otherwise the returned value will be empty and the boolean will
// be false.
func LookupEnv(key string) (string, bool) {
+ testlog.Getenv(key)
return syscall.Getenv(key)
}
diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go
index 8a53e5d..b3f60b6 100644
--- a/libgo/go/os/exec.go
+++ b/libgo/go/os/exec.go
@@ -5,6 +5,7 @@
package os
import (
+ "internal/testlog"
"runtime"
"sync"
"sync/atomic"
@@ -84,13 +85,15 @@ func FindProcess(pid int) (*Process, error) {
}
// StartProcess starts a new process with the program, arguments and attributes
-// specified by name, argv and attr.
+// specified by name, argv and attr. The argv slice will become os.Args in the
+// new process, so it normally starts with the program name.
//
// StartProcess is a low-level interface. The os/exec package provides
// higher-level interfaces.
//
// If there is an error, it will be of type *PathError.
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
+ testlog.Open(name)
return startProcess(name, argv, attr)
}
diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go
index a877d8a..aa33570f 100644
--- a/libgo/go/os/exec/exec_test.go
+++ b/libgo/go/os/exec/exec_test.go
@@ -405,9 +405,15 @@ var testedAlreadyLeaked = false
// basefds returns the number of expected file descriptors
// to be present in a process at start.
-// stdin, stdout, stderr, epoll/kqueue
+// stdin, stdout, stderr, epoll/kqueue, maybe testlog
func basefds() uintptr {
- return os.Stderr.Fd() + 1
+ n := os.Stderr.Fd() + 1
+ for _, arg := range os.Args {
+ if strings.HasPrefix(arg, "-test.testlogfile=") {
+ n++
+ }
+ }
+ return n
}
func closeUnexpectedFds(t *testing.T, m string) {
@@ -1003,6 +1009,9 @@ func TestContext(t *testing.T) {
}
func TestContextCancel(t *testing.T) {
+ if testenv.Builder() == "windows-386-xp" {
+ t.Skipf("known to fail on Windows XP. Issue 17245")
+ }
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := helperCommandContext(t, ctx, "cat")
diff --git a/libgo/go/os/executable_test.go b/libgo/go/os/executable_test.go
index 7800844..4a9a883 100644
--- a/libgo/go/os/executable_test.go
+++ b/libgo/go/os/executable_test.go
@@ -17,7 +17,7 @@ import (
const executable_EnvVar = "OSTEST_OUTPUT_EXECPATH"
func TestExecutable(t *testing.T) {
- testenv.MustHaveExec(t) // will also execlude nacl, which doesn't support Executable anyway
+ testenv.MustHaveExec(t) // will also exclude nacl, which doesn't support Executable anyway
ep, err := os.Executable()
if err != nil {
t.Fatalf("Executable failed: %v", err)
diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go
index 542b074..c667421 100644
--- a/libgo/go/os/file.go
+++ b/libgo/go/os/file.go
@@ -39,6 +39,7 @@ package os
import (
"errors"
"internal/poll"
+ "internal/testlog"
"io"
"syscall"
"time"
@@ -207,7 +208,8 @@ func (f *File) WriteString(s string) (n int, err error) {
return f.Write([]byte(s))
}
-// Mkdir creates a new directory with the specified name and permission bits.
+// Mkdir creates a new directory with the specified name and permission
+// bits (before umask).
// If there is an error, it will be of type *PathError.
func Mkdir(name string, perm FileMode) error {
e := syscall.Mkdir(fixLongPath(name), syscallMode(perm))
@@ -228,8 +230,15 @@ func Mkdir(name string, perm FileMode) error {
// If there is an error, it will be of type *PathError.
func Chdir(dir string) error {
if e := syscall.Chdir(dir); e != nil {
+ testlog.Open(dir) // observe likely non-existent directory
return &PathError{"chdir", dir, e}
}
+ if log := testlog.Logger(); log != nil {
+ wd, err := Getwd()
+ if err == nil {
+ log.Chdir(wd)
+ }
+ }
return nil
}
@@ -250,6 +259,16 @@ func Create(name string) (*File, error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
+// 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 (before umask), if applicable. If successful,
+// methods on the returned File can be used for I/O.
+// If there is an error, it will be of type *PathError.
+func OpenFile(name string, flag int, perm FileMode) (*File, error) {
+ testlog.Open(name)
+ return openFileNolog(name, flag, perm)
+}
+
// lstat is overridden in tests.
var lstat = Lstat
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go
index e4f8fd9..7e28178 100644
--- a/libgo/go/os/file_plan9.go
+++ b/libgo/go/os/file_plan9.go
@@ -79,12 +79,8 @@ func syscallMode(i FileMode) (o uint32) {
return
}
-// 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.
-// If there is an error, it will be of type *PathError.
-func OpenFile(name string, flag int, perm FileMode) (*File, error) {
+// openFileNolog is the Plan 9 implementation of OpenFile.
+func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
var (
fd int
e error
diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index af9c37f9..67d2ee1 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -66,7 +66,7 @@ func (f *File) Fd() uintptr {
// opened in blocking mode. The File will continue to work,
// but any blocking operation will tie up a thread.
if f.nonblock {
- syscall.SetNonblock(f.pfd.Sysfd, false)
+ f.pfd.SetBlocking()
}
return uintptr(f.pfd.Sysfd)
@@ -152,12 +152,8 @@ func epipecheck(file *File, e error) {
// 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.
-// If there is an error, it will be of type *PathError.
-func OpenFile(name string, flag int, perm FileMode) (*File, error) {
+// openFileNolog is the Unix implementation of OpenFile.
+func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
chmod := false
if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
if _, err := Stat(name); IsNotExist(err) {
diff --git a/libgo/go/os/getwd.go b/libgo/go/os/getwd.go
index 4c3c0d9..87ad8eb 100644
--- a/libgo/go/os/getwd.go
+++ b/libgo/go/os/getwd.go
@@ -30,13 +30,13 @@ func Getwd() (dir string, err error) {
// Clumsy but widespread kludge:
// if $PWD is set and matches ".", use it.
- dot, err := Stat(".")
+ dot, err := statNolog(".")
if err != nil {
return "", err
}
dir = Getenv("PWD")
if len(dir) > 0 && dir[0] == '/' {
- d, err := Stat(dir)
+ d, err := statNolog(dir)
if err == nil && SameFile(dot, d) {
return dir, nil
}
@@ -56,7 +56,7 @@ func Getwd() (dir string, err error) {
dir = getwdCache.dir
getwdCache.Unlock()
if len(dir) > 0 {
- d, err := Stat(dir)
+ d, err := statNolog(dir)
if err == nil && SameFile(dot, d) {
return dir, nil
}
@@ -64,7 +64,7 @@ func Getwd() (dir string, err error) {
// Root is a special case because it has no parent
// and ends in a slash.
- root, err := Stat("/")
+ root, err := statNolog("/")
if err != nil {
// Can't stat root - no hope.
return "", err
@@ -81,7 +81,7 @@ func Getwd() (dir string, err error) {
if len(parent) >= 1024 { // Sanity check
return "", syscall.ENAMETOOLONG
}
- fd, err := Open(parent)
+ fd, err := openFileNolog(parent, O_RDONLY, 0)
if err != nil {
return "", err
}
@@ -93,7 +93,7 @@ func Getwd() (dir string, err error) {
return "", err
}
for _, name := range names {
- d, _ := Lstat(parent + "/" + name)
+ d, _ := lstatNolog(parent + "/" + name)
if SameFile(d, dot) {
dir = "/" + name + dir
goto Found
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index e1c5b45..8ed9252 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -1360,14 +1360,26 @@ func TestSeek(t *testing.T) {
{-1, io.SeekEnd, int64(len(data)) - 1},
{1 << 33, io.SeekStart, 1 << 33},
{1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
+
+ // Issue 21681, Windows 4G-1, etc:
+ {1<<32 - 1, io.SeekStart, 1<<32 - 1},
+ {0, io.SeekCurrent, 1<<32 - 1},
+ {2<<32 - 1, io.SeekStart, 2<<32 - 1},
+ {0, io.SeekCurrent, 2<<32 - 1},
}
for i, tt := range tests {
+ if runtime.GOOS == "nacl" && tt.out > 1<<30 {
+ t.Logf("skipping test case #%d on nacl; https://golang.org/issue/21728", i)
+ continue
+ }
off, err := f.Seek(tt.in, tt.whence)
if off != tt.out || err != nil {
- if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
- // Reiserfs rejects the big seeks.
- // https://golang.org/issue/91
- break
+ if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" {
+ mounts, _ := ioutil.ReadFile("/proc/mounts")
+ if strings.Contains(string(mounts), "reiserfs") {
+ // Reiserfs rejects the big seeks.
+ t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
+ }
}
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
}
diff --git a/libgo/go/os/path.go b/libgo/go/os/path.go
index 17c49c8..eb996e5 100644
--- a/libgo/go/os/path.go
+++ b/libgo/go/os/path.go
@@ -13,7 +13,7 @@ import (
// MkdirAll creates a directory named path,
// along with any necessary parents, and returns nil,
// or else returns an error.
-// The permission bits perm are used for all
+// The permission bits perm (before umask) are used for all
// directories that MkdirAll creates.
// If path is already a directory, MkdirAll does nothing
// and returns nil.
diff --git a/libgo/go/os/pipe_test.go b/libgo/go/os/pipe_test.go
index 9d79d84..aad6c27 100644
--- a/libgo/go/os/pipe_test.go
+++ b/libgo/go/os/pipe_test.go
@@ -10,6 +10,7 @@ package os_test
import (
"fmt"
"internal/testenv"
+ "io"
"io/ioutil"
"os"
osexec "os/exec"
@@ -17,6 +18,7 @@ import (
"runtime"
"strconv"
"strings"
+ "sync"
"syscall"
"testing"
"time"
@@ -220,3 +222,86 @@ func TestReadNonblockingFd(t *testing.T) {
t.Errorf("child process failed: %v", err)
}
}
+
+func TestCloseWithBlockingReadByNewFile(t *testing.T) {
+ var p [2]int
+ err := syscall.Pipe(p[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+ // os.NewFile returns a blocking mode file.
+ testCloseWithBlockingRead(t, os.NewFile(uintptr(p[0]), "reader"), os.NewFile(uintptr(p[1]), "writer"))
+}
+
+func TestCloseWithBlockingReadByFd(t *testing.T) {
+ r, w, err := os.Pipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Calling Fd will put the file into blocking mode.
+ _ = r.Fd()
+ testCloseWithBlockingRead(t, r, w)
+}
+
+// Test that we don't let a blocking read prevent a close.
+func testCloseWithBlockingRead(t *testing.T, r, w *os.File) {
+ defer r.Close()
+ defer w.Close()
+
+ c1, c2 := make(chan bool), make(chan bool)
+ var wg sync.WaitGroup
+
+ wg.Add(1)
+ go func(c chan bool) {
+ defer wg.Done()
+ // Give the other goroutine a chance to enter the Read
+ // or Write call. This is sloppy but the test will
+ // pass even if we close before the read/write.
+ time.Sleep(20 * time.Millisecond)
+
+ if err := r.Close(); err != nil {
+ t.Error(err)
+ }
+ close(c)
+ }(c1)
+
+ wg.Add(1)
+ go func(c chan bool) {
+ defer wg.Done()
+ var b [1]byte
+ _, err := r.Read(b[:])
+ close(c)
+ if err == nil {
+ t.Error("I/O on closed pipe unexpectedly succeeded")
+ }
+ if err != io.EOF {
+ t.Errorf("got %v, expected io.EOF", err)
+ }
+ }(c2)
+
+ for c1 != nil || c2 != nil {
+ select {
+ case <-c1:
+ c1 = nil
+ // r.Close has completed, but the blocking Read
+ // is hanging. Close the writer to unblock it.
+ w.Close()
+ case <-c2:
+ c2 = nil
+ case <-time.After(1 * time.Second):
+ switch {
+ case c1 != nil && c2 != nil:
+ t.Error("timed out waiting for Read and Close")
+ w.Close()
+ case c1 != nil:
+ t.Error("timed out waiting for Close")
+ case c2 != nil:
+ t.Error("timed out waiting for Read")
+ default:
+ t.Error("impossible case")
+ }
+ }
+ }
+
+ wg.Wait()
+}
diff --git a/libgo/go/os/stat.go b/libgo/go/os/stat.go
index 564215b..af66838 100644
--- a/libgo/go/os/stat.go
+++ b/libgo/go/os/stat.go
@@ -1,64 +1,23 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2017 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 !aix
-// +build !darwin
-// +build !freebsd
-// +build !linux
-// +build !netbsd
-// +build !openbsd
-// +build !solaris
-
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.Mtim),
- sys: st,
- }
- fs.mode = FileMode(st.Mode & 0777)
- switch st.Mode & syscall.S_IFMT {
- case syscall.S_IFBLK, syscall.S_IFCHR:
- fs.mode |= ModeDevice
- 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
- }
- return fs
-}
+import "internal/testlog"
-func timespecToTime(ts syscall.Timespec) time.Time {
- return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+// Stat returns a FileInfo describing the named file.
+// If there is an error, it will be of type *PathError.
+func Stat(name string) (FileInfo, error) {
+ testlog.Stat(name)
+ return statNolog(name)
}
-// For testing.
-func atime(fi FileInfo) time.Time {
- return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)
+// Lstat returns a FileInfo describing the named file.
+// If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link. Lstat makes no attempt to follow the link.
+// If there is an error, it will be of type *PathError.
+func Lstat(name string) (FileInfo, error) {
+ testlog.Stat(name)
+ return lstatNolog(name)
}
diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go
index 274d0d8..8057fd4 100644
--- a/libgo/go/os/stat_plan9.go
+++ b/libgo/go/os/stat_plan9.go
@@ -86,9 +86,8 @@ func dirstat(arg interface{}) (*syscall.Dir, error) {
return nil, &PathError{"stat", name, err}
}
-// Stat returns a FileInfo describing the named file.
-// If there is an error, it will be of type *PathError.
-func Stat(name string) (FileInfo, error) {
+// statNolog implements Stat for Plan 9.
+func statNolog(name string) (FileInfo, error) {
d, err := dirstat(name)
if err != nil {
return nil, err
@@ -96,12 +95,9 @@ func Stat(name string) (FileInfo, error) {
return fileInfoFromStat(d), nil
}
-// Lstat returns a FileInfo describing the named file.
-// If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link. Lstat makes no attempt to follow the link.
-// If there is an error, it will be of type *PathError.
-func Lstat(name string) (FileInfo, error) {
- return Stat(name)
+// lstatNolog implements Lstat for Plan 9.
+func lstatNolog(name string) (FileInfo, error) {
+ return statNolog(name)
}
// For testing.
diff --git a/libgo/go/os/stat_unix.go b/libgo/go/os/stat_unix.go
index 7855fba..bc5d06c 100644
--- a/libgo/go/os/stat_unix.go
+++ b/libgo/go/os/stat_unix.go
@@ -25,9 +25,8 @@ func (f *File) Stat() (FileInfo, error) {
return &fs, nil
}
-// Stat returns a FileInfo describing the named file.
-// If there is an error, it will be of type *PathError.
-func Stat(name string) (FileInfo, error) {
+// statNolog stats a file with no test logging.
+func statNolog(name string) (FileInfo, error) {
var fs fileStat
err := syscall.Stat(name, &fs.sys)
if err != nil {
@@ -37,11 +36,8 @@ func Stat(name string) (FileInfo, error) {
return &fs, nil
}
-// Lstat returns a FileInfo describing the named file.
-// If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link. Lstat makes no attempt to follow the link.
-// If there is an error, it will be of type *PathError.
-func Lstat(name string) (FileInfo, error) {
+// lstatNolog lstats a file with no test logging.
+func lstatNolog(name string) (FileInfo, error) {
var fs fileStat
err := syscall.Lstat(name, &fs.sys)
if err != nil {