mitchellh / go-homedir Goto Github PK
View Code? Open in Web Editor NEWGo library for detecting and expanding the user's home directory without cgo.
License: MIT License
Go library for detecting and expanding the user's home directory without cgo.
License: MIT License
Lines 148 to 167 in af06845
TL;DR, change code to
func dirWindows() (string, error) {
home := os.Getenv("LOCALAPPDATA")
if home == "" {
return "", errors.New("LOCALAPPDATA environment variable is missing or empty")
}
return home, nil
}
$HOME
is non-standard on Windows, and likely references $USERPROFILE
. $USERPROFILE
is not meant to be a location that applications store files other than via a save dialog box or similar situation where the user is explicitly putting files there. The proper location to store data that should be automatically synced to a network or uploaded to the cloud is $APPDATA
. For data that should be machine-local (e.g., caches, application data, etc.) it should be stored in $LOCALAPPDATA
.
In this library, it doesn't appear that you distinguish between data types so $LOCALAPPDATA
is the best location. If someone throws a cache in there you don't break the user's profile.
Note: $LOCALAPPDATA
has been around since Windows XP/2003 while the fallback you were using of $HOMEDRIVE
I think has been deprecated and $HOMEPATH
is fairly new (and I think also deprecated), so this is not only more correct, but also more backward compatible than the code currently present.
Related: ipfs/kubo#861.
I don't have getent on my system, so the dirUnix function failed to execute it. It checks (https://github.com/mitchellh/go-homedir/blob/master/homedir.go#L87) if the exec.ErrNotFound error is returned, but this error is wrapped by exec.Error() so the returned error will never be exec.ErrNotFound.
The actual returned error message is: exec: "getent": executable file not found in $PATH
, whereas it expected the following: executable file not found in $PATH
.
A fix would be if strings.HasSufix(err.Error(), err.ErrNotFound.Error()) {
.
In a MR in containers/common someone mentioned this package after I already reimplemented this module.
While looking into this, I found a bug in your code:
homedir.Expand("~something")
This throws an "cannot expand user-specific home dir". Directory names starting with a "~" are valid, so this is a bug in my opinion.
I implemented the function (using os/user) as follows:
// resolveHomeDir converts a path referencing the home directory via "~"
// to an absolute path
func resolveHomeDir(path string) (string, error) {
// check if the path references the home dir to avoid work
// don't use strings.HasPrefix(path, "~") as this doesn't match "~" alone
// use strings.HasPrefix(...) to not match "something/~/something"
if !(path == "~" || strings.HasPrefix(path, "~/")) {
// path does not reference home dir -> Nothing to do
return path, nil
}
// only get HomeDir when necessary
home, err := unshare.HomeDir()
if err != nil {
return "", err
}
// replace the first "~" (start of path) with the HomeDir to resolve "~"
return strings.Replace(path, "~", home, 1), nil
}
By replacing unshare.HomeDir with your Dir function, this issue should be fixed.
I originally opened this in a downstream terraform provider including go-homedir
as a dependency. The main issue is that HOMEDRIVE/HOMEPATH are relics of NT4 and not standard environment variables post Windows Vista. They appear to exist sometimes in environments with a history of roaming profiles.
You may read the explanation in the original issue: hashicorp/terraform-provider-azurerm#1395
This document has a table of standard environment variables on Windows: https://msdn.microsoft.com/en-us/library/dd378457(v=vs.85).aspx
Lines 138 to 155 in 3864e76
Go 1.9 ships with os/user.LookupId, os/user.Lookup, os/user.LookupGroup, os/user.LookupGroupId that work without cgo. If you compile without cgo enabled, those functions will read /etc/passwd and /etc/group respectively to find answers to the questions you ask. Which may be good enough for your use case.
(I wrote the functions in question, and I'm curious how well they work for folks. I would appreciate feedback on how well they work or don't. If they don't work, I'd love to help fix them. Thanks!)
It would be great to tag some versions.
The os package code seems to be almost the very same. So, is this package still relevant? Or is the std lib os still using cgo somewhere?
From package os.
func UserHomeDir() (string, error) {
env, enverr := "HOME", "$HOME"
switch runtime.GOOS {
case "windows":
env, enverr = "USERPROFILE", "%userprofile%"
case "plan9":
env, enverr = "home", "$home"
}
if v := Getenv(env); v != "" {
return v, nil
}
// On some geese the home directory is not always defined.
switch runtime.GOOS {
case "android":
return "/sdcard", nil
case "ios":
return "/", nil
}
return "", errors.New(enverr + " is not defined")
}
This line within dirUnix()
(L87) fails in macOS, as it assumes getent
is installed, which is not the case for macOS, as this is a Unix/Linux-only utility.
cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
This is the error that's returned
"getent": executable file not found in $PATH
Suggest detecting whether the user is on a Mac and use a Mac name resolving binary like dscacheutil
or dns-sd
.
I'd like to use this library as one of my users has run into the OSX issue mentioned in the README.
I currently build plan9 binaries - is it likely to work there?
Thanks
Nick
This package turns out to be a dependency of https://github.com/ipfs/go-ipfs. I am in the process of packaging IPFS for Gentoo where we prefer to build our software from source when we install it. Thus I am also packaging this project and would kindly like to ask you to push a semantic version tag, which makes things a lot easier for me.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.