* 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:
		
							parent
							
								
									9adc074dc3
								
							
						
					
					
						commit
						40b3f64b55
					
				
					 12 changed files with 255 additions and 126 deletions
				
			
		|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 += \ | ||||
|  |  | |||
|  | @ -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"); | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|   | ||||
| } | ||||
|  |  | |||
|  | @ -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
									
								
							
							
						
						
									
										87
									
								
								src/libutil/serialise.cc
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										71
									
								
								src/libutil/serialise.hh
									
										
									
									
									
										Normal 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 */ | ||||
|  | @ -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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										9
									
								
								src/nix-worker/Makefile.am
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/nix-worker/Makefile.am
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										63
									
								
								src/nix-worker/main.cc
									
										
									
									
									
										Normal 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"; | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue