mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-04 13:06:01 +00:00
94 lines
1.6 KiB
Go
94 lines
1.6 KiB
Go
// Copyright 2015 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.
|
|
|
|
// The working directory in Plan 9 is effectively per P, so different
|
|
// goroutines and even the same goroutine as it's rescheduled on
|
|
// different Ps can see different working directories.
|
|
//
|
|
// Instead, track a Go process-wide intent of the current working directory,
|
|
// and switch to it at important points.
|
|
|
|
package syscall
|
|
|
|
import "sync"
|
|
|
|
var (
|
|
wdmu sync.Mutex // guards following
|
|
wdSet bool
|
|
wdStr string
|
|
)
|
|
|
|
func Fixwd() {
|
|
wdmu.Lock()
|
|
defer wdmu.Unlock()
|
|
fixwdLocked()
|
|
}
|
|
|
|
func fixwdLocked() {
|
|
if !wdSet {
|
|
return
|
|
}
|
|
// always call chdir when getwd returns an error
|
|
wd, _ := getwd()
|
|
if wd == wdStr {
|
|
return
|
|
}
|
|
if err := chdir(wdStr); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
func fixwd(paths ...string) {
|
|
for _, path := range paths {
|
|
if path != "" && path[0] != '/' && path[0] != '#' {
|
|
Fixwd()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// goroutine-specific getwd
|
|
func getwd() (wd string, err error) {
|
|
fd, err := open(".", O_RDONLY)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer Close(fd)
|
|
return Fd2path(fd)
|
|
}
|
|
|
|
func Getwd() (wd string, err error) {
|
|
wdmu.Lock()
|
|
defer wdmu.Unlock()
|
|
|
|
if wdSet {
|
|
return wdStr, nil
|
|
}
|
|
wd, err = getwd()
|
|
if err != nil {
|
|
return
|
|
}
|
|
wdSet = true
|
|
wdStr = wd
|
|
return wd, nil
|
|
}
|
|
|
|
func Chdir(path string) error {
|
|
fixwd(path)
|
|
wdmu.Lock()
|
|
defer wdmu.Unlock()
|
|
|
|
if err := chdir(path); err != nil {
|
|
return err
|
|
}
|
|
|
|
wd, err := getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
wdSet = true
|
|
wdStr = wd
|
|
return nil
|
|
}
|