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 for {
57 dir, err = syscall.Getwd()
58 if err != syscall.EINTR {
59 break
60 }
61 }
62
63
64
65
66 if err != syscall.ENAMETOOLONG && err != syscall.EINVAL && err != errERANGE && err != errENOMEM {
67 return dir, NewSyscallError("getwd", err)
68 }
69 }
70
71
72 if dot == nil {
73 dot, err = statNolog(".")
74 if err != nil {
75 return "", err
76 }
77 }
78
79 getwdCache.Lock()
80 dir = getwdCache.dir
81 getwdCache.Unlock()
82 if len(dir) > 0 {
83 d, err := statNolog(dir)
84 if err == nil && SameFile(dot, d) {
85 return dir, nil
86 }
87 }
88
89
90
91 root, err := statNolog("/")
92 if err != nil {
93
94 return "", err
95 }
96 if SameFile(root, dot) {
97 return "/", nil
98 }
99
100
101
102
103 dir = ""
104 for parent := ".."; ; parent = "../" + parent {
105 if len(parent) >= 1024 {
106 return "", NewSyscallError("getwd", syscall.ENAMETOOLONG)
107 }
108 fd, err := openDirNolog(parent)
109 if err != nil {
110 return "", err
111 }
112
113 for {
114 names, err := fd.Readdirnames(100)
115 if err != nil {
116 fd.Close()
117
118
119
120
121 if syscall.ImplementsGetwd {
122 return "", NewSyscallError("getwd", syscall.ENAMETOOLONG)
123 }
124 return "", NewSyscallError("getwd", errENOSYS)
125 }
126 for _, name := range names {
127 d, _ := lstatNolog(parent + "/" + name)
128 if SameFile(d, dot) {
129 dir = "/" + name + dir
130 goto Found
131 }
132 }
133 }
134
135 Found:
136 pd, err := fd.Stat()
137 fd.Close()
138 if err != nil {
139 return "", err
140 }
141 if SameFile(pd, root) {
142 break
143 }
144
145 dot = pd
146 }
147
148
149 getwdCache.Lock()
150 getwdCache.dir = dir
151 getwdCache.Unlock()
152
153 return dir, nil
154 }
155
View as plain text