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  }