github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/filesystem/resources.go (about) 1 package filesystem 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path/filepath" 8 ) 9 10 // LibexecPath computes the expected libexec path assuming a Filesystem 11 // Hierarchy Standard layout with the current executable located in the bin 12 // directory. It will return an error if the executable does not exist within 13 // the "bin" directory of such a layout, but it does not verify that the libexec 14 // directory exists. 15 func LibexecPath() (string, error) { 16 // Compute the path to the current executable. 17 executablePath, err := os.Executable() 18 if err != nil { 19 return "", fmt.Errorf("unable to compute executable path: %w", err) 20 } 21 22 // If the executable path is a symbolic link, then perform resolution. 23 // Unfortunately there's no way to do this in a completely race-free 24 // fashion, but we're dealing with system prefixes here so it shouldn't be a 25 // problem. 26 if metadata, err := os.Lstat(executablePath); err != nil { 27 return "", fmt.Errorf("unable to read executable metadata: %w", err) 28 } else if metadata.Mode()&os.ModeSymlink != 0 { 29 if target, err := os.Readlink(executablePath); err != nil { 30 return "", fmt.Errorf("unable to read executable symbolic link target: %w", err) 31 } else if filepath.IsAbs(target) { 32 executablePath = target 33 } else { 34 executablePath = filepath.Clean(filepath.Join(filepath.Dir(executablePath), target)) 35 } 36 } 37 38 // Check that the executable resides within a bin directory. 39 if filepath.Base(filepath.Dir(executablePath)) != "bin" { 40 return "", errors.New("executable does not reside within bin directory") 41 } 42 43 // Compute the expected libexec path. 44 return filepath.Clean(filepath.Join(executablePath, "..", "..", "libexec")), nil 45 }