diff --git a/third_party/nix/doc/manual/command-ref/nix-daemon.xml b/third_party/nix/doc/manual/command-ref/nix-daemon.xml
index a2161f033..9159d15d1 100644
--- a/third_party/nix/doc/manual/command-ref/nix-daemon.xml
+++ b/third_party/nix/doc/manual/command-ref/nix-daemon.xml
@@ -30,6 +30,22 @@ performs build actions and other operations on the Nix store on behalf
of unprivileged users.
+
+
+Options
+
+
+
+
+
+ Causes the nix daemon to forward stdin and stdout to and
+ from the actual daemon socket. This is used when communicating with a remote
+ store over SSH
+
+
+
+
+
diff --git a/third_party/nix/misc/systemd/nix-daemon.service.in b/third_party/nix/misc/systemd/nix-daemon.service.in
index 25655204d..c3d2a4a39 100644
--- a/third_party/nix/misc/systemd/nix-daemon.service.in
+++ b/third_party/nix/misc/systemd/nix-daemon.service.in
@@ -5,7 +5,7 @@ RequiresMountsFor=@localstatedir@
ConditionPathIsReadWrite=@localstatedir@/nix/daemon-socket
[Service]
-ExecStart=@@bindir@/nix-daemon nix-daemon --daemon
+ExecStart=@@bindir@/nix-daemon nix-daemon
KillMode=process
[Install]
diff --git a/third_party/nix/src/CMakeLists.txt b/third_party/nix/src/CMakeLists.txt
index 3775333ee..a142bfafb 100644
--- a/third_party/nix/src/CMakeLists.txt
+++ b/third_party/nix/src/CMakeLists.txt
@@ -61,8 +61,8 @@ target_sources(nix
nix-channel/nix-channel.cc
nix-collect-garbage/nix-collect-garbage.cc
nix-copy-closure/nix-copy-closure.cc
- nix-daemon/nix-daemon.cc
nix-daemon/nix-daemon-proto.cc
+ nix-daemon/nix-daemon-main.cc
nix-env/nix-env.cc
nix-env/user-env.cc
nix-instantiate/nix-instantiate.cc
diff --git a/third_party/nix/src/libstore/derivations.cc b/third_party/nix/src/libstore/derivations.cc
index 419fc584f..18b313385 100644
--- a/third_party/nix/src/libstore/derivations.cc
+++ b/third_party/nix/src/libstore/derivations.cc
@@ -31,11 +31,11 @@ void DerivationOutput::parseHashInfo(bool& recursive, Hash& hash) const {
}
BasicDerivation BasicDerivation::from_proto(
- const nix::proto::Derivation* proto_derivation, const nix::Store* store) {
+ const nix::proto::Derivation* proto_derivation, const nix::Store& store) {
BasicDerivation result;
result.platform = proto_derivation->platform();
result.builder = proto_derivation->builder().path();
- store->assertStorePath(result.builder);
+ store.assertStorePath(result.builder);
result.outputs.insert(proto_derivation->outputs().begin(),
proto_derivation->outputs().end());
diff --git a/third_party/nix/src/libstore/derivations.hh b/third_party/nix/src/libstore/derivations.hh
index d8a5dbf09..21ef71372 100644
--- a/third_party/nix/src/libstore/derivations.hh
+++ b/third_party/nix/src/libstore/derivations.hh
@@ -59,7 +59,7 @@ struct BasicDerivation {
// Convert the given proto derivation to a BasicDerivation in the given
// nix::Store.
static BasicDerivation from_proto(
- const nix::proto::Derivation* proto_derivation, const nix::Store* store);
+ const nix::proto::Derivation* proto_derivation, const nix::Store& store);
virtual ~BasicDerivation(){};
diff --git a/third_party/nix/src/libstore/ssh-store.cc b/third_party/nix/src/libstore/ssh-store.cc
index eae8ee888..48fea858a 100644
--- a/third_party/nix/src/libstore/ssh-store.cc
+++ b/third_party/nix/src/libstore/ssh-store.cc
@@ -67,7 +67,7 @@ ref SSHStore::getFSAccessor() {
ref SSHStore::openConnection() {
auto conn = make_ref();
- conn->sshConn = master.startCommand("nix-daemon --stdio");
+ conn->sshConn = master.startCommand("nix-daemon --pipe");
conn->to = FdSink(conn->sshConn->in.get());
conn->from = FdSource(conn->sshConn->out.get());
initConnection(*conn);
diff --git a/third_party/nix/src/libutil/util.cc b/third_party/nix/src/libutil/util.cc
index f69c341c2..75a8e73ea 100644
--- a/third_party/nix/src/libutil/util.cc
+++ b/third_party/nix/src/libutil/util.cc
@@ -167,6 +167,7 @@ Path canonPath(const Path& path, bool resolveSymlinks) {
return s.empty() ? "/" : s;
}
+// TODO(grfn) remove in favor of std::filesystem::path::parent_path()
Path dirOf(absl::string_view path) {
Path::size_type pos = path.rfind('/');
if (pos == std::string::npos) {
@@ -175,6 +176,7 @@ Path dirOf(absl::string_view path) {
return pos == 0 ? "/" : Path(path, 0, pos);
}
+// TODO(grfn) remove in favor of std::filesystem::path::root_name()
std::string baseNameOf(const Path& path) {
if (path.empty()) {
return "";
@@ -558,6 +560,7 @@ Path getDataDir() {
return dataDir;
}
+// TODO(grfn): Remove in favor of std::filesystem::create_directories
Paths createDirs(const Path& path) {
Paths created;
if (path == "/") {
diff --git a/third_party/nix/src/nix-daemon/nix-daemon-main.cc b/third_party/nix/src/nix-daemon/nix-daemon-main.cc
new file mode 100644
index 000000000..e492c343b
--- /dev/null
+++ b/third_party/nix/src/nix-daemon/nix-daemon-main.cc
@@ -0,0 +1,143 @@
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "libmain/shared.hh"
+#include "libstore/globals.hh"
+#include "libstore/store-api.hh"
+#include "libutil/util.hh"
+#include "nix-daemon-proto.hh"
+#include "nix-daemon/nix-daemon-proto.hh"
+#include "nix/legacy.hh"
+
+namespace nix::daemon {
+
+using grpc::Server;
+using grpc_impl::ServerBuilder;
+
+// TODO(grfn): There has to be a better way to do this - this was ported
+// verbatim from the old daemon implementation without much critical evaluation.
+static int ForwardToSocket(nix::Path socket_path) {
+ // Forward on this connection to the real daemon
+ int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sockfd == -1) {
+ throw SysError("creating Unix domain socket");
+ }
+
+ auto socketDir = dirOf(socket_path);
+ if (chdir(socketDir.c_str()) == -1) {
+ throw SysError(format("changing to socket directory '%1%'") % socketDir);
+ }
+
+ auto socketName = baseNameOf(socket_path);
+ auto addr = sockaddr_un{};
+ addr.sun_family = AF_UNIX;
+ if (socketName.size() + 1 >= sizeof(addr.sun_path)) {
+ throw Error(format("socket name %1% is too long") % socketName);
+ }
+ strncpy(addr.sun_path, socketName.c_str(), sizeof(addr.sun_family));
+
+ if (connect(sockfd, reinterpret_cast(&addr),
+ sizeof(addr)) == -1) {
+ throw SysError(format("cannot connect to daemon at %1%") % socket_path);
+ }
+
+ auto nfds = (sockfd > STDIN_FILENO ? sockfd : STDIN_FILENO) + 1;
+ while (true) {
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(sockfd, &fds);
+ FD_SET(STDIN_FILENO, &fds);
+ if (select(nfds, &fds, nullptr, nullptr, nullptr) == -1) {
+ throw SysError("waiting for data from client or server");
+ }
+ if (FD_ISSET(sockfd, &fds)) {
+ auto res = splice(sockfd, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX,
+ SPLICE_F_MOVE);
+ if (res == -1) {
+ throw SysError("splicing data from daemon socket to stdout");
+ }
+ if (res == 0) {
+ throw EndOfFile("unexpected EOF from daemon socket");
+ }
+ }
+ if (FD_ISSET(STDIN_FILENO, &fds)) {
+ auto res = splice(STDIN_FILENO, nullptr, sockfd, nullptr, SSIZE_MAX,
+ SPLICE_F_MOVE);
+ if (res == -1) {
+ throw SysError("splicing data from stdin to daemon socket");
+ }
+ if (res == 0) {
+ return 0;
+ }
+ }
+ }
+}
+
+int RunServer() {
+ Store::Params params;
+ params["path-info-cache-size"] = "0";
+ auto store = openStore(settings.storeUri, params);
+ auto worker = NewWorkerService(*store);
+
+ std::filesystem::path socket_path(settings.nixDaemonSocketFile);
+ std::filesystem::create_directories(socket_path.parent_path());
+ auto socket_addr = absl::StrFormat("unix://%s", socket_path);
+
+ ServerBuilder builder;
+ builder.AddListeningPort(socket_addr, grpc::InsecureServerCredentials());
+ builder.RegisterService(worker);
+
+ std::unique_ptr server(builder.BuildAndStart());
+ if (server) {
+ LOG(INFO) << "Nix daemon listening at " << socket_addr;
+ server->Wait();
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static int main_(int argc, char** argv) {
+ auto pipe = false;
+
+ // TODO(grfn): Replace with absl::flags
+ parseCmdLine(argc, argv,
+ [&](Strings::iterator& arg, const Strings::iterator& end) {
+ if (*arg == "--help") {
+ showManPage("nix-daemon");
+ } else if (*arg == "--version") {
+ printVersion("nix-daemon");
+ } else if (*arg == "--pipe") {
+ // Causes the daemon to forward stdin and stdout to and from
+ // the actual daemon socket
+ pipe = true;
+ } else {
+ return false;
+ }
+ return true;
+ });
+
+ if (pipe) {
+ if (getStoreType() == tDaemon) {
+ return ForwardToSocket(settings.nixDaemonSocketFile);
+ } else {
+ // TODO(grfn): Need to launch a server on stdin here - upstream calls
+ // processConnection(true, "root", 0);
+ throw "Not implemented";
+ }
+ }
+ return RunServer();
+}
+
+// TODO(grfn): Replace this with something less magical
+static RegisterLegacyCommand s1("nix-daemon", main_);
+
+} // namespace nix::daemon
diff --git a/third_party/nix/src/nix-daemon/nix-daemon-proto.cc b/third_party/nix/src/nix-daemon/nix-daemon-proto.cc
index ffd34cc60..d382964a7 100644
--- a/third_party/nix/src/nix-daemon/nix-daemon-proto.cc
+++ b/third_party/nix/src/nix-daemon/nix-daemon-proto.cc
@@ -26,7 +26,7 @@ static Status INVALID_STORE_PATH =
class WorkerServiceImpl final : public WorkerService::Service {
public:
- WorkerServiceImpl(nix::Store* store) : store_(store) {}
+ WorkerServiceImpl(nix::Store& store) : store_(&store) {}
Status IsValidPath(grpc::ServerContext* context, const StorePath* request,
nix::proto::IsValidPathResponse* response) override {
@@ -221,7 +221,7 @@ class WorkerServiceImpl final : public WorkerService::Service {
nix::proto::BuildDerivationResponse* response) override {
auto drv_path = request->drv_path().path();
store_->assertStorePath(drv_path);
- auto drv = BasicDerivation::from_proto(&request->derivation(), store_);
+ auto drv = BasicDerivation::from_proto(&request->derivation(), *store_);
auto build_mode = nix::build_mode_from(request->build_mode());
if (!build_mode) {
@@ -282,12 +282,11 @@ class WorkerServiceImpl final : public WorkerService::Service {
};
private:
- // TODO(tazjin): Who owns the store?
- nix::Store* store_;
+ ref store_;
};
-std::unique_ptr NewWorkerService(nix::Store* store) {
- return std::make_unique(store);
+WorkerService::Service* NewWorkerService(nix::Store& store) {
+ return new WorkerServiceImpl(store);
}
} // namespace nix::daemon
diff --git a/third_party/nix/src/nix-daemon/nix-daemon-proto.hh b/third_party/nix/src/nix-daemon/nix-daemon-proto.hh
index 5ffab9ebb..ca871213e 100644
--- a/third_party/nix/src/nix-daemon/nix-daemon-proto.hh
+++ b/third_party/nix/src/nix-daemon/nix-daemon-proto.hh
@@ -7,7 +7,6 @@
namespace nix::daemon {
-std::unique_ptr NewWorkerService(
- nix::Store*);
+nix::proto::WorkerService::Service* NewWorkerService(nix::Store&);
} // namespace nix::daemon