* Some refactoring.

This commit is contained in:
Eelco Dolstra 2003-05-26 13:45:00 +00:00
parent f8d91f20e6
commit 8b930a0c94
8 changed files with 276 additions and 235 deletions

View file

@ -1,13 +0,0 @@
#! /bin/sh
export PATH=$sys1/bin:$sys2/bin
export LIBRARY_PATH=$glibc/lib
export CC=$gcc/bin/gcc
export CFLAGS="-isystem $glibc/include -isystem $kernel/include"
top=`pwd`
tar xvfz $src
cd aterm-2.0
./configure --prefix=$top
make
make install

View file

@ -1,12 +0,0 @@
# Dependencies.
sys1 <- 1e80cb7e0fbfc9f5c0509a465ecdf6cf # sys1-bootstrap
sys2 <- 7512824c50c61ea8d89d0f193a4f72d1 # sys2-bootstrap
gcc <- 02212b3dc4e50349376975367d433929 # gcc-bootstrap
glibc <- c0ce03ee0bab298babbe7e3b6159d36c # glibc-bootstrap
kernel <- 3dc8333a2c2b4d627b892755417acf89 # kernel-bootstrap
# Original sources.
src = 853474e4bcf4a85f7d38a0676b36bded # aterm-2.0.tar.gz
# Build script.
build = ee7ae4ade69f846d2385871bf532ef7e # aterm-2.0-build.sh

View file

@ -1,11 +1,11 @@
bin_PROGRAMS = nix fix bin_PROGRAMS = nix fix
nix_SOURCES = nix.cc md5.c CXXFLAGS = -DSYSTEM=\"@host@\" -Wall
nix_CXXFLAGS = -DSYSTEM=\"@host@\" -Wall
nix_SOURCES = nix.cc db.cc util.cc md5.c
nix_LDADD = -ldb_cxx-4 -lATerm nix_LDADD = -ldb_cxx-4 -lATerm
fix_SOURCES = fix.cc md5.c fix_SOURCES = fix.cc util.cc md5.c
fix_CXXFLAGS = -DSYSTEM=\"@host@\" -Wall
fix_LDADD = -lATerm fix_LDADD = -lATerm
install-data-local: install-data-local:

116
src/db.cc Normal file
View file

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

26
src/db.hh Normal file
View file

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

View file

