diff --git a/lix/libutil/users.cc b/lix/libutil/users.cc index ad763263c..5c388a3c7 100644 --- a/lix/libutil/users.cc +++ b/lix/libutil/users.cc @@ -19,21 +19,21 @@ std::string getUserName() return name; } -Path getHomeOf(uid_t userId) +static std::optional tryGetHomeOf(uid_t userId) { std::vector buf(16384); struct passwd pwbuf; struct passwd * pw; - if (getpwuid_r(userId, &pwbuf, buf.data(), buf.size(), &pw) != 0 - || !pw || !pw->pw_dir || !pw->pw_dir[0]) - throw Error("cannot determine user's home directory"); + if (getpwuid_r(userId, &pwbuf, buf.data(), buf.size(), &pw) != 0 || !pw || !pw->pw_dir || !pw->pw_dir[0]) + { + return std::nullopt; + } return pw->pw_dir; } -Path getHome() +std::optional tryGetHome() { - static Path homeDir = []() - { + static std::optional homeDir = []() { std::optional unownedUserHomeDir = {}; auto homeDir = getEnv("HOME"); if (homeDir) { @@ -55,8 +55,8 @@ Path getHome() } } if (!homeDir) { - homeDir = getHomeOf(geteuid()); - if (unownedUserHomeDir.has_value() && unownedUserHomeDir != homeDir) { + homeDir = tryGetHomeOf(geteuid()); + if (homeDir && unownedUserHomeDir && unownedUserHomeDir != homeDir) { printTaggedWarning( "$HOME ('%s') is not owned by you, falling back to the one defined in the " "'passwd' file ('%s')", @@ -65,11 +65,19 @@ Path getHome() ); } } - return *homeDir; + return homeDir; }(); return homeDir; } +Path getHome() +{ + if (auto home = tryGetHome()) { + return std::move(*home); + } else { + throw Error("cannot determine user's home directory"); + } +} Path getCacheDir() { @@ -102,14 +110,16 @@ Path getConfigDir() std::vector getConfigDirs() { - Path configHome = getConfigDir(); auto configDirs = getEnv("XDG_CONFIG_DIRS").value_or("/etc/xdg"); std::vector result = tokenizeString>(configDirs, ":"); - result.insert(result.begin(), configHome); + if (auto configHome = getEnv("XDG_CONFIG_HOME")) { + result.insert(result.begin(), *configHome); + } else if (auto userHome = tryGetHome()) { + result.insert(result.begin(), *userHome + "/.config"); + } return result; } - Path getDataDir() { auto dataDir = getEnv("XDG_DATA_HOME"); diff --git a/lix/libutil/users.hh b/lix/libutil/users.hh index a9e95a918..5dc78e078 100644 --- a/lix/libutil/users.hh +++ b/lix/libutil/users.hh @@ -10,9 +10,9 @@ namespace nix { std::string getUserName(); /** - * @return the given user's home directory from /etc/passwd. + * @return $HOME or the user's home directory from /etc/passwd, if available. */ -Path getHomeOf(uid_t userId); +std::optional tryGetHome(); /** * @return $HOME or the user's home directory from /etc/passwd.