From 40b3f64b55f98e03b3173541b8d94cd924099223 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Nov 2006 19:19:59 +0000 Subject: [PATCH] * Skeleton of the privileged worker program. * Some refactoring: put the NAR archive integer/string serialisation code in a separate file so it can be reused by the worker protocol implementation. --- configure.ac | 1 + src/Makefile.am | 2 +- src/libstore/local-store.cc | 4 +- src/libutil/Makefile.am | 6 ++- src/libutil/archive.cc | 88 +++++-------------------------------- src/libutil/archive.hh | 23 ++-------- src/libutil/hash.cc | 2 +- src/libutil/serialise.cc | 87 ++++++++++++++++++++++++++++++++++++ src/libutil/serialise.hh | 71 ++++++++++++++++++++++++++++++ src/nix-store/main.cc | 25 +---------- src/nix-worker/Makefile.am | 9 ++++ src/nix-worker/main.cc | 63 ++++++++++++++++++++++++++ 12 files changed, 255 insertions(+), 126 deletions(-) create mode 100644 src/libutil/serialise.cc create mode 100644 src/libutil/serialise.hh create mode 100644 src/nix-worker/Makefile.am create mode 100644 src/nix-worker/main.cc diff --git a/configure.ac b/configure.ac index b5c0e61b5..8267cc83c 100644 --- a/configure.ac +++ b/configure.ac @@ -266,6 +266,7 @@ AC_CONFIG_FILES([Makefile src/libexpr/Makefile src/nix-instantiate/Makefile src/nix-env/Makefile + src/nix-worker/Makefile src/nix-log2xml/Makefile src/bsdiff-4.3/Makefile scripts/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 2bf789fd3..601e0726b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \ - libexpr nix-instantiate nix-env nix-log2xml bsdiff-4.3 + libexpr nix-instantiate nix-env nix-worker nix-log2xml bsdiff-4.3 EXTRA_DIST = aterm-helper.pl diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 2ae443762..aa8166d7e 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -173,7 +173,7 @@ void createStoreTransaction(Transaction & txn) /* Path copying. */ -struct CopySink : DumpSink +struct CopySink : Sink { string s; virtual void operator () (const unsigned char * data, unsigned int len) @@ -183,7 +183,7 @@ struct CopySink : DumpSink }; -struct CopySource : RestoreSource +struct CopySource : Source { string & s; unsigned int pos; diff --git a/src/libutil/Makefile.am b/src/libutil/Makefile.am index cf75be8a8..bd0996543 100644 --- a/src/libutil/Makefile.am +++ b/src/libutil/Makefile.am @@ -1,10 +1,12 @@ pkglib_LTLIBRARIES = libutil.la -libutil_la_SOURCES = util.cc hash.cc archive.cc aterm.cc aterm-map.cc xml-writer.cc +libutil_la_SOURCES = util.cc hash.cc serialise.cc \ + archive.cc aterm.cc aterm-map.cc xml-writer.cc libutil_la_LIBADD = ../boost/format/libformat.la -pkginclude_HEADERS = util.hh hash.hh archive.hh aterm.hh aterm-map.hh xml-writer.hh types.hh +pkginclude_HEADERS = util.hh hash.hh serialise.hh \ + archive.hh aterm.hh aterm-map.hh xml-writer.hh types.hh if !HAVE_OPENSSL libutil_la_SOURCES += \ diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 32c75fee5..e3bd63db0 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -18,41 +18,10 @@ namespace nix { static string archiveVersion1 = "nix-archive-1"; -static void writePadding(unsigned int len, DumpSink & sink) -{ - if (len % 8) { - unsigned char zero[8]; - memset(zero, 0, sizeof(zero)); - sink(zero, 8 - (len % 8)); - } -} +static void dump(const string & path, Sink & sink); -static void writeInt(unsigned int n, DumpSink & sink) -{ - unsigned char buf[8]; - memset(buf, 0, sizeof(buf)); - buf[0] = n & 0xff; - buf[1] = (n >> 8) & 0xff; - buf[2] = (n >> 16) & 0xff; - buf[3] = (n >> 24) & 0xff; - sink(buf, sizeof(buf)); -} - - -static void writeString(const string & s, DumpSink & sink) -{ - unsigned int len = s.length(); - writeInt(len, sink); - sink((const unsigned char *) s.c_str(), len); - writePadding(len, sink); -} - - -static void dump(const string & path, DumpSink & sink); - - -static void dumpEntries(const Path & path, DumpSink & sink) +static void dumpEntries(const Path & path, Sink & sink) { Strings names = readDirectory(path); vector names2(names.begin(), names.end()); @@ -73,7 +42,7 @@ static void dumpEntries(const Path & path, DumpSink & sink) static void dumpContents(const Path & path, unsigned int size, - DumpSink & sink) + Sink & sink) { writeString("contents", sink); writeInt(size, sink); @@ -95,7 +64,7 @@ static void dumpContents(const Path & path, unsigned int size, } -static void dump(const Path & path, DumpSink & sink) +static void dump(const Path & path, Sink & sink) { struct stat st; if (lstat(path.c_str(), &st)) @@ -132,7 +101,7 @@ static void dump(const Path & path, DumpSink & sink) } -void dumpPath(const Path & path, DumpSink & sink) +void dumpPath(const Path & path, Sink & sink) { writeString(archiveVersion1, sink); dump(path, sink); @@ -145,42 +114,7 @@ static Error badArchive(string s) } -static void readPadding(unsigned int len, RestoreSource & source) -{ - if (len % 8) { - unsigned char zero[8]; - unsigned int n = 8 - (len % 8); - source(zero, n); - for (unsigned int i = 0; i < n; i++) - if (zero[i]) throw badArchive("non-zero padding"); - } -} - -static unsigned int readInt(RestoreSource & source) -{ - unsigned char buf[8]; - source(buf, sizeof(buf)); - if (buf[4] || buf[5] || buf[6] || buf[7]) - throw Error("implementation cannot deal with > 32-bit integers"); - return - buf[0] | - (buf[1] << 8) | - (buf[2] << 16) | - (buf[3] << 24); -} - - -static string readString(RestoreSource & source) -{ - unsigned int len = readInt(source); - char buf[len]; - source((unsigned char *) buf, len); - readPadding(len, source); - return string(buf, len); -} - - -static void skipGeneric(RestoreSource & source) +static void skipGeneric(Source & source) { if (readString(source) == "(") { while (readString(source) != ")") @@ -189,10 +123,10 @@ static void skipGeneric(RestoreSource & source) } -static void restore(const Path & path, RestoreSource & source); +static void restore(const Path & path, Source & source); -static void restoreEntry(const Path & path, RestoreSource & source) +static void restoreEntry(const Path & path, Source & source) { string s, name; @@ -219,7 +153,7 @@ static void restoreEntry(const Path & path, RestoreSource & source) } -static void restoreContents(int fd, const Path & path, RestoreSource & source) +static void restoreContents(int fd, const Path & path, Source & source) { unsigned int size = readInt(source); unsigned int left = size; @@ -238,7 +172,7 @@ static void restoreContents(int fd, const Path & path, RestoreSource & source) } -static void restore(const Path & path, RestoreSource & source) +static void restore(const Path & path, Source & source) { string s; @@ -315,7 +249,7 @@ static void restore(const Path & path, RestoreSource & source) } -void restorePath(const Path & path, RestoreSource & source) +void restorePath(const Path & path, Source & source) { if (readString(source) != archiveVersion1) throw badArchive("expected Nix archive"); diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh index f85d589c6..c70ef3f1c 100644 --- a/src/libutil/archive.hh +++ b/src/libutil/archive.hh @@ -2,6 +2,7 @@ #define __ARCHIVE_H #include "types.hh" +#include "serialise.hh" namespace nix { @@ -44,27 +45,9 @@ namespace nix { `+' denotes string concatenation. */ -struct DumpSink -{ - virtual ~DumpSink() { } - virtual void operator () (const unsigned char * data, unsigned int len) = 0; -}; +void dumpPath(const Path & path, Sink & sink); -void dumpPath(const Path & path, DumpSink & sink); - - -struct RestoreSource -{ - virtual ~RestoreSource() { } - - /* The callee should store exactly *len bytes in the buffer - pointed to by data. It should block if that much data is not - yet available, or throw an error if it is not going to be - available. */ - virtual void operator () (unsigned char * data, unsigned int len) = 0; -}; - -void restorePath(const Path & path, RestoreSource & source); +void restorePath(const Path & path, Source & source); } diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 7381948f2..8dc33f5d0 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -282,7 +282,7 @@ Hash hashFile(HashType ht, const Path & path) } -struct HashSink : DumpSink +struct HashSink : Sink { HashType ht; Ctx ctx; diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc new file mode 100644 index 000000000..aa11c590a --- /dev/null +++ b/src/libutil/serialise.cc @@ -0,0 +1,87 @@ +#include "serialise.hh" +#include "util.hh" + + +namespace nix { + + +void FdSink::operator () (const unsigned char * data, unsigned int len) +{ + writeFull(fd, data, len); +} + + +void FdSource::operator () (unsigned char * data, unsigned int len) +{ + readFull(fd, data, len); +} + + +void writePadding(unsigned int len, Sink & sink) +{ + if (len % 8) { + unsigned char zero[8]; + memset(zero, 0, sizeof(zero)); + sink(zero, 8 - (len % 8)); + } +} + + +void writeInt(unsigned int n, Sink & sink) +{ + unsigned char buf[8]; + memset(buf, 0, sizeof(buf)); + buf[0] = n & 0xff; + buf[1] = (n >> 8) & 0xff; + buf[2] = (n >> 16) & 0xff; + buf[3] = (n >> 24) & 0xff; + sink(buf, sizeof(buf)); +} + + +void writeString(const string & s, Sink & sink) +{ + unsigned int len = s.length(); + writeInt(len, sink); + sink((const unsigned char *) s.c_str(), len); + writePadding(len, sink); +} + + +void readPadding(unsigned int len, Source & source) +{ + if (len % 8) { + unsigned char zero[8]; + unsigned int n = 8 - (len % 8); + source(zero, n); + for (unsigned int i = 0; i < n; i++) + if (zero[i]) throw Error("non-zero padding"); + } +} + + +unsigned int readInt(Source & source) +{ + unsigned char buf[8]; + source(buf, sizeof(buf)); + if (buf[4] || buf[5] || buf[6] || buf[7]) + throw Error("implementation cannot deal with > 32-bit integers"); + return + buf[0] | + (buf[1] << 8) | + (buf[2] << 16) | + (buf[3] << 24); +} + + +string readString(Source & source) +{ + unsigned int len = readInt(source); + char buf[len]; + source((unsigned char *) buf, len); + readPadding(len, source); + return string(buf, len); +} + + +} diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh new file mode 100644 index 000000000..459a693ee --- /dev/null +++ b/src/libutil/serialise.hh @@ -0,0 +1,71 @@ +#ifndef __SERIALISE_H +#define __SERIALISE_H + +#include "types.hh" + + +namespace nix { + + +/* Abstract destination of binary data. */ +struct Sink +{ + virtual ~Sink() { } + virtual void operator () (const unsigned char * data, unsigned int len) = 0; +}; + + +/* Abstract source of binary data. */ +struct Source +{ + virtual ~Source() { } + + /* The callee should store exactly *len bytes in the buffer + pointed to by data. It should block if that much data is not + yet available, or throw an error if it is not going to be + available. */ + virtual void operator () (unsigned char * data, unsigned int len) = 0; +}; + + +/* A sink that writes data to a file descriptor. */ +struct FdSink : Sink +{ + int fd; + + FdSink(int fd) + { + this->fd = fd; + } + + void operator () (const unsigned char * data, unsigned int len); +}; + + +/* A source that reads data from a file descriptor. */ +struct FdSource : Source +{ + int fd; + + FdSource(int fd) + { + this->fd = fd; + } + + void operator () (unsigned char * data, unsigned int len); +}; + + +void writePadding(unsigned int len, Sink & sink); +void writeInt(unsigned int n, Sink & sink); +void writeString(const string & s, Sink & sink); + +void readPadding(unsigned int len, Source & source); +unsigned int readInt(Source & source); +string readString(Source & source); + + +} + + +#endif /* !__SERIALISE_H */ diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index f31814881..c3755c2a1 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -607,17 +607,6 @@ static void opDelete(Strings opFlags, Strings opArgs) } -/* A sink that writes dump output to stdout. */ -struct StdoutSink : DumpSink -{ - virtual void operator () - (const unsigned char * data, unsigned int len) - { - writeFull(STDOUT_FILENO, data, len); - } -}; - - /* Dump a path as a Nix archive. The archive is written to standard output. */ static void opDump(Strings opFlags, Strings opArgs) @@ -625,22 +614,12 @@ static void opDump(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); if (opArgs.size() != 1) throw UsageError("only one argument allowed"); - StdoutSink sink; + FdSink sink(STDOUT_FILENO); string path = *opArgs.begin(); dumpPath(path, sink); } -/* A source that reads restore input from stdin. */ -struct StdinSource : RestoreSource -{ - virtual void operator () (unsigned char * data, unsigned int len) - { - readFull(STDIN_FILENO, data, len); - } -}; - - /* Restore a value from a Nix archive. The archive is read from standard input. */ static void opRestore(Strings opFlags, Strings opArgs) @@ -648,7 +627,7 @@ static void opRestore(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); if (opArgs.size() != 1) throw UsageError("only one argument allowed"); - StdinSource source; + FdSource source(STDIN_FILENO); restorePath(*opArgs.begin(), source); } diff --git a/src/nix-worker/Makefile.am b/src/nix-worker/Makefile.am new file mode 100644 index 000000000..6f10efff5 --- /dev/null +++ b/src/nix-worker/Makefile.am @@ -0,0 +1,9 @@ +libexec_PROGRAMS = nix-worker + +nix_worker_SOURCES = main.cc +nix_worker_LDADD = ../libmain/libmain.la ../libstore/libstore.la ../libutil/libutil.la \ + ../boost/format/libformat.la ${bdb_lib} ${aterm_lib} + +AM_CXXFLAGS = \ + -I$(srcdir)/.. ${bdb_include} $(aterm_include) -I$(srcdir)/../libutil \ + -I$(srcdir)/../libstore -I$(srcdir)/../libmain diff --git a/src/nix-worker/main.cc b/src/nix-worker/main.cc new file mode 100644 index 000000000..4fe92a85a --- /dev/null +++ b/src/nix-worker/main.cc @@ -0,0 +1,63 @@ +#include "shared.hh" +#include "local-store.hh" +#include "util.hh" + +using namespace nix; + + +/* !!! Mostly cut&pasted from util/archive.hh */ +/* Use buffered reads. */ +static unsigned int readInt(int fd) +{ + unsigned char buf[8]; + readFull(fd, buf, sizeof(buf)); + if (buf[4] || buf[5] || buf[6] || buf[7]) + throw Error("implementation cannot deal with > 32-bit integers"); + return + buf[0] | + (buf[1] << 8) | + (buf[2] << 16) | + (buf[3] << 24); +} + + +void processConnection(int fdFrom, int fdTo) +{ + store = openStore(); + + unsigned int magic = readInt(fdFrom); + if (magic != 0x6e697864) throw Error("protocol mismatch"); + + + +} + + +void run(Strings args) +{ + bool slave = false; + bool daemon = false; + + for (Strings::iterator i = args.begin(); i != args.end(); ) { + string arg = *i++; + if (arg == "--slave") slave = true; + } + + if (slave) + processConnection(STDIN_FILENO, STDOUT_FILENO); + + else if (daemon) + throw Error("daemon mode not implemented"); + + else + throw Error("must be run in either --slave or --daemon mode"); + +} + + +void printHelp() +{ +} + + +string programId = "nix-store";