Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package os

import (
	
	
	
)

var getwdCache struct {
	sync.Mutex
	dir string
}
Getwd returns a rooted path name corresponding to the current directory. If the current directory can be reached via multiple paths (due to symbolic links), Getwd may return any one of them.
func () ( string,  error) {
	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
		return syscall.Getwd()
	}
Clumsy but widespread kludge: if $PWD is set and matches ".", use it.
	,  := statNolog(".")
	if  != nil {
		return "", 
	}
	 = Getenv("PWD")
	if len() > 0 && [0] == '/' {
		,  := statNolog()
		if  == nil && SameFile(, ) {
			return , nil
		}
	}
If the operating system provides a Getwd call, use it. Otherwise, we're trying to find our way back to ".".
	if syscall.ImplementsGetwd {
		var (
			 string
			 error
		)
		for {
			,  = syscall.Getwd()
			if  != syscall.EINTR {
				break
			}
		}
		return , NewSyscallError("getwd", )
	}
Apply same kludge but to cached dir instead of $PWD.
	getwdCache.Lock()
	 = getwdCache.dir
	getwdCache.Unlock()
	if len() > 0 {
		,  := statNolog()
		if  == nil && SameFile(, ) {
			return , nil
		}
	}
Root is a special case because it has no parent and ends in a slash.
	,  := statNolog("/")
Can't stat root - no hope.
		return "", 
	}
	if SameFile(, ) {
		return "/", nil
	}
General algorithm: find name in parent and then find name of parent. Each iteration adds /name to the beginning of dir.
	 = ""
	for  := ".."; ;  = "../" +  {
		if len() >= 1024 { // Sanity check
			return "", syscall.ENAMETOOLONG
		}
		,  := openFileNolog(, O_RDONLY, 0)
		if  != nil {
			return "", 
		}

		for {
			,  := .Readdirnames(100)
			if  != nil {
				.Close()
				return "", 
			}
			for ,  := range  {
				,  := lstatNolog( + "/" + )
				if SameFile(, ) {
					 = "/" +  + 
					goto 
				}
			}
		}

	:
		,  := .Stat()
		.Close()
		if  != nil {
			return "", 
		}
		if SameFile(, ) {
			break
Set up for next round.
		 = 
	}
Save answer as hint to avoid the expensive path next time.