diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/file-system.cc | 1 | ||||
-rw-r--r-- | src/libutil/meson.build | 2 | ||||
-rw-r--r-- | src/libutil/users.cc | 105 | ||||
-rw-r--r-- | src/libutil/users.hh | 61 | ||||
-rw-r--r-- | src/libutil/util.cc | 97 | ||||
-rw-r--r-- | src/libutil/util.hh | 47 |
6 files changed, 169 insertions, 144 deletions
diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 9804c449c..721bf97e2 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -9,6 +9,7 @@ #include "serialise.hh" #include "signals.hh" #include "types.hh" +#include "users.hh" namespace fs = std::filesystem; diff --git a/src/libutil/meson.build b/src/libutil/meson.build index b662ea455..5e767b447 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -39,6 +39,7 @@ libutil_sources = files( 'unix-domain-socket.cc', 'url.cc', 'url-name.cc', + 'users.cc', 'util.cc', 'xml-writer.cc', ) @@ -109,6 +110,7 @@ libutil_headers = files( 'url-parts.hh', 'url-name.hh', 'url.hh', + 'users.hh', 'util.hh', 'variant-wrapper.hh', 'xml-writer.hh', diff --git a/src/libutil/users.cc b/src/libutil/users.cc new file mode 100644 index 000000000..a9a8a7353 --- /dev/null +++ b/src/libutil/users.cc @@ -0,0 +1,105 @@ +#include "environment-variables.hh" +#include "file-system.hh" +#include "logging.hh" +#include "strings.hh" + +#include <pwd.h> +#include <sys/types.h> +#include <unistd.h> + +namespace nix { + +std::string getUserName() +{ + auto pw = getpwuid(geteuid()); + std::string name = pw ? pw->pw_name : getEnv("USER").value_or(""); + if (name.empty()) + throw Error("cannot figure out user name"); + return name; +} + +Path getHomeOf(uid_t userId) +{ + std::vector<char> 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"); + return pw->pw_dir; +} + +Path getHome() +{ + static Path homeDir = []() + { + std::optional<std::string> unownedUserHomeDir = {}; + auto homeDir = getEnv("HOME"); + if (homeDir) { + // Only use $HOME if doesn't exist or is owned by the current user. + struct stat st; + int result = stat(homeDir->c_str(), &st); + if (result != 0) { + if (errno != ENOENT) { + warn("couldn't stat $HOME ('%s') for reason other than not existing ('%d'), falling back to the one defined in the 'passwd' file", *homeDir, errno); + homeDir.reset(); + } + } else if (st.st_uid != geteuid()) { + unownedUserHomeDir.swap(homeDir); + } + } + if (!homeDir) { + homeDir = getHomeOf(geteuid()); + if (unownedUserHomeDir.has_value() && unownedUserHomeDir != homeDir) { + warn("$HOME ('%s') is not owned by you, falling back to the one defined in the 'passwd' file ('%s')", *unownedUserHomeDir, *homeDir); + } + } + return *homeDir; + }(); + return homeDir; +} + + +Path getCacheDir() +{ + auto cacheDir = getEnv("XDG_CACHE_HOME"); + return cacheDir ? *cacheDir : getHome() + "/.cache"; +} + + +Path getConfigDir() +{ + auto configDir = getEnv("XDG_CONFIG_HOME"); + return configDir ? *configDir : getHome() + "/.config"; +} + +std::vector<Path> getConfigDirs() +{ + Path configHome = getConfigDir(); + auto configDirs = getEnv("XDG_CONFIG_DIRS").value_or("/etc/xdg"); + std::vector<Path> result = tokenizeString<std::vector<std::string>>(configDirs, ":"); + result.insert(result.begin(), configHome); + return result; +} + + +Path getDataDir() +{ + auto dataDir = getEnv("XDG_DATA_HOME"); + return dataDir ? *dataDir : getHome() + "/.local/share"; +} + +Path getStateDir() +{ + auto stateDir = getEnv("XDG_STATE_HOME"); + return stateDir ? *stateDir : getHome() + "/.local/state"; +} + +Path createNixStateDir() +{ + Path dir = getStateDir() + "/nix"; + createDirs(dir); + return dir; +} + +} diff --git a/src/libutil/users.hh b/src/libutil/users.hh new file mode 100644 index 000000000..3add4c732 --- /dev/null +++ b/src/libutil/users.hh @@ -0,0 +1,61 @@ +#pragma once +///@file + +#include "types.hh" + +#include <sys/types.h> + +namespace nix { + +std::string getUserName(); + +/** + * @return the given user's home directory from /etc/passwd. + */ +Path getHomeOf(uid_t userId); + +/** + * @return $HOME or the user's home directory from /etc/passwd. + */ +Path getHome(); + +/** + * @return $XDG_CACHE_HOME or $HOME/.cache. + */ +Path getCacheDir(); + +/** + * @return $XDG_CONFIG_HOME or $HOME/.config. + */ +Path getConfigDir(); + +/** + * @return the directories to search for user configuration files + */ +std::vector<Path> getConfigDirs(); + +/** + * @return $XDG_DATA_HOME or $HOME/.local/share. + */ +Path getDataDir(); + +/** + * @return $XDG_STATE_HOME or $HOME/.local/state. + * + * @note Not to be confused with settings.nixStateDir. + */ +Path getStateDir(); + +/** + * Create $XDG_STATE_HOME/nix or $HOME/.local/state/nix, and return + * the path to it. + * @note Not to be confused with settings.nixStateDir. + */ +Path createNixStateDir(); + +/** + * Perform tilde expansion on a path. + */ +std::string expandTilde(std::string_view path); + +} diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 099a07622..8e813abc2 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -56,103 +56,6 @@ namespace nix { -std::string getUserName() -{ - auto pw = getpwuid(geteuid()); - std::string name = pw ? pw->pw_name : getEnv("USER").value_or(""); - if (name.empty()) - throw Error("cannot figure out user name"); - return name; -} - -Path getHomeOf(uid_t userId) -{ - std::vector<char> 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"); - return pw->pw_dir; -} - -Path getHome() -{ - static Path homeDir = []() - { - std::optional<std::string> unownedUserHomeDir = {}; - auto homeDir = getEnv("HOME"); - if (homeDir) { - // Only use $HOME if doesn't exist or is owned by the current user. - struct stat st; - int result = stat(homeDir->c_str(), &st); - if (result != 0) { - if (errno != ENOENT) { - warn("couldn't stat $HOME ('%s') for reason other than not existing ('%d'), falling back to the one defined in the 'passwd' file", *homeDir, errno); - homeDir.reset(); - } - } else if (st.st_uid != geteuid()) { - unownedUserHomeDir.swap(homeDir); - } - } - if (!homeDir) { - homeDir = getHomeOf(geteuid()); - if (unownedUserHomeDir.has_value() && unownedUserHomeDir != homeDir) { - warn("$HOME ('%s') is not owned by you, falling back to the one defined in the 'passwd' file ('%s')", *unownedUserHomeDir, *homeDir); - } - } - return *homeDir; - }(); - return homeDir; -} - - -Path getCacheDir() -{ - auto cacheDir = getEnv("XDG_CACHE_HOME"); - return cacheDir ? *cacheDir : getHome() + "/.cache"; -} - - -Path getConfigDir() -{ - auto configDir = getEnv("XDG_CONFIG_HOME"); - return configDir ? *configDir : getHome() + "/.config"; -} - -std::vector<Path> getConfigDirs() -{ - Path configHome = getConfigDir(); - auto configDirs = getEnv("XDG_CONFIG_DIRS").value_or("/etc/xdg"); - std::vector<Path> result = tokenizeString<std::vector<std::string>>(configDirs, ":"); - result.insert(result.begin(), configHome); - return result; -} - - -Path getDataDir() -{ - auto dataDir = getEnv("XDG_DATA_HOME"); - return dataDir ? *dataDir : getHome() + "/.local/share"; -} - -Path getStateDir() -{ - auto stateDir = getEnv("XDG_STATE_HOME"); - return stateDir ? *stateDir : getHome() + "/.local/state"; -} - -Path createNixStateDir() -{ - Path dir = getStateDir() + "/nix"; - createDirs(dir); - return dir; -} - - - - - ////////////////////////////////////////////////////////////////////// diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 907bdf4ed..e408821b9 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -39,53 +39,6 @@ struct Source; extern const std::string nativeSystem; -std::string getUserName(); - -/** - * @return the given user's home directory from /etc/passwd. - */ -Path getHomeOf(uid_t userId); - -/** - * @return $HOME or the user's home directory from /etc/passwd. - */ -Path getHome(); - -/** - * @return $XDG_CACHE_HOME or $HOME/.cache. - */ -Path getCacheDir(); - -/** - * @return $XDG_CONFIG_HOME or $HOME/.config. - */ -Path getConfigDir(); - -/** - * @return the directories to search for user configuration files - */ -std::vector<Path> getConfigDirs(); - -/** - * @return $XDG_DATA_HOME or $HOME/.local/share. - */ -Path getDataDir(); - -/** - * @return $XDG_STATE_HOME or $HOME/.local/state. - * - * @note Not to be confused with settings.nixStateDir. - */ -Path getStateDir(); - -/** - * Create $XDG_STATE_HOME/nix or $HOME/.local/state/nix, and return - * the path to it. - * @note Not to be confused with settings.nixStateDir. - */ -Path createNixStateDir(); - - /** * Save the current mount namespace. Ignored if called more than * once. |