diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/Makefile.am | 2 | ||||
-rw-r--r-- | src/libutil/archive.cc | 8 | ||||
-rw-r--r-- | src/libutil/archive.hh | 1 | ||||
-rw-r--r-- | src/libutil/hash.cc | 17 | ||||
-rw-r--r-- | src/libutil/hash.hh | 10 | ||||
-rw-r--r-- | src/libutil/types.hh | 7 | ||||
-rw-r--r-- | src/libutil/util.cc | 59 | ||||
-rw-r--r-- | src/libutil/util.hh | 11 |
8 files changed, 71 insertions, 44 deletions
diff --git a/src/libutil/Makefile.am b/src/libutil/Makefile.am index aa862208c6f9..98f32633b894 100644 --- a/src/libutil/Makefile.am +++ b/src/libutil/Makefile.am @@ -3,7 +3,7 @@ pkglib_LTLIBRARIES = libutil.la libutil_la_SOURCES = util.cc hash.cc serialise.cc \ archive.cc xml-writer.cc -libutil_la_LIBADD = ../boost/format/libformat.la +libutil_la_LIBADD = ../boost/format/libformat.la ${aterm_lib} ${sqlite_lib} pkginclude_HEADERS = util.hh hash.hh serialise.hh \ archive.hh xml-writer.hh types.hh diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 8fde4328c47e..999b17cd2f19 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -181,8 +181,6 @@ static void parseContents(ParseSink & sink, Source & source, const Path & path) left -= n; } - sink.finalizeContents(size); - readPadding(size, source); } @@ -317,12 +315,6 @@ struct RestoreSink : ParseSink writeFull(fd, data, len); } - void finalizeContents(unsigned long long size) - { - errno = ftruncate(fd, size); - if (errno) throw SysError(format("truncating file to its allocated length of %1% bytes") % size); - } - void createSymlink(const Path & path, const string & target) { Path p = dstPath + path; diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh index f358a2a6be17..fff62031397c 100644 --- a/src/libutil/archive.hh +++ b/src/libutil/archive.hh @@ -64,7 +64,6 @@ struct ParseSink virtual void isExecutable() { }; virtual void preallocateContents(unsigned long long size) { }; virtual void receiveContents(unsigned char * data, unsigned int len) { }; - virtual void finalizeContents(unsigned long long size) { }; virtual void createSymlink(const Path & path, const string & target) { }; }; diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index eef01fe4d609..b9e7846992f6 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -286,9 +286,18 @@ Hash hashFile(HashType ht, const Path & path) HashSink::HashSink(HashType ht) : ht(ht) { ctx = new Ctx; + bytes = 0; start(ht, *ctx); } +HashSink::HashSink(const HashSink & h) +{ + ht = h.ht; + bytes = h.bytes; + ctx = new Ctx; + *ctx = *h.ctx; +} + HashSink::~HashSink() { delete ctx; @@ -297,18 +306,20 @@ HashSink::~HashSink() void HashSink::operator () (const unsigned char * data, unsigned int len) { + bytes += len; update(ht, *ctx, data, len); } -Hash HashSink::finish() +HashResult HashSink::finish() { Hash hash(ht); nix::finish(ht, *ctx, hash.hash); - return hash; + return HashResult(hash, bytes); } -Hash hashPath(HashType ht, const Path & path, PathFilter & filter) +HashResult hashPath( + HashType ht, const Path & path, PathFilter & filter) { HashSink sink(ht); dumpPath(path, sink, filter); diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index 062d97254bfc..13740954d625 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -40,7 +40,6 @@ struct Hash /* For sorting. */ bool operator < (const Hash & h) const; - }; @@ -72,7 +71,8 @@ Hash hashFile(HashType ht, const Path & path); (essentially) hashString(ht, dumpPath(path)). */ struct PathFilter; extern PathFilter defaultPathFilter; -Hash hashPath(HashType ht, const Path & path, +typedef std::pair<Hash, unsigned long long> HashResult; +HashResult hashPath(HashType ht, const Path & path, PathFilter & filter = defaultPathFilter); /* Compress a hash to the specified number of bytes by cyclically @@ -93,16 +93,18 @@ class HashSink : public Sink private: HashType ht; Ctx * ctx; + unsigned long long bytes; public: HashSink(HashType ht); + HashSink(const HashSink & h); ~HashSink(); virtual void operator () (const unsigned char * data, unsigned int len); - Hash finish(); + HashResult finish(); }; } - + #endif /* !__HASH_H */ diff --git a/src/libutil/types.hh b/src/libutil/types.hh index f110188da151..844ad6f76a13 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -27,7 +27,8 @@ protected: string prefix_; // used for location traces etc. string err; public: - BaseError(const format & f); + unsigned int status; // exit status + BaseError(const format & f, unsigned int status = 1); ~BaseError() throw () { }; const char * what() const throw () { return err.c_str(); } const string & msg() const throw () { return err; } @@ -39,7 +40,7 @@ public: class newClass : public superClass \ { \ public: \ - newClass(const format & f) : superClass(f) { }; \ + newClass(const format & f, unsigned int status = 1) : superClass(f, status) { }; \ }; MakeError(Error, BaseError) @@ -63,7 +64,7 @@ typedef set<Path> PathSet; typedef enum { - lvlError, + lvlError = 0, lvlInfo, lvlTalkative, lvlChatty, diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 32c8fce9a1b1..9adaac40d56e 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -7,11 +7,8 @@ #include <sstream> #include <cstring> -#include <sys/stat.h> #include <sys/wait.h> -#include <sys/types.h> #include <fcntl.h> -#include <unistd.h> #include <limits.h> #include "util.hh" @@ -23,7 +20,8 @@ extern char * * environ; namespace nix { -BaseError::BaseError(const format & f) +BaseError::BaseError(const format & f, unsigned int status) + : status(status) { err = f.str(); } @@ -149,6 +147,15 @@ string baseNameOf(const Path & path) } +struct stat lstat(const Path & path) +{ + struct stat st; + if (lstat(path.c_str(), &st)) + throw SysError(format("getting status of `%1%'") % path); + return st; +} + + bool pathExists(const Path & path) { int res; @@ -164,9 +171,7 @@ bool pathExists(const Path & path) Path readLink(const Path & path) { checkInterrupt(); - struct stat st; - if (lstat(path.c_str(), &st)) - throw SysError(format("getting status of `%1%'") % path); + struct stat st = lstat(path); if (!S_ISLNK(st.st_mode)) throw Error(format("`%1%' is not a symlink") % path); char buf[st.st_size]; @@ -178,9 +183,7 @@ Path readLink(const Path & path) bool isLink(const Path & path) { - struct stat st; - if (lstat(path.c_str(), &st)) - throw SysError(format("getting status of `%1%'") % path); + struct stat st = lstat(path); return S_ISLNK(st.st_mode); } @@ -228,13 +231,12 @@ string readFile(const Path & path) } -void writeFile(const Path & path, const string & s, bool doFsync) +void writeFile(const Path & path, const string & s) { AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666); if (fd == -1) throw SysError(format("opening file `%1%'") % path); writeFull(fd, (unsigned char *) s.c_str(), s.size()); - if (doFsync) fsync(fd); } @@ -270,9 +272,7 @@ static void _computePathSize(const Path & path, { checkInterrupt(); - struct stat st; - if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + struct stat st = lstat(path); bytes += st.st_size; blocks += st.st_blocks; @@ -302,9 +302,7 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed, printMsg(lvlVomit, format("%1%") % path); - struct stat st; - if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + struct stat st = lstat(path); if (!S_ISDIR(st.st_mode) && st.st_nlink == 1) { bytesFreed += st.st_size; @@ -351,9 +349,7 @@ void makePathReadOnly(const Path & path) { checkInterrupt(); - struct stat st; - if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % path); + struct stat st = lstat(path); if (!S_ISLNK(st.st_mode) && (st.st_mode & S_IWUSR)) { if (chmod(path.c_str(), st.st_mode & ~S_IWUSR) == -1) @@ -412,12 +408,18 @@ Paths createDirs(const Path & path) { Paths created; if (path == "/") return created; - if (!pathExists(path)) { + + struct stat st; + if (lstat(path.c_str(), &st) == -1) { created = createDirs(dirOf(path)); - if (mkdir(path.c_str(), 0777) == -1) + if (mkdir(path.c_str(), 0777) == -1 && errno != EEXIST) throw SysError(format("creating directory `%1%'") % path); + st = lstat(path); created.push_back(path); } + + if (!S_ISDIR(st.st_mode)) throw Error(format("`%1%' is not a directory") % path); + return created; } @@ -976,6 +978,17 @@ Strings tokenizeString(const string & s, const string & separators) } +string concatStringsSep(const string & sep, const Strings & ss) +{ + string s; + foreach (Strings::const_iterator, i, ss) { + if (s.size() != 0) s += sep; + s += *i; + } + return s; +} + + string statusToString(int status) { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index ff710077ceaa..f86290f31694 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -4,6 +4,7 @@ #include "types.hh" #include <sys/types.h> +#include <sys/stat.h> #include <dirent.h> #include <unistd.h> #include <signal.h> @@ -42,6 +43,9 @@ Path dirOf(const Path & path); following the final `/'. */ string baseNameOf(const Path & path); +/* Get status of `path'. */ +struct stat lstat(const Path & path); + /* Return true iff the given path exists. */ bool pathExists(const Path & path); @@ -60,7 +64,7 @@ string readFile(int fd); string readFile(const Path & path); /* Write a string to a file. */ -void writeFile(const Path & path, const string & s, bool doFsync = false); +void writeFile(const Path & path, const string & s); /* Read a line from a file descriptor. */ string readLine(int fd); @@ -280,6 +284,11 @@ MakeError(Interrupted, BaseError) Strings tokenizeString(const string & s, const string & separators = " \t\n\r"); +/* Concatenate the given strings with a separator between the + elements. */ +string concatStringsSep(const string & sep, const Strings & ss); + + /* Convert the exit status of a child as returned by wait() into an error string. */ string statusToString(int status); |