* 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/nix-instantiate/Makefile
src/nix-env/Makefile
src/nix-worker/Makefile
src/nix-log2xml/Makefile
src/bsdiff-4.3/Makefile
scripts/Makefile

View file

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

View file

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

View file

@ -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 += \

View file

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

View file

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

View file

@ -282,7 +282,7 @@ Hash hashFile(HashType ht, const Path & path)
}
struct HashSink : DumpSink
struct HashSink : Sink
{
HashType ht;
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
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);
}

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