* 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.
This commit is contained in:
Eelco Dolstra 2006-11-30 19:19:59 +00:00
parent 9adc074dc3
commit 40b3f64b55
12 changed files with 255 additions and 126 deletions

View file

@ -266,6 +266,7 @@ AC_CONFIG_FILES([Makefile
src/libexpr/Makefile src/libexpr/Makefile
src/nix-instantiate/Makefile src/nix-instantiate/Makefile
src/nix-env/Makefile src/nix-env/Makefile
src/nix-worker/Makefile
src/nix-log2xml/Makefile src/nix-log2xml/Makefile
src/bsdiff-4.3/Makefile src/bsdiff-4.3/Makefile
scripts/Makefile scripts/Makefile

View file

@ -1,5 +1,5 @@
SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \ 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 EXTRA_DIST = aterm-helper.pl

View file

@ -173,7 +173,7 @@ void createStoreTransaction(Transaction & txn)
/* Path copying. */ /* Path copying. */
struct CopySink : DumpSink struct CopySink : Sink
{ {
string s; string s;
virtual void operator () (const unsigned char * data, unsigned int len) 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; string & s;
unsigned int pos; unsigned int pos;

View file

@ -1,10 +1,12 @@
pkglib_LTLIBRARIES = libutil.la 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 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 if !HAVE_OPENSSL
libutil_la_SOURCES += \ libutil_la_SOURCES += \

View file

@ -18,41 +18,10 @@ namespace nix {
static string archiveVersion1 = "nix-archive-1"; static string archiveVersion1 = "nix-archive-1";
static void writePadding(unsigned int len, DumpSink & sink) static void dump(const string & path, Sink & sink);
{
if (len % 8) {
unsigned char zero[8];
memset(zero, 0, sizeof(zero));
sink(zero, 8 - (len % 8));
}
}
static void writeInt(unsigned int n, DumpSink & sink) static void dumpEntries(const Path & path, 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));
}
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)
{ {
Strings names = readDirectory(path); Strings names = readDirectory(path);
vector<string> names2(names.begin(), names.end()); vector<string> 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, static void dumpContents(const Path & path, unsigned int size,
DumpSink & sink) Sink & sink)
{ {
writeString("contents", sink); writeString("contents", sink);
writeInt(size, 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; struct stat st;
if (lstat(path.c_str(), &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); writeString(archiveVersion1, sink);
dump(path, sink); dump(path, sink);
@ -145,42 +114,7 @@ static Error badArchive(string s)
} }
static void readPadding(unsigned int len, RestoreSource & source) static void skipGeneric(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 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)
{ {
if (readString(source) == "(") { if (readString(source) == "(") {
while (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; 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 size = readInt(source);
unsigned int left = size; 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; 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) if (readString(source) != archiveVersion1)
throw badArchive("expected Nix archive"); throw badArchive("expected Nix archive");

View file

@ -2,6 +2,7 @@
#define __ARCHIVE_H #define __ARCHIVE_H
#include "types.hh" #include "types.hh"
#include "serialise.hh"
namespace nix { namespace nix {
@ -44,27 +45,9 @@ namespace nix {
`+' denotes string concatenation. */ `+' denotes string concatenation. */
struct DumpSink void dumpPath(const Path & path, Sink & sink);
{
virtual ~DumpSink() { }
virtual void operator () (const unsigned char * data, unsigned int len) = 0;
};
void dumpPath(const Path & path, DumpSink & sink); void restorePath(const Path & path, Source & source);
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);
} }

View file

@ -282,7 +282,7 @@ Hash hashFile(HashType ht, const Path & path)
} }
struct HashSink : DumpSink struct HashSink : Sink
{ {
HashType ht; HashType ht;
Ctx ctx; Ctx ctx;

87
src/libutil/serialise.cc Normal file
View file

@ -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);
}
}

71
src/libutil/serialise.hh Normal file
View file

@ -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 */

View file

@ -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 /* Dump a path as a Nix archive. The archive is written to standard
output. */ output. */
static void opDump(Strings opFlags, Strings opArgs) 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 (!opFlags.empty()) throw UsageError("unknown flag");
if (opArgs.size() != 1) throw UsageError("only one argument allowed"); if (opArgs.size() != 1) throw UsageError("only one argument allowed");
StdoutSink sink; FdSink sink(STDOUT_FILENO);
string path = *opArgs.begin(); string path = *opArgs.begin();
dumpPath(path, sink); 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 /* Restore a value from a Nix archive. The archive is read from
standard input. */ standard input. */
static void opRestore(Strings opFlags, Strings opArgs) 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 (!opFlags.empty()) throw UsageError("unknown flag");
if (opArgs.size() != 1) throw UsageError("only one argument allowed"); if (opArgs.size() != 1) throw UsageError("only one argument allowed");
StdinSource source; FdSource source(STDIN_FILENO);
restorePath(*opArgs.begin(), source); restorePath(*opArgs.begin(), source);
} }

View file

@ -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

63
src/nix-worker/main.cc Normal file
View file

@ -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";