1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 var getwdCache
struct {
17 // useSyscallwd determines whether to use the return value of
18 // syscall.Getwd based on its error.
19 var useSyscallwd
= func(error
) bool { return true }
21 // Getwd returns a rooted path name corresponding to the
22 // current directory. If the current directory can be
23 // reached via multiple paths (due to symbolic links),
24 // Getwd may return any one of them.
25 func Getwd() (pwd
string, err error
) {
26 // If the operating system provides a Getwd call, use it.
27 if syscall
.ImplementsGetwd
{
28 s
, e
:= syscall
.Getwd()
30 return s
, NewSyscallError("getwd", e
)
34 // Otherwise, we're trying to find our way back to ".".
40 // Clumsy but widespread kludge:
41 // if $PWD is set and matches ".", use it.
43 if len(pwd
) > 0 && pwd
[0] == '/' {
45 if err
== nil && SameFile(dot
, d
) {
50 // Apply same kludge but to cached dir instead of $PWD.
56 if err
== nil && SameFile(dot
, d
) {
61 // Root is a special case because it has no parent
62 // and ends in a slash.
63 root
, err
:= Stat("/")
65 // Can't stat root - no hope.
68 if SameFile(root
, dot
) {
72 // General algorithm: find name in parent
73 // and then find name of parent. Each iteration
74 // adds /name to the beginning of pwd.
76 for parent
:= ".."; ; parent
= "../" + parent
{
77 if len(parent
) >= 1024 { // Sanity check
78 return "", syscall
.ENAMETOOLONG
80 fd
, err
:= Open(parent
)
86 names
, err
:= fd
.Readdirnames(100)
91 for _
, name
:= range names
{
92 d
, _
:= Lstat(parent
+ "/" + name
)
94 pwd
= "/" + name
+ pwd
106 if SameFile(pd
, root
) {
109 // Set up for next round.
113 // Save answer as hint to avoid the expensive path next time.