mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-25 15:26:17 +02:00
commit
799e662cbe
7 changed files with 51 additions and 37 deletions
|
@ -96,7 +96,7 @@ void drainFD(int fd, Sink & sink, bool block)
|
||||||
throw SysError("making file descriptor non-blocking");
|
throw SysError("making file descriptor non-blocking");
|
||||||
}
|
}
|
||||||
|
|
||||||
Finally finally([&]() {
|
Finally finally([&] {
|
||||||
if (!block) {
|
if (!block) {
|
||||||
if (fcntl(fd, F_SETFL, saved) == -1)
|
if (fcntl(fd, F_SETFL, saved) == -1)
|
||||||
throw SysError("making file descriptor blocking");
|
throw SysError("making file descriptor blocking");
|
||||||
|
@ -114,7 +114,7 @@ void drainFD(int fd, Sink & sink, bool block)
|
||||||
throw SysError("reading from file");
|
throw SysError("reading from file");
|
||||||
}
|
}
|
||||||
else if (rd == 0) break;
|
else if (rd == 0) break;
|
||||||
else sink({(char *) buf.data(), (size_t) rd});
|
else sink({reinterpret_cast<char *>(buf.data()), size_t(rd)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
||||||
/* Normal component; copy it. */
|
/* Normal component; copy it. */
|
||||||
else {
|
else {
|
||||||
s += '/';
|
s += '/';
|
||||||
if (const auto slash = path.find('/'); slash == std::string::npos) {
|
if (const auto slash = path.find('/'); slash == path.npos) {
|
||||||
s += path;
|
s += path;
|
||||||
path = {};
|
path = {};
|
||||||
} else {
|
} else {
|
||||||
|
@ -116,14 +116,18 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.empty() ? "/" : std::move(s);
|
if (s.empty()) {
|
||||||
|
s = "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path dirOf(const PathView path)
|
Path dirOf(const PathView path)
|
||||||
{
|
{
|
||||||
Path::size_type pos = path.rfind('/');
|
Path::size_type pos = path.rfind('/');
|
||||||
if (pos == std::string::npos)
|
if (pos == path.npos)
|
||||||
return ".";
|
return ".";
|
||||||
return pos == 0 ? "/" : Path(path, 0, pos);
|
return pos == 0 ? "/" : Path(path, 0, pos);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +143,7 @@ std::string_view baseNameOf(std::string_view path)
|
||||||
last -= 1;
|
last -= 1;
|
||||||
|
|
||||||
auto pos = path.rfind('/', last);
|
auto pos = path.rfind('/', last);
|
||||||
if (pos == std::string::npos)
|
if (pos == path.npos)
|
||||||
pos = 0;
|
pos = 0;
|
||||||
else
|
else
|
||||||
pos += 1;
|
pos += 1;
|
||||||
|
|
|
@ -131,7 +131,7 @@ void killUser(uid_t uid)
|
||||||
users to which the current process can send signals. So we
|
users to which the current process can send signals. So we
|
||||||
fork a process, switch to uid, and send a mass kill. */
|
fork a process, switch to uid, and send a mass kill. */
|
||||||
|
|
||||||
Pid pid = startProcess([&]() {
|
Pid pid = startProcess([&] {
|
||||||
|
|
||||||
if (setuid(uid) == -1)
|
if (setuid(uid) == -1)
|
||||||
throw SysError("setting uid");
|
throw SysError("setting uid");
|
||||||
|
@ -168,11 +168,12 @@ void killUser(uid_t uid)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
using ChildWrapperFunction = std::function<void()>;
|
||||||
|
|
||||||
/* Wrapper around vfork to prevent the child process from clobbering
|
/* Wrapper around vfork to prevent the child process from clobbering
|
||||||
the caller's stack frame in the parent. */
|
the caller's stack frame in the parent. */
|
||||||
static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline));
|
static pid_t doFork(bool allowVfork, ChildWrapperFunction & fun) __attribute__((noinline));
|
||||||
static pid_t doFork(bool allowVfork, std::function<void()> fun)
|
static pid_t doFork(bool allowVfork, ChildWrapperFunction & fun)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
pid_t pid = allowVfork ? vfork() : fork();
|
pid_t pid = allowVfork ? vfork() : fork();
|
||||||
|
@ -188,8 +189,8 @@ static pid_t doFork(bool allowVfork, std::function<void()> fun)
|
||||||
#if __linux__
|
#if __linux__
|
||||||
static int childEntry(void * arg)
|
static int childEntry(void * arg)
|
||||||
{
|
{
|
||||||
auto main = (std::function<void()> *) arg;
|
auto & fun = *reinterpret_cast<ChildWrapperFunction*>(arg);
|
||||||
(*main)();
|
fun();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -197,7 +198,7 @@ static int childEntry(void * arg)
|
||||||
|
|
||||||
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
|
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
|
||||||
{
|
{
|
||||||
std::function<void()> wrapper = [&]() {
|
ChildWrapperFunction wrapper = [&] {
|
||||||
if (!options.allowVfork)
|
if (!options.allowVfork)
|
||||||
logger = makeSimpleLogger();
|
logger = makeSimpleLogger();
|
||||||
try {
|
try {
|
||||||
|
@ -225,11 +226,11 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
|
||||||
assert(!(options.cloneFlags & CLONE_VM));
|
assert(!(options.cloneFlags & CLONE_VM));
|
||||||
|
|
||||||
size_t stackSize = 1 * 1024 * 1024;
|
size_t stackSize = 1 * 1024 * 1024;
|
||||||
auto stack = (char *) mmap(0, stackSize,
|
auto stack = static_cast<char *>(mmap(0, stackSize,
|
||||||
PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0));
|
||||||
if (stack == MAP_FAILED) throw SysError("allocating stack");
|
if (stack == MAP_FAILED) throw SysError("allocating stack");
|
||||||
|
|
||||||
Finally freeStack([&]() { munmap(stack, stackSize); });
|
Finally freeStack([&] { munmap(stack, stackSize); });
|
||||||
|
|
||||||
pid = clone(childEntry, stack + stackSize, options.cloneFlags | SIGCHLD, &wrapper);
|
pid = clone(childEntry, stack + stackSize, options.cloneFlags | SIGCHLD, &wrapper);
|
||||||
#else
|
#else
|
||||||
|
@ -308,7 +309,7 @@ void runProgram2(const RunOptions & options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fork. */
|
/* Fork. */
|
||||||
Pid pid = startProcess([&]() {
|
Pid pid = startProcess([&] {
|
||||||
if (options.environment)
|
if (options.environment)
|
||||||
replaceEnv(*options.environment);
|
replaceEnv(*options.environment);
|
||||||
if (options.standardOut && dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
if (options.standardOut && dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
||||||
|
@ -350,7 +351,7 @@ void runProgram2(const RunOptions & options)
|
||||||
|
|
||||||
std::promise<void> promise;
|
std::promise<void> promise;
|
||||||
|
|
||||||
Finally doJoin([&]() {
|
Finally doJoin([&] {
|
||||||
if (writerThread.joinable())
|
if (writerThread.joinable())
|
||||||
writerThread.join();
|
writerThread.join();
|
||||||
});
|
});
|
||||||
|
@ -358,7 +359,7 @@ void runProgram2(const RunOptions & options)
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
in.readSide.close();
|
in.readSide.close();
|
||||||
writerThread = std::thread([&]() {
|
writerThread = std::thread([&] {
|
||||||
try {
|
try {
|
||||||
std::vector<char> buf(8 * 1024);
|
std::vector<char> buf(8 * 1024);
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
|
@ -179,7 +179,7 @@ std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()>
|
||||||
auto token = interruptCallbacks->nextToken++;
|
auto token = interruptCallbacks->nextToken++;
|
||||||
interruptCallbacks->callbacks.emplace(token, callback);
|
interruptCallbacks->callbacks.emplace(token, callback);
|
||||||
|
|
||||||
auto res = std::make_unique<InterruptCallbackImpl>();
|
std::unique_ptr<InterruptCallbackImpl> res {new InterruptCallbackImpl{}};
|
||||||
res->token = token;
|
res->token = token;
|
||||||
|
|
||||||
return std::unique_ptr<InterruptCallback>(res.release());
|
return std::unique_ptr<InterruptCallback>(res.release());
|
||||||
|
|
|
@ -38,6 +38,14 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
||||||
return fdSocket;
|
return fdSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sockaddr* safeSockAddrPointerCast(struct sockaddr_un *addr) {
|
||||||
|
// Casting between types like these legacy C library interfaces require
|
||||||
|
// is forbidden in C++.
|
||||||
|
// To maintain backwards compatibility, the implementation of the
|
||||||
|
// bind function contains some hints to the compiler that allow for this
|
||||||
|
// special case.
|
||||||
|
return reinterpret_cast<struct sockaddr *>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
void bind(int fd, const std::string & path)
|
void bind(int fd, const std::string & path)
|
||||||
{
|
{
|
||||||
|
@ -45,9 +53,10 @@ void bind(int fd, const std::string & path)
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
|
auto psaddr {safeSockAddrPointerCast(&addr)};
|
||||||
|
|
||||||
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||||
Pid pid = startProcess([&]() {
|
Pid pid = startProcess([&] {
|
||||||
Path dir = dirOf(path);
|
Path dir = dirOf(path);
|
||||||
if (chdir(dir.c_str()) == -1)
|
if (chdir(dir.c_str()) == -1)
|
||||||
throw SysError("chdir to '%s' failed", dir);
|
throw SysError("chdir to '%s' failed", dir);
|
||||||
|
@ -55,7 +64,7 @@ void bind(int fd, const std::string & path)
|
||||||
if (base.size() + 1 >= sizeof(addr.sun_path))
|
if (base.size() + 1 >= sizeof(addr.sun_path))
|
||||||
throw Error("socket path '%s' is too long", base);
|
throw Error("socket path '%s' is too long", base);
|
||||||
memcpy(addr.sun_path, base.c_str(), base.size() + 1);
|
memcpy(addr.sun_path, base.c_str(), base.size() + 1);
|
||||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
if (bind(fd, psaddr, sizeof(addr)) == -1)
|
||||||
throw SysError("cannot bind to socket '%s'", path);
|
throw SysError("cannot bind to socket '%s'", path);
|
||||||
_exit(0);
|
_exit(0);
|
||||||
});
|
});
|
||||||
|
@ -64,7 +73,7 @@ void bind(int fd, const std::string & path)
|
||||||
throw Error("cannot bind to socket '%s'", path);
|
throw Error("cannot bind to socket '%s'", path);
|
||||||
} else {
|
} else {
|
||||||
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
|
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
|
||||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
if (bind(fd, psaddr, sizeof(addr)) == -1)
|
||||||
throw SysError("cannot bind to socket '%s'", path);
|
throw SysError("cannot bind to socket '%s'", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,11 +83,12 @@ void connect(int fd, const std::string & path)
|
||||||
{
|
{
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
|
auto psaddr {safeSockAddrPointerCast(&addr)};
|
||||||
|
|
||||||
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||||
Pipe pipe;
|
Pipe pipe;
|
||||||
pipe.create();
|
pipe.create();
|
||||||
Pid pid = startProcess([&]() {
|
Pid pid = startProcess([&] {
|
||||||
try {
|
try {
|
||||||
pipe.readSide.close();
|
pipe.readSide.close();
|
||||||
Path dir = dirOf(path);
|
Path dir = dirOf(path);
|
||||||
|
@ -88,7 +98,7 @@ void connect(int fd, const std::string & path)
|
||||||
if (base.size() + 1 >= sizeof(addr.sun_path))
|
if (base.size() + 1 >= sizeof(addr.sun_path))
|
||||||
throw Error("socket path '%s' is too long", base);
|
throw Error("socket path '%s' is too long", base);
|
||||||
memcpy(addr.sun_path, base.c_str(), base.size() + 1);
|
memcpy(addr.sun_path, base.c_str(), base.size() + 1);
|
||||||
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
if (connect(fd, psaddr, sizeof(addr)) == -1)
|
||||||
throw SysError("cannot connect to socket at '%s'", path);
|
throw SysError("cannot connect to socket at '%s'", path);
|
||||||
writeFull(pipe.writeSide.get(), "0\n");
|
writeFull(pipe.writeSide.get(), "0\n");
|
||||||
} catch (SysError & e) {
|
} catch (SysError & e) {
|
||||||
|
@ -107,7 +117,7 @@ void connect(int fd, const std::string & path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
|
memcpy(addr.sun_path, path.c_str(), path.size() + 1);
|
||||||
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
if (connect(fd, psaddr, sizeof(addr)) == -1)
|
||||||
throw SysError("cannot connect to socket at '%s'", path);
|
throw SysError("cannot connect to socket at '%s'", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,9 @@ template<class C> C tokenizeString(std::string_view s, std::string_view separato
|
||||||
{
|
{
|
||||||
C result;
|
C result;
|
||||||
auto pos = s.find_first_not_of(separators, 0);
|
auto pos = s.find_first_not_of(separators, 0);
|
||||||
while (pos != std::string_view::npos) {
|
while (pos != s.npos) {
|
||||||
auto end = s.find_first_of(separators, pos + 1);
|
auto end = s.find_first_of(separators, pos + 1);
|
||||||
if (end == std::string_view::npos) end = s.size();
|
if (end == s.npos) end = s.size();
|
||||||
result.insert(result.end(), std::string(s, pos, end - pos));
|
result.insert(result.end(), std::string(s, pos, end - pos));
|
||||||
pos = s.find_first_not_of(separators, end);
|
pos = s.find_first_not_of(separators, end);
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ template std::vector<std::string> tokenizeString(std::string_view s, std::string
|
||||||
std::string chomp(std::string_view s)
|
std::string chomp(std::string_view s)
|
||||||
{
|
{
|
||||||
size_t i = s.find_last_not_of(" \n\r\t");
|
size_t i = s.find_last_not_of(" \n\r\t");
|
||||||
return i == std::string_view::npos ? "" : std::string(s, 0, i + 1);
|
return i == s.npos ? "" : std::string(s, 0, i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ std::string replaceStrings(
|
||||||
{
|
{
|
||||||
if (from.empty()) return res;
|
if (from.empty()) return res;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while ((pos = res.find(from, pos)) != std::string::npos) {
|
while ((pos = res.find(from, pos)) != res.npos) {
|
||||||
res.replace(pos, from.size(), to);
|
res.replace(pos, from.size(), to);
|
||||||
pos += to.size();
|
pos += to.size();
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ std::string rewriteStrings(std::string s, const StringMap & rewrites)
|
||||||
for (auto & i : rewrites) {
|
for (auto & i : rewrites) {
|
||||||
if (i.first == i.second) continue;
|
if (i.first == i.second) continue;
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
while ((j = s.find(i.first, j)) != std::string::npos)
|
while ((j = s.find(i.first, j)) != s.npos)
|
||||||
s.replace(j, i.first.size(), i.second);
|
s.replace(j, i.first.size(), i.second);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
@ -122,12 +122,11 @@ bool hasSuffix(std::string_view s, std::string_view suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string toLower(const std::string & s)
|
std::string toLower(std::string s)
|
||||||
{
|
{
|
||||||
std::string r(s);
|
for (auto & c : s)
|
||||||
for (auto & c : r)
|
|
||||||
c = std::tolower(c);
|
c = std::tolower(c);
|
||||||
return r;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,7 +134,7 @@ std::string shellEscape(const std::string_view s)
|
||||||
{
|
{
|
||||||
std::string r;
|
std::string r;
|
||||||
r.reserve(s.size() + 2);
|
r.reserve(s.size() + 2);
|
||||||
r += "'";
|
r += '\'';
|
||||||
for (auto & i : s)
|
for (auto & i : s)
|
||||||
if (i == '\'') r += "'\\''"; else r += i;
|
if (i == '\'') r += "'\\''"; else r += i;
|
||||||
r += '\'';
|
r += '\'';
|
||||||
|
@ -184,7 +183,7 @@ std::string base64Encode(std::string_view s)
|
||||||
std::string base64Decode(std::string_view s)
|
std::string base64Decode(std::string_view s)
|
||||||
{
|
{
|
||||||
constexpr char npos = -1;
|
constexpr char npos = -1;
|
||||||
constexpr std::array<char, 256> base64DecodeChars = [&]() {
|
constexpr std::array<char, 256> base64DecodeChars = [&] {
|
||||||
std::array<char, 256> result{};
|
std::array<char, 256> result{};
|
||||||
for (auto& c : result)
|
for (auto& c : result)
|
||||||
c = npos;
|
c = npos;
|
||||||
|
|
|
@ -180,7 +180,7 @@ bool hasSuffix(std::string_view s, std::string_view suffix);
|
||||||
/**
|
/**
|
||||||
* Convert a string to lower case.
|
* Convert a string to lower case.
|
||||||
*/
|
*/
|
||||||
std::string toLower(const std::string & s);
|
std::string toLower(std::string s);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue