#include "util.hh" #include "users.hh" #include "environment-variables.hh" #include "file-system.hh" #include #include #include 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 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 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; } bool isRootUser() { return getuid() == 0; } }