aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2007-02-21 17:34:02 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2007-02-21 17:34:02 +0000
commitbdadb98de8fcd5ed99cca97071741e2775f3ada2 (patch)
treee00b997c3dd90baafeb20fbf2ac2b89e87b2d325 /src
parent0f5da8a83c227879566ed87623617fe195bc6f88 (diff)
* `nix-store --import' now also works in remote mode. The worker
always requires a signature on the archive. This is to ensure that unprivileged users cannot add Trojan horses to the Nix store.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/remote-store.cc30
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/worker-protocol.hh3
-rw-r--r--src/nix-worker/nix-worker.cc36
4 files changed, 62 insertions, 9 deletions
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index dbeb7cf12..1aab90d38 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -256,7 +256,13 @@ void RemoteStore::exportPath(const Path & path, bool sign,
Path RemoteStore::importPath(bool requireSignature, Source & source)
{
- throw Error("not implemented");
+ writeInt(wopImportPath, to);
+ /* We ignore requireSignature, since the worker forces it to true
+ anyway. */
+
+ processStderr(0, &source);
+ Path path = readStorePath(from);
+ return path;
}
@@ -340,16 +346,28 @@ void RemoteStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
}
-void RemoteStore::processStderr(Sink * sink)
+void RemoteStore::processStderr(Sink * sink, Source * source)
{
unsigned int msg;
- while ((msg = readInt(from)) == STDERR_NEXT || msg == STDERR_DATA) {
- string s = readString(from);
- if (msg == STDERR_DATA) {
+ while ((msg = readInt(from)) == STDERR_NEXT
+ || msg == STDERR_READ || msg == STDERR_WRITE) {
+ if (msg == STDERR_WRITE) {
+ string s = readString(from);
if (!sink) throw Error("no sink");
(*sink)((const unsigned char *) s.c_str(), s.size());
}
- else writeToStderr((const unsigned char *) s.c_str(), s.size());
+ else if (msg == STDERR_READ) {
+ if (!source) throw Error("no source");
+ unsigned int len = readInt(from);
+ unsigned char * buf = new unsigned char[len];
+ AutoDeleteArray<unsigned char> d(buf);
+ (*source)(buf, len);
+ writeString(string((const char *) buf, len), to);
+ }
+ else {
+ string s = readString(from);
+ writeToStderr((const unsigned char *) s.c_str(), s.size());
+ }
}
if (msg == STDERR_ERROR)
throw Error(readString(from));
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index f57dcbd93..19af8c0be 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -70,7 +70,7 @@ private:
FdSource from;
Pid child;
- void processStderr(Sink * sink = 0);
+ void processStderr(Sink * sink = 0, Source * source = 0);
void forkSlave();
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index e48fd5fe9..0126c8d59 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -32,7 +32,8 @@ typedef enum {
#define STDERR_NEXT 0x6f6c6d67
-#define STDERR_DATA 0x64617461
+#define STDERR_READ 0x64617461 // data needed from source
+#define STDERR_WRITE 0x64617416 // data for sink
#define STDERR_LAST 0x616c7473
#define STDERR_ERROR 0x63787470
diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc
index 04578a8b8..6e4c6e4a9 100644
--- a/src/nix-worker/nix-worker.cc
+++ b/src/nix-worker/nix-worker.cc
@@ -187,12 +187,37 @@ struct TunnelSink : Sink
virtual void operator ()
(const unsigned char * data, unsigned int len)
{
- writeInt(STDERR_DATA, to);
+ writeInt(STDERR_WRITE, to);
writeString(string((const char *) data, len), to);
}
};
+struct TunnelSource : Source
+{
+ Source & from;
+ TunnelSource(Source & from) : from(from)
+ {
+ }
+ virtual void operator ()
+ (unsigned char * data, unsigned int len)
+ {
+ /* Careful: we're going to receive data from the client now,
+ so we have to disable the SIGPOLL handler. */
+ setSigPollAction(false);
+ canSendStderr = false;
+
+ writeInt(STDERR_READ, to);
+ writeInt(len, to);
+ string s = readString(from);
+ if (s.size() != len) throw Error("not enough data");
+ memcpy(data, (const unsigned char *) s.c_str(), len);
+
+ startWork();
+ }
+};
+
+
static void performOp(Source & from, Sink & to, unsigned int op)
{
switch (op) {
@@ -289,6 +314,15 @@ static void performOp(Source & from, Sink & to, unsigned int op)
break;
}
+ case wopImportPath: {
+ startWork();
+ TunnelSource source(from);
+ Path path = store->importPath(true, source);
+ stopWork();
+ writeString(path, to);
+ break;
+ }
+
case wopBuildDerivations: {
PathSet drvs = readStorePaths(from);
startWork();