aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/local-store.cc22
-rw-r--r--src/libstore/remote-store.cc23
-rw-r--r--src/libstore/remote-store.hh4
-rw-r--r--src/libstore/ssh-store.cc1
-rw-r--r--src/libstore/store-api.cc53
-rw-r--r--src/libstore/store-api.hh10
-rw-r--r--src/nix-daemon/nix-daemon.cc37
-rw-r--r--src/nix/doctor.cc4
-rw-r--r--tests/local.mk1
-rw-r--r--tests/ssh-relay.sh16
10 files changed, 83 insertions, 88 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index a79b2da44..84f8d7752 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -1533,5 +1533,27 @@ void LocalStore::createUser(const std::string & userName, uid_t userId)
}
}
+static bool isNonUriPath(const std::string & spec) {
+ return
+ // is not a URL
+ spec.find("://") == std::string::npos
+ // Has at least one path separator, and so isn't a single word that
+ // might be special like "auto"
+ && spec.find("/") != std::string::npos;
+}
+
+static RegisterStoreImplementation regStore([](
+ const std::string & uri, const Store::Params & params)
+ -> std::shared_ptr<Store>
+{
+ Store::Params params2 = params;
+ if (uri == "local") {
+ } else if (isNonUriPath(uri)) {
+ params2["root"] = absPath(uri);
+ } else {
+ return nullptr;
+ }
+ return std::shared_ptr<Store>(std::make_shared<LocalStore>(params2));
+});
}
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index dc61951d3..d890042bb 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -96,7 +96,16 @@ RemoteStore::RemoteStore(const Params & params)
: Store(params)
, connections(make_ref<Pool<Connection>>(
std::max(1, (int) maxConnections),
- [this]() { return openConnectionWrapper(); },
+ [this]() {
+ auto conn = openConnectionWrapper();
+ try {
+ initConnection(*conn);
+ } catch (...) {
+ failed = true;
+ throw;
+ }
+ return conn;
+ },
[this](const ref<Connection> & r) {
return
r->to.good()
@@ -179,8 +188,6 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
conn->startTime = std::chrono::steady_clock::now();
- initConnection(*conn);
-
return conn;
}
@@ -982,14 +989,18 @@ std::exception_ptr RemoteStore::Connection::processStderr(Sink * sink, Source *
return nullptr;
}
-static std::string uriScheme = "unix://";
+static std::string_view uriScheme = "unix://";
static RegisterStoreImplementation regStore([](
const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store>
{
- if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0;
- return std::make_shared<UDSRemoteStore>(std::string(uri, uriScheme.size()), params);
+ if (hasPrefix(uri, uriScheme))
+ return std::make_shared<UDSRemoteStore>(std::string(uri, uriScheme.size()), params);
+ else if (uri == "daemon")
+ return std::make_shared<UDSRemoteStore>(params);
+ else
+ return nullptr;
});
}
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 6f05f2197..eaeb68e57 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -102,8 +102,6 @@ public:
void flushBadConnections();
-protected:
-
struct Connection
{
AutoCloseFD fd;
@@ -119,6 +117,8 @@ protected:
ref<Connection> openConnectionWrapper();
+protected:
+
virtual ref<Connection> openConnection() = 0;
void initConnection(Connection & conn);
diff --git a/src/libstore/ssh-store.cc b/src/libstore/ssh-store.cc
index 6cb97c1f1..046b5710a 100644
--- a/src/libstore/ssh-store.cc
+++ b/src/libstore/ssh-store.cc
@@ -72,7 +72,6 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
+ (remoteStore.get() == "" ? "" : " --store " + shellEscape(remoteStore.get())));
conn->to = FdSink(conn->sshConn->in.get());
conn->from = FdSource(conn->sshConn->out.get());
- initConnection(*conn);
return conn;
}
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index a41441079..ba4459bbe 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -1046,51 +1046,24 @@ ref<Store> openStore(const std::string & uri_,
throw Error("don't know how to open Nix store '%s'", uri);
}
-static bool isNonUriPath(const std::string & spec) {
- return
- // is not a URL
- spec.find("://") == std::string::npos
- // Has at least one path separator, and so isn't a single word that
- // might be special like "auto"
- && spec.find("/") != std::string::npos;
-}
-
-StoreType getStoreType(const std::string & uri, const std::string & stateDir)
-{
- if (uri == "daemon") {
- return tDaemon;
- } else if (uri == "local" || isNonUriPath(uri)) {
- return tLocal;
- } else if (uri == "" || uri == "auto") {
- if (access(stateDir.c_str(), R_OK | W_OK) == 0)
- return tLocal;
- else if (pathExists(settings.nixDaemonSocketFile))
- return tDaemon;
- else
- return tLocal;
- } else {
- return tOther;
- }
-}
-
+// Specific prefixes are handled by the specific types of store, while here we
+// handle the general cases not covered by the other ones.
static RegisterStoreImplementation regStore([](
const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store>
{
- switch (getStoreType(uri, get(params, "state").value_or(settings.nixStateDir))) {
- case tDaemon:
- return std::shared_ptr<Store>(std::make_shared<UDSRemoteStore>(params));
- case tLocal: {
- Store::Params params2 = params;
- if (isNonUriPath(uri)) {
- params2["root"] = absPath(uri);
- }
- return std::shared_ptr<Store>(std::make_shared<LocalStore>(params2));
- }
- default:
- return nullptr;
- }
+ auto stateDir = get(params, "state").value_or(settings.nixStateDir);
+ if (uri == "" || uri == "auto") {
+ if (access(stateDir.c_str(), R_OK | W_OK) == 0)
+ return std::make_shared<LocalStore>(params);
+ else if (pathExists(settings.nixDaemonSocketFile))
+ return std::make_shared<UDSRemoteStore>(params);
+ else
+ return std::make_shared<LocalStore>(params);
+ } else {
+ return nullptr;
+ }
});
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 61aa3ba7e..52f0916f2 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -728,16 +728,6 @@ ref<Store> openStore(const std::string & uri = settings.storeUri.get(),
const Store::Params & extraParams = Store::Params());
-enum StoreType {
- tDaemon,
- tLocal,
- tOther
-};
-
-
-StoreType getStoreType(const std::string & uri = settings.storeUri.get(),
- const std::string & stateDir = settings.nixStateDir);
-
/* Return the default substituter stores, defined by the
‘substituters’ option and various legacy options. */
std::list<ref<Store>> getDefaultSubstituters();
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index cfa634a44..6e652ccbf 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -1,5 +1,6 @@
#include "shared.hh"
#include "local-store.hh"
+#include "remote-store.hh"
#include "util.hh"
#include "serialise.hh"
#include "archive.hh"
@@ -285,44 +286,28 @@ static int _main(int argc, char * * argv)
initPlugins();
if (stdio) {
- if (getStoreType() == tDaemon) {
- // Forward on this connection to the real daemon
- auto socketPath = settings.nixDaemonSocketFile;
- auto s = socket(PF_UNIX, SOCK_STREAM, 0);
- if (s == -1)
- throw SysError("creating Unix domain socket");
-
- auto socketDir = dirOf(socketPath);
- if (chdir(socketDir.c_str()) == -1)
- throw SysError("changing to socket directory '%1%'", socketDir);
-
- auto socketName = std::string(baseNameOf(socketPath));
- auto addr = sockaddr_un{};
- addr.sun_family = AF_UNIX;
- if (socketName.size() + 1 >= sizeof(addr.sun_path))
- throw Error("socket name %1% is too long", socketName);
- strcpy(addr.sun_path, socketName.c_str());
-
- if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) == -1)
- throw SysError("cannot connect to daemon at %1%", socketPath);
-
- auto nfds = (s > STDIN_FILENO ? s : STDIN_FILENO) + 1;
+ if (auto store = openUncachedStore().dynamic_pointer_cast<RemoteStore>()) {
+ auto conn = store->openConnectionWrapper();
+ int from = conn->from.fd;
+ int to = conn->to.fd;
+
+ auto nfds = std::max(from, STDIN_FILENO) + 1;
while (true) {
fd_set fds;
FD_ZERO(&fds);
- FD_SET(s, &fds);
+ FD_SET(from, &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(s, &fds)) {
- auto res = splice(s, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
+ if (FD_ISSET(from, &fds)) {
+ auto res = splice(from, nullptr, STDOUT_FILENO, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
if (res == -1)
throw SysError("splicing data from daemon socket to stdout");
else if (res == 0)
throw EndOfFile("unexpected EOF from daemon socket");
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
- auto res = splice(STDIN_FILENO, nullptr, s, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
+ auto res = splice(STDIN_FILENO, nullptr, to, nullptr, SSIZE_MAX, SPLICE_F_MOVE);
if (res == -1)
throw SysError("splicing data from stdin to daemon socket");
else if (res == 0)
diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc
index 82e92cdd0..683e91446 100644
--- a/src/nix/doctor.cc
+++ b/src/nix/doctor.cc
@@ -49,9 +49,7 @@ struct CmdDoctor : StoreCommand
{
logger->log("Running checks against store uri: " + store->getUri());
- auto type = getStoreType();
-
- if (type < tOther) {
+ if (store.dynamic_pointer_cast<LocalFSStore>()) {
success &= checkNixInPath();
success &= checkProfileRoots(store);
}
diff --git a/tests/local.mk b/tests/local.mk
index 53035da41..fd9438386 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -15,6 +15,7 @@ nix_tests = \
linux-sandbox.sh \
build-dry.sh \
build-remote-input-addressed.sh \
+ ssh-relay.sh \
nar-access.sh \
structured-attrs.sh \
fetchGit.sh \
diff --git a/tests/ssh-relay.sh b/tests/ssh-relay.sh
new file mode 100644
index 000000000..dce50974b
--- /dev/null
+++ b/tests/ssh-relay.sh
@@ -0,0 +1,16 @@
+source common.sh
+
+echo foo > $TEST_ROOT/hello.sh
+
+ssh_localhost=ssh://localhost
+remote_store=?remote-store=$ssh_localhost
+
+store=$ssh_localhost
+
+store+=$remote_store
+store+=$remote_store
+store+=$remote_store
+
+out=$(nix add-to-store --store "$store" $TEST_ROOT/hello.sh)
+
+[ foo = $(< $out) ]