github.com/dara-project/godist@v0.0.0-20200823115410-e0c80c8f0c78/src/os/getwd.go (about) 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. 4 5 package os 6 7 import ( 8 "dara" 9 "runtime" 10 "sync" 11 "syscall" 12 ) 13 14 var getwdCache struct { 15 sync.Mutex 16 dir string 17 } 18 19 // useSyscallwd determines whether to use the return value of 20 // syscall.Getwd based on its error. 21 var useSyscallwd = func(error) bool { return true } 22 23 // Getwd returns a rooted path name corresponding to the 24 // current directory. If the current directory can be 25 // reached via multiple paths (due to symbolic links), 26 // Getwd may return any one of them. 27 func Getwd() (dir string, err error) { 28 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { 29 dir, err = syscall.Getwd() 30 // DARA Instrumentation 31 if runtime.Is_dara_profiling_on() { 32 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 33 retInfo1 := dara.GeneralType{Type: dara.STRING} 34 copy(retInfo1.String[:], dir) 35 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 36 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 37 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 38 } 39 return dir, err 40 } 41 42 // Clumsy but widespread kludge: 43 // if $PWD is set and matches ".", use it. 44 dot, err := statNolog(".") 45 if err != nil { 46 // DARA Instrumentation 47 if runtime.Is_dara_profiling_on() { 48 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 49 retInfo1 := dara.GeneralType{Type: dara.STRING} 50 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 51 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 52 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 53 } 54 return "", err 55 } 56 dir = Getenv("PWD") 57 if len(dir) > 0 && dir[0] == '/' { 58 d, err := statNolog(dir) 59 if err == nil && SameFile(dot, d) { 60 // DARA Instrumentation 61 if runtime.Is_dara_profiling_on() { 62 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 63 retInfo1 := dara.GeneralType{Type: dara.STRING} 64 copy(retInfo1.String[:], dir) 65 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 66 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 67 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 68 } 69 return dir, nil 70 } 71 } 72 73 // If the operating system provides a Getwd call, use it. 74 // Otherwise, we're trying to find our way back to ".". 75 if syscall.ImplementsGetwd { 76 s, e := syscall.Getwd() 77 if useSyscallwd(e) { 78 // DARA Instrumentation 79 if runtime.Is_dara_profiling_on() { 80 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 81 retInfo1 := dara.GeneralType{Type: dara.STRING} 82 copy(retInfo1.String[:], s) 83 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 84 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 85 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 86 } 87 return s, NewSyscallError("getwd", e) 88 } 89 } 90 91 // Apply same kludge but to cached dir instead of $PWD. 92 getwdCache.Lock() 93 dir = getwdCache.dir 94 getwdCache.Unlock() 95 if len(dir) > 0 { 96 d, err := statNolog(dir) 97 if err == nil && SameFile(dot, d) { 98 // DARA Instrumentation 99 if runtime.Is_dara_profiling_on() { 100 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 101 retInfo1 := dara.GeneralType{Type: dara.STRING} 102 copy(retInfo1.String[:], dir) 103 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 104 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 105 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 106 } 107 return dir, nil 108 } 109 } 110 111 // Root is a special case because it has no parent 112 // and ends in a slash. 113 root, err := statNolog("/") 114 if err != nil { 115 // Can't stat root - no hope. 116 // DARA Instrumentation 117 if runtime.Is_dara_profiling_on() { 118 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 119 retInfo1 := dara.GeneralType{Type: dara.STRING} 120 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 121 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 122 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 123 } 124 return "", err 125 } 126 if SameFile(root, dot) { 127 // DARA Instrumentation 128 if runtime.Is_dara_profiling_on() { 129 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 130 retInfo1 := dara.GeneralType{Type: dara.STRING} 131 copy(retInfo1.String[:], "/") 132 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 133 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 134 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 135 } 136 return "/", nil 137 } 138 139 // General algorithm: find name in parent 140 // and then find name of parent. Each iteration 141 // adds /name to the beginning of dir. 142 dir = "" 143 for parent := ".."; ; parent = "../" + parent { 144 if len(parent) >= 1024 { // Sanity check 145 // DARA Instrumentation 146 if runtime.Is_dara_profiling_on() { 147 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 148 retInfo1 := dara.GeneralType{Type: dara.STRING} 149 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 150 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 151 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 152 } 153 return "", syscall.ENAMETOOLONG 154 } 155 fd, err := openFileNolog(parent, O_RDONLY, 0) 156 if err != nil { 157 // DARA Instrumentation 158 if runtime.Is_dara_profiling_on() { 159 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 160 retInfo1 := dara.GeneralType{Type: dara.STRING} 161 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 162 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 163 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 164 } 165 return "", err 166 } 167 168 for { 169 names, err := fd.Readdirnames(100) 170 if err != nil { 171 fd.Close() 172 // DARA Instrumentation 173 if runtime.Is_dara_profiling_on() { 174 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 175 retInfo1 := dara.GeneralType{Type: dara.STRING} 176 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 177 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 178 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 179 } 180 return "", err 181 } 182 for _, name := range names { 183 d, _ := lstatNolog(parent + "/" + name) 184 if SameFile(d, dot) { 185 dir = "/" + name + dir 186 goto Found 187 } 188 } 189 } 190 191 Found: 192 pd, err := fd.Stat() 193 if err != nil { 194 // DARA Instrumentation 195 if runtime.Is_dara_profiling_on() { 196 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 197 retInfo1 := dara.GeneralType{Type: dara.STRING} 198 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 199 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 200 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 201 } 202 return "", err 203 } 204 fd.Close() 205 if SameFile(pd, root) { 206 break 207 } 208 // Set up for next round. 209 dot = pd 210 } 211 212 // Save answer as hint to avoid the expensive path next time. 213 getwdCache.Lock() 214 getwdCache.dir = dir 215 getwdCache.Unlock() 216 217 // DARA Instrumentation 218 if runtime.Is_dara_profiling_on() { 219 runtime.Dara_Debug_Print(func() { println("[GETWD]") }) 220 retInfo1 := dara.GeneralType{Type: dara.STRING} 221 copy(retInfo1.String[:], dir) 222 retInfo2 := dara.GeneralType{Type: dara.ERROR, Unsupported: dara.UNSUPPORTEDVAL} 223 syscallInfo := dara.GeneralSyscall{dara.DSYS_GETWD, 0, 2, [10]dara.GeneralType{}, [10]dara.GeneralType{retInfo1, retInfo2}} 224 runtime.Report_Syscall_To_Scheduler(dara.DSYS_GETWD, syscallInfo) 225 } 226 return dir, nil 227 }