aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc75
1 files changed, 57 insertions, 18 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 563a72c12..1b6467eb2 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -512,6 +512,7 @@ std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
if (!fd)
throw SysError("creating temporary file '%s'", tmpl);
+ closeOnExec(fd.get());
return {std::move(fd), tmpl};
}
@@ -562,7 +563,7 @@ Path getConfigDir()
std::vector<Path> getConfigDirs()
{
Path configHome = getConfigDir();
- string configDirs = getEnv("XDG_CONFIG_DIRS").value_or("");
+ string configDirs = getEnv("XDG_CONFIG_DIRS").value_or("/etc/xdg");
std::vector<Path> result = tokenizeString<std::vector<string>>(configDirs, ":");
result.insert(result.begin(), configHome);
return result;
@@ -1205,7 +1206,7 @@ void closeOnExec(int fd)
//////////////////////////////////////////////////////////////////////
-bool _isInterrupted = false;
+std::atomic<bool> _isInterrupted = false;
static thread_local bool interruptThrown = false;
thread_local std::function<bool()> interruptCheck;
@@ -1436,8 +1437,7 @@ std::string filterANSIEscapes(const std::string & s, bool filterAll, unsigned in
}
-static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static std::array<char, 256> base64DecodeChars;
+constexpr char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
string base64Encode(std::string_view s)
{
@@ -1462,12 +1462,15 @@ string base64Encode(std::string_view s)
string base64Decode(std::string_view s)
{
- static std::once_flag flag;
- std::call_once(flag, [](){
- base64DecodeChars = { (char)-1 };
+ constexpr char npos = -1;
+ constexpr std::array<char, 256> base64DecodeChars = [&]() {
+ std::array<char, 256> result{};
+ for (auto& c : result)
+ c = npos;
for (int i = 0; i < 64; i++)
- base64DecodeChars[(int) base64Chars[i]] = i;
- });
+ result[base64Chars[i]] = i;
+ return result;
+ }();
string res;
unsigned int d = 0, bits = 0;
@@ -1477,7 +1480,7 @@ string base64Decode(std::string_view s)
if (c == '\n') continue;
char digit = base64DecodeChars[(unsigned char) c];
- if (digit == -1)
+ if (digit == npos)
throw Error("invalid character in Base64 string: '%c'", c);
bits += 6;
@@ -1630,9 +1633,39 @@ void setStackSize(size_t stackSize)
#endif
}
-void restoreProcessContext()
+static AutoCloseFD fdSavedMountNamespace;
+
+void saveMountNamespace()
+{
+#if __linux__
+ static std::once_flag done;
+ std::call_once(done, []() {
+ AutoCloseFD fd = open("/proc/self/ns/mnt", O_RDONLY);
+ if (!fd)
+ throw SysError("saving parent mount namespace");
+ fdSavedMountNamespace = std::move(fd);
+ });
+#endif
+}
+
+void restoreMountNamespace()
+{
+#if __linux__
+ try {
+ if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1)
+ throw SysError("restoring parent mount namespace");
+ } catch (Error & e) {
+ debug(e.msg());
+ }
+#endif
+}
+
+void restoreProcessContext(bool restoreMounts)
{
restoreSignals();
+ if (restoreMounts) {
+ restoreMountNamespace();
+ }
restoreAffinity();
@@ -1670,7 +1703,7 @@ std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()>
}
-AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
+AutoCloseFD createUnixDomainSocket()
{
AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM
#ifdef SOCK_CLOEXEC
@@ -1679,8 +1712,14 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
, 0);
if (!fdSocket)
throw SysError("cannot create Unix domain socket");
-
closeOnExec(fdSocket.get());
+ return fdSocket;
+}
+
+
+AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
+{
+ auto fdSocket = nix::createUnixDomainSocket();
bind(fdSocket.get(), path);
@@ -1709,7 +1748,7 @@ void bind(int fd, const std::string & path)
std::string base(baseNameOf(path));
if (base.size() + 1 >= sizeof(addr.sun_path))
throw Error("socket path '%s' is too long", base);
- strcpy(addr.sun_path, base.c_str());
+ memcpy(addr.sun_path, base.c_str(), base.size() + 1);
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
throw SysError("cannot bind to socket '%s'", path);
_exit(0);
@@ -1718,7 +1757,7 @@ void bind(int fd, const std::string & path)
if (status != 0)
throw Error("cannot bind to socket '%s'", path);
} else {
- strcpy(addr.sun_path, path.c_str());
+ memcpy(addr.sun_path, path.c_str(), path.size() + 1);
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
throw SysError("cannot bind to socket '%s'", path);
}
@@ -1738,7 +1777,7 @@ void connect(int fd, const std::string & path)
std::string base(baseNameOf(path));
if (base.size() + 1 >= sizeof(addr.sun_path))
throw Error("socket path '%s' is too long", base);
- strcpy(addr.sun_path, base.c_str());
+ memcpy(addr.sun_path, base.c_str(), base.size() + 1);
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
throw SysError("cannot connect to socket at '%s'", path);
_exit(0);
@@ -1747,7 +1786,7 @@ void connect(int fd, const std::string & path)
if (status != 0)
throw Error("cannot connect to socket at '%s'", path);
} else {
- strcpy(addr.sun_path, path.c_str());
+ memcpy(addr.sun_path, path.c_str(), path.size() + 1);
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
throw SysError("cannot connect to socket at '%s'", path);
}
@@ -1766,7 +1805,7 @@ void commonChildInit(Pipe & logPipe)
logger = makeSimpleLogger();
const static string pathNullDevice = "/dev/null";
- restoreProcessContext();
+ restoreProcessContext(false);
/* Put the child in a separate session (and thus a separate
process group) so that it has no controlling terminal (meaning