about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/Makefile.am2
-rw-r--r--src/libutil/archive.cc8
-rw-r--r--src/libutil/archive.hh1
-rw-r--r--src/libutil/hash.cc17
-rw-r--r--src/libutil/hash.hh10
-rw-r--r--src/libutil/types.hh7
-rw-r--r--src/libutil/util.cc59
-rw-r--r--src/libutil/util.hh11
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);