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 // Getwd returns a rooted path name corresponding to the
18 // current directory. If the current directory can be
19 // reached via multiple paths (due to symbolic links),
20 // Getwd may return any one of them.
21 func Getwd() (pwd string, err error) {
22 // If the operating system provides a Getwd call, use it.
23 if syscall.ImplementsGetwd {
24 s, e := syscall.Getwd()
25 return s, NewSyscallError("getwd", e)
28 // Otherwise, we're trying to find our way back to ".".
34 // Clumsy but widespread kludge:
35 // if $PWD is set and matches ".", use it.
37 if len(pwd) > 0 && pwd[0] == '/' {
39 if err == nil && SameFile(dot, d) {
44 // Apply same kludge but to cached dir instead of $PWD.
50 if err == nil && SameFile(dot, d) {
55 // Root is a special case because it has no parent
56 // and ends in a slash.
57 root, err := Stat("/")
59 // Can't stat root - no hope.
62 if SameFile(root, dot) {
66 // General algorithm: find name in parent
67 // and then find name of parent. Each iteration
68 // adds /name to the beginning of pwd.
70 for parent := ".."; ; parent = "../" + parent {
71 if len(parent) >= 1024 { // Sanity check
72 return "", syscall.ENAMETOOLONG
74 fd, err := Open(parent)
80 names, err := fd.Readdirnames(100)
85 for _, name := range names {
86 d, _ := Lstat(parent + "/" + name)
88 pwd = "/" + name + pwd
100 if SameFile(pd, root) {
103 // Set up for next round.
107 // Save answer as hint to avoid the expensive path next time.