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.
13 var getwdCache
struct {
18 // useSyscallwd determines whether to use the return value of
19 // syscall.Getwd based on its error.
20 var useSyscallwd
= func(error
) bool { return true }
22 // Getwd returns a rooted path name corresponding to the
23 // current directory. If the current directory can be
24 // reached via multiple paths (due to symbolic links),
25 // Getwd may return any one of them.
26 func Getwd() (dir
string, err error
) {
27 if runtime
.GOOS
== "windows" {
28 return syscall
.Getwd()
31 // Clumsy but widespread kludge:
32 // if $PWD is set and matches ".", use it.
38 if len(dir
) > 0 && dir
[0] == '/' {
40 if err
== nil && SameFile(dot
, d
) {
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()
50 return s
, NewSyscallError("getwd", e
)
54 // Apply same kludge but to cached dir instead of $PWD.
60 if err
== nil && SameFile(dot
, d
) {
65 // Root is a special case because it has no parent
66 // and ends in a slash.
67 root
, err
:= Stat("/")
69 // Can't stat root - no hope.
72 if SameFile(root
, dot
) {
76 // General algorithm: find name in parent
77 // and then find name of parent. Each iteration
78 // adds /name to the beginning of dir.
80 for parent
:= ".."; ; parent
= "../" + parent
{
81 if len(parent
) >= 1024 { // Sanity check
82 return "", syscall
.ENAMETOOLONG
84 fd
, err
:= Open(parent
)
90 names
, err
:= fd
.Readdirnames(100)
95 for _
, name
:= range names
{
96 d
, _
:= Lstat(parent
+ "/" + name
)
98 dir
= "/" + name
+ dir
110 if SameFile(pd
, root
) {
113 // Set up for next round.
117 // Save answer as hint to avoid the expensive path next time.