util.{hh,cc}: Split out users.{hh,cc}

Change-Id: I1bd92479a2cb7e5c2c2e1541b80474adb05ea0df
This commit is contained in:
Tom Hubrecht 2024-05-28 15:40:03 +02:00
parent b910551120
commit f79ee66646
21 changed files with 185 additions and 154 deletions

View file

@ -31,6 +31,7 @@
#include "print.hh"
#include "progress-bar.hh"
#include "gc-small-vector.hh"
#include "users.hh"
#if HAVE_BOEHMGC
#define GC_INCLUDE_NEW

View file

@ -1,8 +1,8 @@
#include "eval-cache.hh"
#include "sqlite.hh"
#include "eval.hh"
#include "eval-inline.hh"
#include "store-api.hh"
#include "users.hh"
namespace nix::eval_cache {

View file

@ -1,6 +1,7 @@
#include "file-system.hh"
#include "globals.hh"
#include "profiles.hh"
#include "eval.hh"
#include "users.hh"
#include "eval-settings.hh"
namespace nix {

View file

@ -1,5 +1,5 @@
#include "flake.hh"
#include "globals.hh"
#include "users.hh"
#include "fetch-settings.hh"
#include <nlohmann/json.hpp>

View file

@ -19,7 +19,7 @@
#include <variant>
#include "finally.hh"
#include "util.hh"
#include "users.hh"
#include "nixexpr.hh"
#include "eval.hh"

View file

@ -2,6 +2,7 @@
#include "sqlite.hh"
#include "sync.hh"
#include "store-api.hh"
#include "users.hh"
#include <nlohmann/json.hpp>

View file

@ -6,7 +6,7 @@
#include "store-api.hh"
#include "url-parts.hh"
#include "pathlocks.hh"
#include "util.hh"
#include "users.hh"
#include "git.hh"
#include "logging.hh"
#include "finally.hh"

View file

@ -3,6 +3,7 @@
#include "processes.hh"
#include "store-api.hh"
#include "url-parts.hh"
#include "users.hh"
#include "fetch-settings.hh"

View file

@ -1,6 +1,6 @@
#include "registry.hh"
#include "fetchers.hh"
#include "util.hh"
#include "users.hh"
#include "globals.hh"
#include "store-api.hh"
#include "local-fs-store.hh"

View file

@ -1,6 +1,6 @@
#include "environment-variables.hh"
#include "globals.hh"
#include "util.hh"
#include "users.hh"
#include "archive.hh"
#include "args.hh"
#include "abstract-setting-to-json.hh"

View file

@ -2,6 +2,7 @@
#include "sync.hh"
#include "sqlite.hh"
#include "globals.hh"
#include "users.hh"
#include <sqlite3.h>
#include <nlohmann/json.hpp>

View file

@ -1,7 +1,7 @@
#include "profiles.hh"
#include "store-api.hh"
#include "local-fs-store.hh"
#include "util.hh"
#include "users.hh"
#include <sys/types.h>
#include <sys/stat.h>

View file

@ -14,6 +14,7 @@
// FIXME this should not be here, see TODO below on
// `addMultipleToStore`.
#include "worker-protocol.hh"
#include "users.hh"
#include <nlohmann/json.hpp>
#include <regex>

View file

@ -9,6 +9,7 @@
#include "serialise.hh"
#include "signals.hh"
#include "types.hh"
#include "users.hh"
namespace fs = std::filesystem;

View file

@ -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',

105
src/libutil/users.cc Normal file
View file

@ -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;
}
}

61
src/libutil/users.hh Normal file
View file

@ -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);
}

View file

@ -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;
}
//////////////////////////////////////////////////////////////////////

View file

@ -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.

View file

@ -6,7 +6,7 @@
#include "legacy.hh"
#include "fetchers.hh"
#include "eval-settings.hh" // for defexpr
#include "util.hh"
#include "users.hh"
#include <fcntl.h>
#include <regex>

View file

@ -11,7 +11,7 @@
#include "store-api.hh"
#include "local-fs-store.hh"
#include "user-env.hh"
#include "util.hh"
#include "users.hh"
#include "value-to-json.hh"
#include "xml-writer.hh"
#include "legacy.hh"