From 6cee4d3e8f52d4ab5ba2f97ca58f11d5e4c29fd4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 7 Aug 2014 08:58:25 -0400 Subject: [PATCH] os: in Getwd, $PWD override syscall.Getwd This makes os.Getwd mimic C getwd on OS X, and possibly other systems. The change on OS X was a regression from 1.2 to 1.3. Fixes #8400. LGTM=bradfitz R=iant, bradfitz CC=golang-codereviews https://golang.org/cl/118970043 --- src/pkg/os/getwd.go | 23 +++++++++++------------ src/pkg/os/os_test.go | 9 +++++++-- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/pkg/os/getwd.go b/src/pkg/os/getwd.go index a72edeaee6e..eacb414660a 100644 --- a/src/pkg/os/getwd.go +++ b/src/pkg/os/getwd.go @@ -23,22 +23,12 @@ var useSyscallwd = func(error) bool { return true } // reached via multiple paths (due to symbolic links), // Getwd may return any one of them. func Getwd() (dir string, err error) { - // If the operating system provides a Getwd call, use it. - if syscall.ImplementsGetwd { - s, e := syscall.Getwd() - if useSyscallwd(e) { - return s, NewSyscallError("getwd", e) - } - } - - // Otherwise, we're trying to find our way back to ".". + // Clumsy but widespread kludge: + // if $PWD is set and matches ".", use it. dot, err := Stat(".") if err != nil { return "", err } - - // Clumsy but widespread kludge: - // if $PWD is set and matches ".", use it. dir = Getenv("PWD") if len(dir) > 0 && dir[0] == '/' { d, err := Stat(dir) @@ -47,6 +37,15 @@ func Getwd() (dir string, err error) { } } + // If the operating system provides a Getwd call, use it. + // Otherwise, we're trying to find our way back to ".". + if syscall.ImplementsGetwd { + s, e := syscall.Getwd() + if useSyscallwd(e) { + return s, NewSyscallError("getwd", e) + } + } + // Apply same kludge but to cached dir instead of $PWD. getwdCache.Lock() dir = getwdCache.dir diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go index 2811f29f348..0224c9b01d6 100644 --- a/src/pkg/os/os_test.go +++ b/src/pkg/os/os_test.go @@ -811,8 +811,8 @@ func TestChdirAndGetwd(t *testing.T) { t.Fatalf("Open .: %s", err) } // These are chosen carefully not to be symlinks on a Mac - // (unlike, say, /var, /etc, and /tmp). - dirs := []string{"/", "/usr/bin"} + // (unlike, say, /var, /etc), except /tmp, which we handle below. + dirs := []string{"/", "/usr/bin", "/tmp"} // /usr/bin does not usually exist on Plan 9 or Android. switch runtime.GOOS { case "android": @@ -820,6 +820,7 @@ func TestChdirAndGetwd(t *testing.T) { case "plan9": dirs = []string{"/", "/usr"} } + oldwd := Getenv("PWD") for mode := 0; mode < 2; mode++ { for _, d := range dirs { if mode == 0 { @@ -833,7 +834,11 @@ func TestChdirAndGetwd(t *testing.T) { err = fd1.Chdir() fd1.Close() } + if d == "/tmp" { + Setenv("PWD", "/tmp") + } pwd, err1 := Getwd() + Setenv("PWD", oldwd) err2 := fd.Chdir() if err2 != nil { // We changed the current directory and cannot go back.