about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/db.cc116
-rw-r--r--src/db.hh26
-rw-r--r--src/nix.cc142
-rw-r--r--src/util.cc94
-rw-r--r--src/util.hh100
6 files changed, 276 insertions, 210 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 31fad892583b..ffbaaeb83051 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,11 +1,11 @@
 bin_PROGRAMS = nix fix
 
-nix_SOURCES = nix.cc md5.c
-nix_CXXFLAGS = -DSYSTEM=\"@host@\" -Wall
+CXXFLAGS = -DSYSTEM=\"@host@\" -Wall
+
+nix_SOURCES = nix.cc db.cc util.cc md5.c
 nix_LDADD = -ldb_cxx-4 -lATerm
 
-fix_SOURCES = fix.cc md5.c
-fix_CXXFLAGS = -DSYSTEM=\"@host@\" -Wall
+fix_SOURCES = fix.cc util.cc md5.c
 fix_LDADD = -lATerm
 
 install-data-local:
diff --git a/src/db.cc b/src/db.cc
new file mode 100644
index 000000000000..e9f3a0f9e34b
--- /dev/null
+++ b/src/db.cc
@@ -0,0 +1,116 @@
+#include "db.hh"
+#include "util.hh"
+
+#include <db_cxx.h>
+
+
+/* Wrapper classes that ensures that the database is closed upon
+   object destruction. */
+class Db2 : public Db 
+{
+public:
+    Db2(DbEnv *env, u_int32_t flags) : Db(env, flags) { }
+    ~Db2() { close(0); }
+};
+
+
+class DbcClose 
+{
+    Dbc * cursor;
+public:
+    DbcClose(Dbc * c) : cursor(c) { }
+    ~DbcClose() { cursor->close(); }
+};
+
+
+static auto_ptr<Db2> openDB(const string & filename, const string & dbname,
+    bool readonly)
+{
+    auto_ptr<Db2> db(new Db2(0, 0));
+
+    db->open(filename.c_str(), dbname.c_str(),
+        DB_HASH, readonly ? DB_RDONLY : DB_CREATE, 0666);
+
+    return db;
+}
+
+
+static void rethrow(DbException & e)
+{
+    throw Error(e.what());
+}
+
+
+void createDB(const string & filename, const string & dbname)
+{
+    try {
+        openDB(filename, dbname, false);
+    } catch (DbException e) { rethrow(e); }
+}
+
+
+bool queryDB(const string & filename, const string & dbname,
+    const string & key, string & data)
+{
+    try {
+
+        int err;
+        auto_ptr<Db2> db = openDB(filename, dbname, true);
+
+        Dbt kt((void *) key.c_str(), key.length());
+        Dbt dt;
+
+        err = db->get(0, &kt, &dt, 0);
+        if (err) return false;
+
+        data = string((char *) dt.get_data(), dt.get_size());
+    
+    } catch (DbException e) { rethrow(e); }
+
+    return true;
+}
+
+
+void setDB(const string & filename, const string & dbname,
+    const string & key, const string & data)
+{
+    try {
+        auto_ptr<Db2> db = openDB(filename, dbname, false);
+        Dbt kt((void *) key.c_str(), key.length());
+        Dbt dt((void *) data.c_str(), data.length());
+        db->put(0, &kt, &dt, 0);
+    } catch (DbException e) { rethrow(e); }
+}
+
+
+void delDB(const string & filename, const string & dbname,
+    const string & key)
+{
+    try {
+        auto_ptr<Db2> db = openDB(filename, dbname, false);
+        Dbt kt((void *) key.c_str(), key.length());
+        db->del(0, &kt, 0);
+    } catch (DbException e) { rethrow(e); }
+}
+
+
+void enumDB(const string & filename, const string & dbname,
+    DBPairs & contents)
+{
+    try {
+
+        auto_ptr<Db2> db = openDB(filename, dbname, false);
+
+        Dbc * cursor;
+        db->cursor(0, &cursor, 0);
+        DbcClose cursorCloser(cursor);
+
+        Dbt kt, dt;
+        while (cursor->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND) {
+            string key((char *) kt.get_data(), kt.get_size());
+            string data((char *) dt.get_data(), dt.get_size());
+            contents.push_back(DBPair(key, data));
+        }
+
+    } catch (DbException e) { rethrow(e); }
+}
diff --git a/src/db.hh b/src/db.hh
new file mode 100644
index 000000000000..0054dbec13e1
--- /dev/null
+++ b/src/db.hh
@@ -0,0 +1,26 @@
+#ifndef __DB_H
+#define __DB_H
+
+#include <string>
+#include <list>
+
+using namespace std;
+
+typedef pair<string, string> DBPair;
+typedef list<DBPair> DBPairs;
+
+void createDB(const string & filename, const string & dbname);
+
+bool queryDB(const string & filename, const string & dbname,
+    const string & key, string & data);
+
+void setDB(const string & filename, const string & dbname,
+    const string & key, const string & data);
+
+void delDB(const string & filename, const string & dbname,
+    const string & key);
+
+void enumDB(const string & filename, const string & dbname,
+    DBPairs & contents);
+
+#endif /* !__DB_H */
diff --git a/src/nix.cc b/src/nix.cc
index 38643e3d69d5..5904bf82d519 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -11,13 +11,12 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
-#include <db_cxx.h>
-
 extern "C" {
 #include <aterm1.h>
 }
 
 #include "util.hh"
