github.com/gidoBOSSftw5731/go/src@v0.0.0-20210226122457-d24b0edbf019/syscall/pwd_plan9.go (about) 1 // Copyright 2015 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 // The working directory in Plan 9 is effectively per P, so different 6 // goroutines and even the same goroutine as it's rescheduled on 7 // different Ps can see different working directories. 8 // 9 // Instead, track a Go process-wide intent of the current working directory, 10 // and switch to it at important points. 11 12 package syscall 13 14 import "sync" 15 16 var ( 17 wdmu sync.Mutex // guards following 18 wdSet bool 19 wdStr string 20 ) 21 22 func Fixwd() { 23 wdmu.Lock() 24 defer wdmu.Unlock() 25 fixwdLocked() 26 } 27 28 func fixwdLocked() { 29 if !wdSet { 30 return 31 } 32 // always call chdir when getwd returns an error 33 wd, _ := getwd() 34 if wd == wdStr { 35 return 36 } 37 if err := chdir(wdStr); err != nil { 38 return 39 } 40 } 41 42 func fixwd(paths ...string) { 43 for _, path := range paths { 44 if path != "" && path[0] != '/' && path[0] != '#' { 45 Fixwd() 46 return 47 } 48 } 49 } 50 51 // goroutine-specific getwd 52 func getwd() (wd string, err error) { 53 fd, err := open(".", O_RDONLY) 54 if err != nil { 55 return "", err 56 } 57 defer Close(fd) 58 return Fd2path(fd) 59 } 60 61 func Getwd() (wd string, err error) { 62 wdmu.Lock() 63 defer wdmu.Unlock() 64 65 if wdSet { 66 return wdStr, nil 67 } 68 wd, err = getwd() 69 if err != nil { 70 return 71 } 72 wdSet = true 73 wdStr = wd 74 return wd, nil 75 } 76 77 func Chdir(path string) error { 78 fixwd(path) 79 wdmu.Lock() 80 defer wdmu.Unlock() 81 82 if err := chdir(path); err != nil { 83 return err 84 } 85 86 wd, err := getwd() 87 if err != nil { 88 return err 89 } 90 wdSet = true 91 wdStr = wd 92 return nil 93 }