@ -11,13 +11,12 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <db_cxx.h>
extern "C" { extern "C" {
#include <aterm1.h> #include <aterm1.h>
} }
#include "util.hh" #include "util.hh"
#include "db.hh"
using namespace std; using namespace std;
@ -30,91 +29,7 @@ static string dbNetSources = "netsources";
static string nixSourcesDir; static string nixSourcesDir;
static string nixDB;
/* 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));
}
}
/* Download object referenced by the given URL into the sources /* Download object referenced by the given URL into the sources
@ -150,7 +65,7 @@ string getFile(string hash)
string fn, url; string fn, url;
if (queryDB(dbRefs, hash, fn)) { if (queryDB(nixDB, dbRefs, hash, fn)) {
/* Verify that the file hasn't changed. !!! race */ /* Verify that the file hasn't changed. !!! race */
if (hashFile(fn) != hash) if (hashFile(fn) != hash)
@ -163,7 +78,7 @@ string getFile(string hash)
throw Error("consistency problem: file fetched from " + url + throw Error("consistency problem: file fetched from " + url +
" should have hash " + hash + ", but it doesn't"); " 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, " throw Error("a file with hash " + hash + " is requested, "
"but it is not known to exist locally or on the network"); "but it is not known to exist locally or on the network");
@ -171,7 +86,7 @@ string getFile(string hash)
fn = fetchURL(url); 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. */ /* Try to use a prebuilt. */
string prebuiltHash, prebuiltFile; string prebuiltHash, prebuiltFile;
if (queryDB(dbPrebuilts, hash, prebuiltHash)) { if (queryDB(nixDB, dbPrebuilts, hash, prebuiltHash)) {
try { try {
prebuiltFile = getFile(prebuiltHash); prebuiltFile = getFile(prebuiltHash);
@ -398,7 +313,7 @@ build:
throw; throw;
} }
setDB(dbInstPkgs, hash, path); setDB(nixDB, dbInstPkgs, hash, path);
} }
@ -406,7 +321,7 @@ string getPkg(string hash)
{ {
string path; string path;
checkHash(hash); checkHash(hash);
while (!queryDB(dbInstPkgs, hash, path)) while (!queryDB(nixDB, dbInstPkgs, hash, path))
installPkg(hash); installPkg(hash);
return path; return path;
} }
@ -470,9 +385,9 @@ void delPkg(string hash)
{ {
string path; string path;
checkHash(hash); 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 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) if (WEXITSTATUS(res) != 0)
cerr << "errors deleting " + path + ", ignoring" << endl; cerr << "errors deleting " + path + ", ignoring" << endl;
} }
@ -509,7 +424,7 @@ void registerPrebuilt(string pkgHash, string prebuiltHash)
{ {
checkHash(pkgHash); checkHash(pkgHash);
checkHash(prebuiltHash); checkHash(prebuiltHash);
setDB(dbPrebuilts, pkgHash, prebuiltHash); setDB(nixDB, dbPrebuilts, pkgHash, prebuiltHash);
} }
@ -517,7 +432,7 @@ string registerFile(string filename)
{ {
filename = absPath(filename); filename = absPath(filename);
string hash = hashFile(filename); string hash = hashFile(filename);
setDB(dbRefs, hash, filename); setDB(nixDB, dbRefs, hash, filename);
return hash; return hash;
} }
@ -525,7 +440,7 @@ string registerFile(string filename)
void registerURL(string hash, string url) void registerURL(string hash, string url)
{ {
checkHash(hash); checkHash(hash);
setDB(dbNetSources, hash, url); setDB(nixDB, dbNetSources, hash, url);
/* !!! currently we allow only one network source per hash */ /* !!! currently we allow only one network source per hash */
} }
@ -535,18 +450,18 @@ void registerInstalledPkg(string hash, string path)
{ {
checkHash(hash); checkHash(hash);
if (path == "") if (path == "")
delDB(dbInstPkgs, hash); delDB(nixDB, dbInstPkgs, hash);
else else
setDB(dbInstPkgs, hash, path); setDB(nixDB, dbInstPkgs, hash, path);
} }
void initDB() void initDB()
{ {
openDB(dbRefs, false); createDB(nixDB, dbRefs);
openDB(dbInstPkgs, false); createDB(nixDB, dbInstPkgs);
openDB(dbPrebuilts, false); createDB(nixDB, dbPrebuilts);
openDB(dbNetSources, false); createDB(nixDB, dbNetSources);
} }
@ -555,7 +470,7 @@ void verifyDB()
/* Check that all file references are still valid. */ /* Check that all file references are still valid. */
DBPairs fileRefs; DBPairs fileRefs;
enumDB(dbRefs, fileRefs); enumDB(nixDB, dbRefs, fileRefs);
for (DBPairs::iterator it = fileRefs.begin(); for (DBPairs::iterator it = fileRefs.begin();
it != fileRefs.end(); it++) it != fileRefs.end(); it++)
@ -563,18 +478,18 @@ void verifyDB()
try { try {
if (hashFile(it->second) != it->first) { if (hashFile(it->second) != it->first) {
cerr << "file " << it->second << " has changed\n"; cerr << "file " << it->second << " has changed\n";
delDB(dbRefs, it->first); delDB(nixDB, dbRefs, it->first);
} }
} catch (BadRefError e) { /* !!! better error check */ } catch (BadRefError e) { /* !!! better error check */
cerr << "file " << it->second << " has disappeared\n"; cerr << "file " << it->second << " has disappeared\n";
delDB(dbRefs, it->first); delDB(nixDB, dbRefs, it->first);
} }
} }
/* Check that all installed packages are still there. */ /* Check that all installed packages are still there. */
DBPairs instPkgs; DBPairs instPkgs;
enumDB(dbInstPkgs, instPkgs); enumDB(nixDB, dbInstPkgs, instPkgs);
for (DBPairs::iterator it = instPkgs.begin(); for (DBPairs::iterator it = instPkgs.begin();
it != instPkgs.end(); it++) it != instPkgs.end(); it++)
@ -582,7 +497,7 @@ void verifyDB()
struct stat st; struct stat st;
if (stat(it->second.c_str(), &st) == -1) { if (stat(it->second.c_str(), &st) == -1) {
cerr << "package " << it->first << " has disappeared\n"; cerr << "package " << it->first << " has disappeared\n";
delDB(dbInstPkgs, it->first); delDB(nixDB, dbInstPkgs, it->first);
} }
} }
@ -595,7 +510,7 @@ void listInstalledPkgs()
{ {
DBPairs instPkgs; DBPairs instPkgs;
enumDB(dbInstPkgs, instPkgs); enumDB(nixDB, dbInstPkgs, instPkgs);
for (DBPairs::iterator it = instPkgs.begin(); for (DBPairs::iterator it = instPkgs.begin();
it != instPkgs.end(); it++) it != instPkgs.end(); it++)
@ -777,6 +692,7 @@ void run(Strings::iterator argCur, Strings::iterator argEnd)
if (homeDir) nixHomeDir = homeDir; if (homeDir) nixHomeDir = homeDir;
nixSourcesDir = nixHomeDir + "/var/nix/sources"; nixSourcesDir = nixHomeDir + "/var/nix/sources";
nixDB = nixHomeDir + "/var/nix/pkginfo.db";
/* Parse the global flags. */ /* Parse the global flags. */
for ( ; argCur != argEnd; argCur++) { for ( ; argCur != argEnd; argCur++) {
@ -856,11 +772,7 @@ int main(int argc, char * * argv)
argCur++; argCur++;
try { try {
try { run(argCur, argEnd);
run(argCur, argEnd);
} catch (DbException e) {
throw Error(e.what());
}
} catch (UsageError & e) { } catch (UsageError & e) {
cerr << "error: " << e.what() << endl cerr << "error: " << e.what() << endl
<< "Try `nix -h' for more information.\n"; << "Try `nix -h' for more information.\n";

94
src/util.cc Normal file
View file

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

View file

@ -39,104 +39,22 @@ public:
typedef vector<string> Strings; typedef vector<string> Strings;
/* !!! the following shouldn't be here; abuse of the preprocessor */
/* The canonical system name, as returned by config.guess. */ /* 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 /* The prefix of the Nix installation, and the environment variable
that can be used to override the default. */ that can be used to override the default. */
static string nixHomeDir = "/nix"; extern string nixHomeDir;
static string nixHomeDirEnvVar = "NIX"; extern string nixHomeDirEnvVar;
string absPath(string filename, string dir = "") string absPath(string filename, string dir = "");
{ bool isHash(const string & s);
if (filename[0] != '/') { void checkHash(const string & s);
if (dir == "") { string hashFile(string filename);
char buf[PATH_MAX]; string dirOf(string s);
if (!getcwd(buf, sizeof(buf))) string baseNameOf(string s);
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);
}
/* 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);
}
#endif /* !__UTIL_H */ #endif /* !__UTIL_H */