Source file
src/os/getwd.go
1
2
3
4
5 package os
6
7 import (
8 "runtime"
9 "sync"
10 "syscall"
11 )
12
13 var getwdCache struct {
14 sync.Mutex
15 dir string
16 }
17
18
19
20
21
22
23
24
25
26 func Getwd() (dir string, err error) {
27 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
28
29
30
31
32 dir, err = syscall.Getwd()
33 return dir, NewSyscallError("getwd", err)
34 }
35
36
37
38 var dot FileInfo
39 dir = Getenv("PWD")
40 if len(dir) > 0 && dir[0] == '/' {
41 dot, err = statNolog(".")
42 if err != nil {
43 return "", err
44 }
45 d, err := statNolog(dir)
46 if err == nil && SameFile(dot, d) {
47 return dir, nil
48 }
49
50
51
52 }
53
54
55 if syscall.ImplementsGetwd {
56 dir, err = ignoringEINTR2(syscall.Getwd)
57
58
59
60
61 if err != syscall.ENAMETOOLONG && err != syscall.EINVAL && err != errERANGE && err != errENOMEM {
62 return dir, NewSyscallError("getwd", err)
63 }
64 }
65
66
67 if dot == nil {
68 dot, err = statNolog(".")
69 if err != nil {
70 return "", err
71 }
72 }
73
74 getwdCache.Lock()
75 dir = getwdCache.dir
76 getwdCache.Unlock()
77 if len(dir) > 0 {
78 d, err := statNolog(dir)
79 if err == nil && SameFile(dot, d) {
80 return dir, nil
81 }
82 }
83
84
85
86 root, err := statNolog("/")
87 if err != nil {
88
89 return "", err
90 }
91 if SameFile(root, dot) {
92 return "/", nil
93 }
94
95
96
97
98 dir = ""
99 for parent := ".."; ; parent = "../" + parent {
100 if len(parent) >= 1024 {
101 return "", NewSyscallError("getwd", syscall.ENAMETOOLONG)
102 }
103 fd, err := openDirNolog(parent)
104 if err != nil {
105 return "", err
106 }
107
108 for {
109 names, err := fd.Readdirnames(100)
110 if err != nil {
111 fd.Close()
112
113
114
115
116 if syscall.ImplementsGetwd {
117 return "", NewSyscallError("getwd", syscall.ENAMETOOLONG)
118 }
119 return "", NewSyscallError("getwd", errENOSYS)
120 }
121 for _, name := range names {
122 d, _ := lstatNolog(parent + "/" + name)
123 if SameFile(d, dot) {
124 dir = "/" + name + dir
125 goto Found
126 }
127 }
128 }
129
130 Found:
131 pd, err := fd.Stat()
132 fd.Close()
133 if err != nil {
134 return "", err
135 }
136 if SameFile(pd, root) {
137 break
138 }
139
140 dot = pd
141 }
142
143
144 getwdCache.Lock()
145 getwdCache.dir = dir
146 getwdCache.Unlock()
147
148 return dir, nil
149 }
150
View as plain text