diff --git a/cmd/checkdevpremine/config.go b/cmd/checkdevpremine/config.go index bc9448bf..37edddad 100644 --- a/cmd/checkdevpremine/config.go +++ b/cmd/checkdevpremine/config.go @@ -8,7 +8,9 @@ import ( "fmt" "net" "os" + "os/user" "path/filepath" + "runtime" "strings" "github.com/decred/dcrd/dcrutil" @@ -47,18 +49,53 @@ func normalizeAddress(addr string) string { return addr } -// cleanAndExpandPath expands environement variables and leading ~ in the +// cleanAndExpandPath expands environment variables and leading ~ in the // passed path, cleans the result, and returns it. func cleanAndExpandPath(path string) string { - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - homeDir := filepath.Dir(appHomeDir) - path = strings.Replace(path, "~", homeDir, 1) + // NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style + // %VARIABLE%, but the variables can still be expanded via POSIX-style + // $VARIABLE. + path = os.ExpandEnv(path) + + if !strings.HasPrefix(path, "~") { + return filepath.Clean(path) } - // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, - // but they variables can still be expanded via POSIX-style $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) + // Expand initial ~ to the current user's home directory, or ~otheruser + // to otheruser's home directory. On Windows, both forward and backward + // slashes can be used. + path = path[1:] + + var pathSeparators string + if runtime.GOOS == "windows" { + pathSeparators = string(os.PathSeparator) + "/" + } else { + pathSeparators = string(os.PathSeparator) + } + + userName := "" + if i := strings.IndexAny(path, pathSeparators); i != -1 { + userName = path[:i] + path = path[i:] + } + + homeDir := "" + var u *user.User + var err error + if userName == "" { + u, err = user.Current() + } else { + u, err = user.Lookup(userName) + } + if err == nil { + homeDir = u.HomeDir + } + // Fallback to CWD if user lookup fails or user has no home directory. + if homeDir == "" { + homeDir = "." + } + + return filepath.Join(homeDir, path) } // loadConfig initializes and parses the config using a config file and command diff --git a/cmd/dcrctl/config.go b/cmd/dcrctl/config.go index 4cb8e447..27b9a97d 100644 --- a/cmd/dcrctl/config.go +++ b/cmd/dcrctl/config.go @@ -10,8 +10,10 @@ import ( "io/ioutil" "net" "os" + "os/user" "path/filepath" "regexp" + "runtime" "strings" "github.com/decred/dcrd/dcrjson" @@ -146,18 +148,53 @@ func normalizeAddress(addr string, useTestNet, useSimNet, useWallet bool) string return addr } -// cleanAndExpandPath expands environement variables and leading ~ in the +// cleanAndExpandPath expands environment variables and leading ~ in the // passed path, cleans the result, and returns it. func cleanAndExpandPath(path string) string { - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - homeDir := filepath.Dir(dcrctlHomeDir) - path = strings.Replace(path, "~", homeDir, 1) + // NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style + // %VARIABLE%, but the variables can still be expanded via POSIX-style + // $VARIABLE. + path = os.ExpandEnv(path) + + if !strings.HasPrefix(path, "~") { + return filepath.Clean(path) } - // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, - // but they variables can still be expanded via POSIX-style $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) + // Expand initial ~ to the current user's home directory, or ~otheruser + // to otheruser's home directory. On Windows, both forward and backward + // slashes can be used. + path = path[1:] + + var pathSeparators string + if runtime.GOOS == "windows" { + pathSeparators = string(os.PathSeparator) + "/" + } else { + pathSeparators = string(os.PathSeparator) + } + + userName := "" + if i := strings.IndexAny(path, pathSeparators); i != -1 { + userName = path[:i] + path = path[i:] + } + + homeDir := "" + var u *user.User + var err error + if userName == "" { + u, err = user.Current() + } else { + u, err = user.Lookup(userName) + } + if err == nil { + homeDir = u.HomeDir + } + // Fallback to CWD if user lookup fails or user has no home directory. + if homeDir == "" { + homeDir = "." + } + + return filepath.Join(homeDir, path) } // filesExists reports whether the named file or directory exists. diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index c575a9c8..9d35f2e9 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -10,12 +10,13 @@ import ( "fmt" "io/ioutil" "os" + "os/user" "path/filepath" + "runtime" "strings" "time" "github.com/decred/dcrd/certgen" - "github.com/decred/dcrd/dcrutil" flags "github.com/jessevdk/go-flags" ) @@ -79,19 +80,53 @@ func main() { } } -// cleanAndExpandPath expands environement variables and leading ~ in the +// cleanAndExpandPath expands environment variables and leading ~ in the // passed path, cleans the result, and returns it. func cleanAndExpandPath(path string) string { - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - appHomeDir := dcrutil.AppDataDir("gencerts", false) - homeDir := filepath.Dir(appHomeDir) - path = strings.Replace(path, "~", homeDir, 1) + // NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style + // %VARIABLE%, but the variables can still be expanded via POSIX-style + // $VARIABLE. + path = os.ExpandEnv(path) + + if !strings.HasPrefix(path, "~") { + return filepath.Clean(path) } - // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, - // but they variables can still be expanded via POSIX-style $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) + // Expand initial ~ to the current user's home directory, or ~otheruser + // to otheruser's home directory. On Windows, both forward and backward + // slashes can be used. + path = path[1:] + + var pathSeparators string + if runtime.GOOS == "windows" { + pathSeparators = string(os.PathSeparator) + "/" + } else { + pathSeparators = string(os.PathSeparator) + } + + userName := "" + if i := strings.IndexAny(path, pathSeparators); i != -1 { + userName = path[:i] + path = path[i:] + } + + homeDir := "" + var u *user.User + var err error + if userName == "" { + u, err = user.Current() + } else { + u, err = user.Lookup(userName) + } + if err == nil { + homeDir = u.HomeDir + } + // Fallback to CWD if user lookup fails or user has no home directory. + if homeDir == "" { + homeDir = "." + } + + return filepath.Join(homeDir, path) } // filesExists reports whether the named file or directory exists. diff --git a/config.go b/config.go index 3dd6d36f..86e9c983 100644 --- a/config.go +++ b/config.go @@ -12,6 +12,7 @@ import ( "fmt" "net" "os" + "os/user" "path/filepath" "regexp" "runtime" @@ -179,15 +180,50 @@ type serviceOptions struct { // cleanAndExpandPath expands environment variables and leading ~ in the // passed path, cleans the result, and returns it. func cleanAndExpandPath(path string) string { - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - homeDir := filepath.Dir(defaultHomeDir) - path = strings.Replace(path, "~", homeDir, 1) + // NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style + // %VARIABLE%, but the variables can still be expanded via POSIX-style + // $VARIABLE. + path = os.ExpandEnv(path) + + if !strings.HasPrefix(path, "~") { + return filepath.Clean(path) } - // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, - // but they variables can still be expanded via POSIX-style $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) + // Expand initial ~ to the current user's home directory, or ~otheruser + // to otheruser's home directory. On Windows, both forward and backward + // slashes can be used. + path = path[1:] + + var pathSeparators string + if runtime.GOOS == "windows" { + pathSeparators = string(os.PathSeparator) + "/" + } else { + pathSeparators = string(os.PathSeparator) + } + + userName := "" + if i := strings.IndexAny(path, pathSeparators); i != -1 { + userName = path[:i] + path = path[i:] + } + + homeDir := "" + var u *user.User + var err error + if userName == "" { + u, err = user.Current() + } else { + u, err = user.Lookup(userName) + } + if err == nil { + homeDir = u.HomeDir + } + // Fallback to CWD if user lookup fails or user has no home directory. + if homeDir == "" { + homeDir = "." + } + + return filepath.Join(homeDir, path) } // validLogLevel returns whether or not logLevel is a valid debug log level. diff --git a/sampleconfig/sampleconfig.go b/sampleconfig/sampleconfig.go index 681ccab6..86a2a355 100644 --- a/sampleconfig/sampleconfig.go +++ b/sampleconfig/sampleconfig.go @@ -14,11 +14,13 @@ const FileContents = `[Application Options] ; The directory to store data such as the block chain and peer addresses. The ; block chain takes several GB, so this location must have a lot of free space. ; The default is ~/.dcrd/data on POSIX OSes, $LOCALAPPDATA/Dcrd/data on Windows, -; ~/Library/Application Support/Dcrd/data on Mac OS, and $homed/dcrd/data on +; ~/Library/Application Support/Dcrd/data on macOS, and $homed/dcrd/data on ; Plan9. Environment variables are expanded so they may be used. NOTE: Windows ; environment variables are typically %VARIABLE%, but they must be accessed with -; $VARIABLE here. Also, ~ is expanded to $LOCALAPPDATA on Windows. -; datadir=~/.dcrd/data +; $VARIABLE here. +; datadir=~/.dcrd/data ; Unix +; datadir=$LOCALAPPDATA/Dcrd/data ; Windows +; datadir=~/Library/Application Support/Dcrd/data ; macOS ; ------------------------------------------------------------------------------