+#include "db.hh"
 
 using namespace std;
 
@@ -30,91 +29,7 @@ static string dbNetSources = "netsources";
 
 
 static string nixSourcesDir;
-
-
-/* Wrapper classes that ensures that the database is closed upon
-   object destruction. */
-class Db2 : public Db 
-{
-public:
-    Db2(DbEnv *env, u_int32_t flags) : Db(env, flags) { }
-    ~Db2() { close(0); }
-};
-
-
-class DbcClose 
-{
-    Dbc * cursor;
-public:
-    DbcClose(Dbc * c) : cursor(c) { }
-    ~DbcClose() { cursor->close(); }
-};
-
-
-auto_ptr<Db2> openDB(const string & dbname, bool readonly)
-{
-    auto_ptr<Db2> db(new Db2(0, 0));
-
-    db->open((nixHomeDir + "/var/nix/pkginfo.db").c_str(), dbname.c_str(),
-        DB_HASH, readonly ? DB_RDONLY : DB_CREATE, 0666);
-
-    return db;
-}
-
-
-bool queryDB(const string & dbname, const string & key, string & data)
-{
-    int err;
-    auto_ptr<Db2> db = openDB(dbname, true);
-
-    Dbt kt((void *) key.c_str(), key.length());
-    Dbt dt;
-
-    err = db->get(0, &kt, &dt, 0);
-    if (err) return false;
-
-    data = string((char *) dt.get_data(), dt.get_size());
-    
-    return true;
-}
-
-
-void setDB(const string & dbname, const string & key, const string & data)
-{
-    auto_ptr<Db2> db = openDB(dbname, false);
-    Dbt kt((void *) key.c_str(), key.length());
-    Dbt dt((void *) data.c_str(), data.length());
-    db->put(0, &kt, &dt, 0);
-}
-
-
-void delDB(const string & dbname, const string & key)
-{
-    auto_ptr<Db2> db = openDB(dbname, false);
-    Dbt kt((void *) key.c_str(), key.length());
-    db->del(0, &kt, 0);
-}
-
-
-typedef pair<string, string> DBPair;
-typedef list<DBPair> DBPairs;
-
-
-void enumDB(const string & dbname, DBPairs & contents)
-{
-    auto_ptr<Db2> db = openDB(dbname, false);
-
-    Dbc * cursor;
-    db->cursor(0, &cursor, 0);
-    DbcClose cursorCloser(cursor);
-
-    Dbt kt, dt;
-    while (cursor->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND) {
-        string key((char *) kt.get_data(), kt.get_size());
-        string data((char *) dt.get_data(), dt.get_size());
-        contents.push_back(DBPair(key, data));
-    }
-}
+static string nixDB;
 
 
 /* Download object referenced by the given URL into the sources
@@ -150,7 +65,7 @@ string getFile(string hash)
 
         string fn, url;
 
-        if (queryDB(dbRefs, hash, fn)) {
+        if (queryDB(nixDB, dbRefs, hash, fn)) {
 
             /* Verify that the file hasn't changed. !!! race */
             if (hashFile(fn) != hash)
