Commit 6cee4d3e authored by Russ Cox's avatar Russ Cox

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
parent 689995a7
...@@ -23,22 +23,12 @@ var useSyscallwd = func(error) bool { return true } ...@@ -23,22 +23,12 @@ var useSyscallwd = func(error) bool { return true }
// reached via multiple paths (due to symbolic links), // reached via multiple paths (due to symbolic links),
// Getwd may return any one of them. // Getwd may return any one of them.
func Getwd() (dir string, err error) { func Getwd() (dir string, err error) {
// If the operating system provides a Getwd call, use it. // Clumsy but widespread kludge:
if syscall.ImplementsGetwd { // if $PWD is set and matches ".", use it.
s, e := syscall.Getwd()
if useSyscallwd(e) {
return s, NewSyscallError("getwd", e)
}
}
// Otherwise, we're trying to find our way back to ".".
dot, err := Stat(".") dot, err := Stat(".")
if err != nil { if err != nil {
return "", err return "", err
} }
// Clumsy but widespread kludge:
// if $PWD is set and matches ".", use it.
dir = Getenv("PWD") dir = Getenv("PWD")
if len(dir) > 0 && dir[0] == '/' { if len(dir) > 0 && dir[0] == '/' {
d, err := Stat(dir) d, err := Stat(dir)
...@@ -47,6 +37,15 @@ func Getwd() (dir string, err error) { ...@@ -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. // Apply same kludge but to cached dir instead of $PWD.
getwdCache.Lock() getwdCache.Lock()
dir = getwdCache.dir dir = getwdCache.dir
......
...@@ -811,8 +811,8 @@ func TestChdirAndGetwd(t *testing.T) { ...@@ -811,8 +811,8 @@ func TestChdirAndGetwd(t *testing.T) {
t.Fatalf("Open .: %s", err) t.Fatalf("Open .: %s", err)
} }
// These are chosen carefully not to be symlinks on a Mac // These are chosen carefully not to be symlinks on a Mac
// (unlike, say, /var, /etc, and /tmp). // (unlike, say, /var, /etc), except /tmp, which we handle below.
dirs := []string{"/", "/usr/bin"} dirs := []string{"/", "/usr/bin", "/tmp"}
// /usr/bin does not usually exist on Plan 9 or Android. // /usr/bin does not usually exist on Plan 9 or Android.
switch runtime.GOOS { switch runtime.GOOS {
case "android": case "android":
...@@ -820,6 +820,7 @@ func TestChdirAndGetwd(t *testing.T) { ...@@ -820,6 +820,7 @@ func TestChdirAndGetwd(t *testing.T) {
case "plan9": case "plan9":
dirs = []string{"/", "/usr"} dirs = []string{"/", "/usr"}
} }
oldwd := Getenv("PWD")
for mode := 0; mode < 2; mode++ { for mode := 0; mode < 2; mode++ {
for _, d := range dirs { for _, d := range dirs {
if mode == 0 { if mode == 0 {
...@@ -833,7 +834,11 @@ func TestChdirAndGetwd(t *testing.T) { ...@@ -833,7 +834,11 @@ func TestChdirAndGetwd(t *testing.T) {
err = fd1.Chdir() err = fd1.Chdir()
fd1.Close() fd1.Close()
} }
if d == "/tmp" {
Setenv("PWD", "/tmp")
}
pwd, err1 := Getwd() pwd, err1 := Getwd()
Setenv("PWD", oldwd)
err2 := fd.Chdir() err2 := fd.Chdir()
if err2 != nil { if err2 != nil {
// We changed the current directory and cannot go back. // We changed the current directory and cannot go back.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment