OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package os | 5 package os |
6 | 6 |
7 import ( | 7 import ( |
| 8 "runtime" |
8 "sync" | 9 "sync" |
9 "syscall" | 10 "syscall" |
10 ) | 11 ) |
11 | 12 |
12 var getwdCache struct { | 13 var getwdCache struct { |
13 sync.Mutex | 14 sync.Mutex |
14 dir string | 15 dir string |
15 } | 16 } |
16 | 17 |
17 // useSyscallwd determines whether to use the return value of | 18 // useSyscallwd determines whether to use the return value of |
18 // syscall.Getwd based on its error. | 19 // syscall.Getwd based on its error. |
19 var useSyscallwd = func(error) bool { return true } | 20 var useSyscallwd = func(error) bool { return true } |
20 | 21 |
21 // Getwd returns a rooted path name corresponding to the | 22 // Getwd returns a rooted path name corresponding to the |
22 // current directory. If the current directory can be | 23 // current directory. If the current directory can be |
23 // reached via multiple paths (due to symbolic links), | 24 // reached via multiple paths (due to symbolic links), |
24 // Getwd may return any one of them. | 25 // Getwd may return any one of them. |
25 func Getwd() (dir string, err error) { | 26 func Getwd() (dir string, err error) { |
26 » // If the operating system provides a Getwd call, use it. | 27 » if runtime.GOOS == "windows" { |
27 » if syscall.ImplementsGetwd { | 28 » » return syscall.Getwd() |
28 » » s, e := syscall.Getwd() | |
29 » » if useSyscallwd(e) { | |
30 » » » return s, NewSyscallError("getwd", e) | |
31 » » } | |
32 } | 29 } |
33 | 30 |
34 » // Otherwise, we're trying to find our way back to ".". | 31 » // Clumsy but widespread kludge: |
| 32 » // if $PWD is set and matches ".", use it. |
35 dot, err := Stat(".") | 33 dot, err := Stat(".") |
36 if err != nil { | 34 if err != nil { |
37 return "", err | 35 return "", err |
38 } | 36 } |
39 | |
40 // Clumsy but widespread kludge: | |
41 // if $PWD is set and matches ".", use it. | |
42 dir = Getenv("PWD") | 37 dir = Getenv("PWD") |
43 if len(dir) > 0 && dir[0] == '/' { | 38 if len(dir) > 0 && dir[0] == '/' { |
44 d, err := Stat(dir) | 39 d, err := Stat(dir) |
45 if err == nil && SameFile(dot, d) { | 40 if err == nil && SameFile(dot, d) { |
46 return dir, nil | 41 return dir, nil |
47 } | 42 } |
48 } | 43 } |
49 | 44 |
| 45 // If the operating system provides a Getwd call, use it. |
| 46 // Otherwise, we're trying to find our way back to ".". |
| 47 if syscall.ImplementsGetwd { |
| 48 s, e := syscall.Getwd() |
| 49 if useSyscallwd(e) { |
| 50 return s, NewSyscallError("getwd", e) |
| 51 } |
| 52 } |
| 53 |
50 // Apply same kludge but to cached dir instead of $PWD. | 54 // Apply same kludge but to cached dir instead of $PWD. |
51 getwdCache.Lock() | 55 getwdCache.Lock() |
52 dir = getwdCache.dir | 56 dir = getwdCache.dir |
53 getwdCache.Unlock() | 57 getwdCache.Unlock() |
54 if len(dir) > 0 { | 58 if len(dir) > 0 { |
55 d, err := Stat(dir) | 59 d, err := Stat(dir) |
56 if err == nil && SameFile(dot, d) { | 60 if err == nil && SameFile(dot, d) { |
57 return dir, nil | 61 return dir, nil |
58 } | 62 } |
59 } | 63 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 dot = pd | 114 dot = pd |
111 } | 115 } |
112 | 116 |
113 // Save answer as hint to avoid the expensive path next time. | 117 // Save answer as hint to avoid the expensive path next time. |
114 getwdCache.Lock() | 118 getwdCache.Lock() |
115 getwdCache.dir = dir | 119 getwdCache.dir = dir |
116 getwdCache.Unlock() | 120 getwdCache.Unlock() |
117 | 121 |
118 return dir, nil | 122 return dir, nil |
119 } | 123 } |
OLD | NEW |