@@ -163,7 +78,7 @@ string getFile(string hash)
             throw Error("consistency problem: file fetched from " + url + 
                 " should have hash " + hash + ", but it doesn't");
 
-        if (!queryDB(dbNetSources, hash, url))
+        if (!queryDB(nixDB, dbNetSources, hash, url))
             throw Error("a file with hash " + hash + " is requested, "
                 "but it is not known to exist locally or on the network");
 
@@ -171,7 +86,7 @@ string getFile(string hash)
         
         fn = fetchURL(url);
         
-        setDB(dbRefs, hash, fn);
+        setDB(nixDB, dbRefs, hash, fn);
     }
 }
 
@@ -332,7 +247,7 @@ void installPkg(string hash)
 
             /* Try to use a prebuilt. */
             string prebuiltHash, prebuiltFile;
-            if (queryDB(dbPrebuilts, hash, prebuiltHash)) {
+            if (queryDB(nixDB, dbPrebuilts, hash, prebuiltHash)) {
 
                 try {
                     prebuiltFile = getFile(prebuiltHash);
@@ -398,7 +313,7 @@ build:
         throw;
     }
 
-    setDB(dbInstPkgs, hash, path);
+    setDB(nixDB, dbInstPkgs, hash, path);
 }
 
 
@@ -406,7 +321,7 @@ string getPkg(string hash)
 {
     string path;
     checkHash(hash);
-    while (!queryDB(dbInstPkgs, hash, path))
+    while (!queryDB(nixDB, dbInstPkgs, hash, path))
         installPkg(hash);
     return path;
 }
@@ -470,9 +385,9 @@ void delPkg(string hash)
 {
     string path;
     checkHash(hash);
-    if (queryDB(dbInstPkgs, hash, path)) {
+    if (queryDB(nixDB, dbInstPkgs, hash, path)) {
         int res = system(("chmod -R +w " + path + " && rm -rf " + path).c_str()); // !!! escaping
-        delDB(dbInstPkgs, hash); // not a bug ??? 
+        delDB(nixDB, dbInstPkgs, hash); // not a bug ??? 
         if (WEXITSTATUS(res) != 0)
             cerr << "errors deleting " + path + ", ignoring" << endl;
     }
@@ -509,7 +424,7 @@ void registerPrebuilt(string pkgHash, string prebuiltHash)
 {
     checkHash(pkgHash);
     checkHash(prebuiltHash);
-    setDB(dbPrebuilts, pkgHash, prebuiltHash);
+    setDB(nixDB, dbPrebuilts, pkgHash, prebuiltHash);
 }
 
 
@@ -517,7 +432,7 @@ string registerFile(string filename)
 {
     filename = absPath(filename);
     string hash = hashFile(filename);
-    setDB(dbRefs, hash, filename);
+    setDB(nixDB, dbRefs, hash, filename);
     return hash;
 }
 
@@ -525,7 +440,7 @@ string registerFile(string filename)
 void registerURL(string hash, string url)
 {
     checkHash(hash);
-    setDB(dbNetSources, hash, url);
+    setDB(nixDB, dbNetSources, hash, url);
     /* !!! currently we allow only one network source per hash */
 }
 
@@ -535,18 +450,18 @@ void registerInstalledPkg(string hash, string path)
 {
     checkHash(hash);
     if (path == "")
-        delDB(dbInstPkgs, hash);
+        delDB(nixDB, dbInstPkgs, hash);
     else
-        setDB(dbInstPkgs, hash, path);
+        setDB(nixDB, dbInstPkgs, hash, path);
 }
 
 
 void initDB()
 {
-    openDB(dbRefs, false);
-    openDB(dbInstPkgs, false);
-    openDB(dbPrebuilts, false);
-    openDB(dbNetSources, false);
+    createDB(nixDB, dbRefs);
+    createDB(nixDB, dbInstPkgs);
+    createDB(nixDB, dbPrebuilts);
+    createDB(nixDB, dbNetSources);
 }
 
 
@@ -555,7 +470,7 @@ void verifyDB()
     /* Check that all file references are still valid. */
     DBPairs fileRefs;
     
-    enumDB(dbRefs, fileRefs);
+    enumDB(nixDB, dbRefs, fileRefs);
 
     for (DBPairs::iterator it = fileRefs.begin();
          it != fileRefs.end(); it++)
@@ -563,18 +478,18 @@ void verifyDB()
         try {
             if (hashFile(it->second) != it->first) {
                 cerr << "file " << it->second << " has changed\n";
-                delDB(dbRefs, it->first);
+                delDB(nixDB, dbRefs, it->first);
             }
         } catch (BadRefError e) { /* !!! better error check */ 
             cerr << "file " << it->second << " has disappeared\n";
-            delDB(dbRefs, it->first);
+            delDB(nixDB, dbRefs, it->first);
         }
     }
 
     /* Check that all installed packages are still there. */
     DBPairs instPkgs;
 
-    enumDB(dbInstPkgs, instPkgs);
+    enumDB(nixDB, dbInstPkgs, instPkgs);
 
     for (DBPairs::iterator it = instPkgs.begin();
          it != instPkgs.end(); it++)
@@ -582,7 +497,7 @@ void verifyDB()
         struct stat st;
         if (stat(it->second.c_str(), &st) == -1) {
             cerr << "package " << it->first << " has disappeared\n";
-            delDB(dbInstPkgs, it->first);
+            delDB(nixDB, dbInstPkgs, it->first);
         }
     }
 
@@ -595,7 +510,7 @@ void listInstalledPkgs()
 {
     DBPairs instPkgs;
 
-    enumDB(dbInstPkgs, instPkgs);
+    enumDB(nixDB, dbInstPkgs, instPkgs);
 
     for (DBPairs::iterator it = instPkgs.begin();
          it != instPkgs.end(); it++)
@@ -777,6 +692,7 @@ void run(Strings::iterator argCur, Strings::iterator argEnd)
     if (homeDir) nixHomeDir = homeDir;
 
     nixSourcesDir = nixHomeDir + "/var/nix/sources";
+    nixDB = nixHomeDir + "/var/nix/pkginfo.db";
 
     /* Parse the global flags. */
     for ( ; argCur != argEnd; argCur++) {
@@ -856,11 +772,7 @@ int main(int argc, char * * argv)
     argCur++;
 
     try {
-        try {
-            run(argCur, argEnd);
-        } catch (DbException e) {
-            throw Error(e.what());
-        }
+        run(argCur, argEnd);
     } catch (UsageError & e) {
         cerr << "error: " << e.what() << endl
              << "Try `nix -h' for more information.\n";
diff --git a/src/util.cc b/src/util.cc
new file mode 100644
index 000000000000..4b7bbac3dd07
--- /dev/null
+++ b/src/util.cc
@@ -0,0 +1,94 @@
+#include "util.hh"
+
+
+string thisSystem = SYSTEM;
+string nixHomeDir = "/nix";
+string nixHomeDirEnvVar = "NIX";
+
+
+
+string absPath(string filename, string dir)
+{
+    if (filename[0] != '/') {
+        if (dir == "") {
+            char buf[PATH_MAX];
+            if (!getcwd(buf, sizeof(buf)))
+                throw Error("cannot get cwd");
+            dir = buf;
+        }
+        filename = dir + "/" + filename;
+        /* !!! canonicalise */
+        char resolved[PATH_MAX];
+        if (!realpath(filename.c_str(), resolved))
+            throw Error("cannot canonicalise path " + filename);
+        filename = resolved;
+    }
+    return filename;
+}
+
+
+static string printHash(unsigned char * buf)
+{
+    ostringstream str;
+    for (int i = 0; i < 16; i++) {
+        str.fill('0');
+        str.width(2);
+        str << hex << (int) buf[i];
+    }
+    return str.str();
+}
+
+    
+/* Verify that a reference is valid (that is, is a MD5 hash code). */
+bool isHash(const string & s)
+{
+    if (s.length() != 32) return false;
+    for (int i = 0; i < 32; i++) {
+        char c = s[i];
+        if (!((c >= '0' && c <= '9') ||
+              (c >= 'a' && c <= 'f')))
+            return false;
+    }
+    return true;
+}
+
+
+void checkHash(const string & s)
+{
+    if (!isHash(s)) throw BadRefError("invalid reference: " + s);
+}
+
+
+/* Compute the MD5 hash of a file. */
+string hashFile(string filename)
+{
+    unsigned char hash[16];
+    FILE * file = fopen(filename.c_str(), "rb");
+    if (!file)
+        throw BadRefError("file `" + filename + "' does not exist");
+    int err = md5_stream(file, hash);
+    fclose(file);
+    if (err) throw BadRefError("cannot hash file");
+    return printHash(hash);
+}
+
+
+
+/* Return the directory part of the given path, i.e., everything
+   before the final `/'. */
+string dirOf(string s)
+{
+    unsigned int pos = s.rfind('/');
+    if (pos == string::npos) throw Error("invalid file name");
+    return string(s, 0, pos);
+}
+
+
+/* Return the base name of the given path, i.e., everything following
+   the final `/'. */
+string baseNameOf(string s)
+{
+    unsigned int pos = s.rfind('/');
+    if (pos == string::npos) throw Error("invalid file name");
+    return string(s, pos + 1);
+}
diff --git a/src/util.hh b/src/util.hh
index 9b3f212de359..2c09efc4d88f 100644
--- a/src/util.hh
+++ b/src/util.hh
@@ -39,104 +39,22 @@ public:
 typedef vector<string> Strings;
 
 
-/* !!! the following shouldn't be here; abuse of the preprocessor */
-
-
 /* The canonical system name, as returned by config.guess. */ 
-static string thisSystem = SYSTEM;
+extern string thisSystem;
 
 
 /* The prefix of the Nix installation, and the environment variable
    that can be used to override the default. */
-static string nixHomeDir = "/nix";
-static string nixHomeDirEnvVar = "NIX";
-
-
-string absPath(string filename, string dir = "")
-{
-    if (filename[0] != '/') {
-        if (dir == "") {
-            char buf[PATH_MAX];
-            if (!getcwd(buf, sizeof(buf)))
-                throw Error("cannot get cwd");
-            dir = buf;
-        }
-        filename = dir + "/" + filename;
-        /* !!! canonicalise */
-        char resolved[PATH_MAX];
-        if (!realpath(filename.c_str(), resolved))
-            throw Error("cannot canonicalise path " + filename);
-        filename = resolved;
-    }
-    return filename;
-}
-
-
-string printHash(unsigned char * buf)
-{
-    ostringstream str;
-    for (int i = 0; i < 16; i++) {
-        str.fill('0');
-        str.width(2);
-        str << hex << (int) buf[i];
-    }
-    return str.str();
-}
-
-    
-/* Verify that a reference is valid (that is, is a MD5 hash code). */
-bool isHash(const string & s)
-{
-    if (s.length() != 32) return false;
-    for (int i = 0; i < 32; i++) {
-        char c = s[i];
-        if (!((c >= '0' && c <= '9') ||
-              (c >= 'a' && c <= 'f')))
-            return false;
-    }
-    return true;
-}
-
-
-void checkHash(const string & s)
-{
-    if (!isHash(s)) throw BadRefError("invalid reference: " + s);
-}
-
-
-/* Compute the MD5 hash of a file. */
-string hashFile(string filename)
-{
-    unsigned char hash[16];
-    FILE * file = fopen(filename.c_str(), "rb");
-    if (!file)
-        throw BadRefError("file `" + filename + "' does not exist");
-    int err = md5_stream(file, hash);
-    fclose(file);
-    if (err) throw BadRefError("cannot hash file");
-    return printHash(hash);
-}
+extern string nixHomeDir;
+extern string nixHomeDirEnvVar;
 
 
-
-/* Return the directory part of the given path, i.e., everything
-   before the final `/'. */
-string dirOf(string s)
-{
-    unsigned int pos = s.rfind('/');
-    if (pos == string::npos) throw Error("invalid file name");
-    return string(s, 0, pos);
-}
-
-
-/* Return the base name of the given path, i.e., everything following
-   the final `/'. */
-string baseNameOf(string s)
-{
-    unsigned int pos = s.rfind('/');
-    if (pos == string::npos) throw Error("invalid file name");
-    return string(s, pos + 1);
-}
+string absPath(string filename, string dir = "");
+bool isHash(const string & s);
+void checkHash(const string & s);
+string hashFile(string filename);
+string dirOf(string s);
+string baseNameOf(string s);
 
 
 #endif /* !__UTIL_H */