Home | History | Annotate | Download | only in syscall
      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 // goroutine-specific getwd
     43 func getwd() (wd string, err error) {
     44 	fd, err := open(".", O_RDONLY)
     45 	if err != nil {
     46 		return "", err
     47 	}
     48 	defer Close(fd)
     49 	return Fd2path(fd)
     50 }
     51 
     52 func Getwd() (wd string, err error) {
     53 	wdmu.Lock()
     54 	defer wdmu.Unlock()
     55 
     56 	if wdSet {
     57 		return wdStr, nil
     58 	}
     59 	wd, err = getwd()
     60 	if err != nil {
     61 		return
     62 	}
     63 	wdSet = true
     64 	wdStr = wd
     65 	return wd, nil
     66 }
     67 
     68 func Chdir(path string) error {
     69 	wdmu.Lock()
     70 	defer wdmu.Unlock()
     71 
     72 	if err := chdir(path); err != nil {
     73 		return err
     74 	}
     75 
     76 	wd, err := getwd()
     77 	if err != nil {
     78 		return err
     79 	}
     80 	wdSet = true
     81 	wdStr = wd
     82 	return nil
     83 }
     84