diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 000000000..5f42afd04 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,2 @@ +nix: nix.c + gcc -g -Wall -o nix nix.c -ldb-4 diff --git a/src/nix.c b/src/nix.c new file mode 100644 index 000000000..e8b18934b --- /dev/null +++ b/src/nix.c @@ -0,0 +1,314 @@ +#include +#include +#include +#include +#include +#include + +#include + + +#define PKGINFO_PATH "/pkg/sys/var/pkginfo" + + +typedef enum {true = 1, false = 0} bool; + + +static char * prog; +static char * dbfile = PKGINFO_PATH; + + +DB * openDB(char * dbname, bool readonly) +{ + int err; + DB * db; + + err = db_create(&db, 0, 0); + if (err) { + fprintf(stderr, "error creating db handle: %s\n", + db_strerror(err)); + return 0; + } + + err = db->open(db, dbfile, dbname, + DB_HASH, readonly ? DB_RDONLY : DB_CREATE, 0666); + if (err) { + fprintf(stderr, "creating opening %s: %s\n", + dbfile, db_strerror(err)); + db->close(db, 0); + return 0; + } + + return db; +} + + +bool queryDB(char * dbname, char * key, char * * data) +{ + DB * db = 0; + DBT kt, dt; + int err; + + db = openDB(dbname, true); + if (!db) goto bad; + + *data = 0; + + memset(&kt, 0, sizeof(kt)); + memset(&dt, 0, sizeof(dt)); + kt.size = strlen(key); + kt.data = key; + + err = db->get(db, 0, &kt, &dt, 0); + if (!err) { + *data = malloc(dt.size + 1); + memcpy(*data, dt.data, dt.size); + (*data)[dt.size] = 0; + } else if (err != DB_NOTFOUND) { + fprintf(stderr, "creating opening %s: %s\n", + dbfile, db_strerror(err)); + goto bad; + } + + db->close(db, 0); + return true; + + bad: + if (db) db->close(db, 0); + return false; +} + + +bool setDB(char * dbname, char * key, char * data) +{ + DB * db = 0; + DBT kt, dt; + int err; + + db = openDB(dbname, false); + if (!db) goto bad; + + memset(&kt, 0, sizeof(kt)); + memset(&dt, 0, sizeof(dt)); + kt.size = strlen(key); + kt.data = key; + dt.size = strlen(data); + dt.data = data; + + err = db->put(db, 0, &kt, &dt, 0); + if (err) { + fprintf(stderr, "error storing data in %s: %s\n", + dbfile, db_strerror(err)); + goto bad; + } + + db->close(db, 0); + return true; + + bad: + if (db) db->close(db, 0); + return false; +} + + +bool delDB(char * dbname, char * key) +{ + DB * db = 0; + DBT kt; + int err; + + db = openDB(dbname, false); + if (!db) goto bad; + + memset(&kt, 0, sizeof(kt)); + kt.size = strlen(key); + kt.data = key; + + err = db->del(db, 0, &kt, 0); + if (err) { + fprintf(stderr, "error deleting data from %s: %s\n", + dbfile, db_strerror(err)); + goto bad; + } + + db->close(db, 0); + return true; + + bad: + if (db) db->close(db, 0); + return false; +} + + +bool getPkg(int argc, char * * argv) +{ + char * pkg; + char * src = 0; + char * inst = 0; + char inst2[1024]; + char cmd[2048]; + int res; + + if (argc != 1) { + fprintf(stderr, "arguments missing in get-pkg\n"); + return false; + } + + pkg = argv[0]; + + if (!queryDB("pkginst", pkg, &inst)) return false; + + if (inst) { + printf("%s\n", inst); + free(inst); + } else { + + fprintf(stderr, "package %s is not yet installed\n", pkg); + + if (!queryDB("pkgsrc", pkg, &src)) return false; + + if (!src) { + fprintf(stderr, "source of package %s is not known\n", pkg); + return false; + } + + if (snprintf(inst2, sizeof(inst2), "/pkg/%s", pkg) >= sizeof(inst2)) { + fprintf(stderr, "buffer overflow\n"); + free(src); + return false; + } + + if (snprintf(cmd, sizeof(cmd), "rsync -a \"%s\"/ \"%s\"", + src, inst2) >= sizeof(cmd)) + { + fprintf(stderr, "buffer overflow\n"); + free(src); + return false; + } + + res = system(cmd); + if (!WIFEXITED(res) || WEXITSTATUS(res) != 0) { + fprintf(stderr, "unable to copy sources\n"); + free(src); + return false; + } + + if (chdir(inst2)) { + fprintf(stderr, "unable to chdir to package directory\n"); + free(src); + return false; + } + + /* Prepare for building. Clean the environment so that the + build process does not inherit things it shouldn't. */ + setenv("PATH", "/pkg/sys/bin", 1); + + res = system("./buildme"); + if (!WIFEXITED(res) || WEXITSTATUS(res) != 0) { + fprintf(stderr, "unable to build package\n"); + free(src); + return false; + } + + setDB("pkginst", pkg, inst2); + + free(src); + + printf("%s\n", inst2); + } + + return true; +} + + +bool registerPkg(int argc, char * * argv) +{ + char * pkg; + char * src; + + if (argc != 2) { + fprintf(stderr, "arguments missing in register-pkg\n"); + return false; + } + + pkg = argv[0]; + src = argv[1]; + + return setDB("pkgsrc", pkg, src); +} + + +/* This is primarily used for bootstrapping. */ +bool registerInstalledPkg(int argc, char * * argv) +{ + char * pkg; + char * inst; + + if (argc != 2) { + fprintf(stderr, "arguments missing in register-installed-pkg\n"); + return false; + } + + pkg = argv[0]; + inst = argv[1]; + + if (strcmp(inst, "") == 0) + return delDB("pkginst", pkg); + else + return setDB("pkginst", pkg, inst); +} + + +bool run(int argc, char * * argv) +{ + char * cmd; + + if (argc < 1) { + fprintf(stderr, "command not specified\n"); + return false; + } + + cmd = argv[0]; + argc--, argv++; + + if (strcmp(cmd, "get-pkg") == 0) + return getPkg(argc, argv); + else if (strcmp(cmd, "register-pkg") == 0) + return registerPkg(argc, argv); + else if (strcmp(cmd, "register-installed-pkg") == 0) + return registerInstalledPkg(argc, argv); + else { + fprintf(stderr, "unknown command: %s\n", cmd); + return false; + } +} + + +int main(int argc, char * * argv) +{ + int c; + + prog = argv[0]; + + while ((c = getopt(argc, argv, "d:")) != EOF) { + + switch (c) { + + case 'd': + dbfile = optarg; + break; + + default: + fprintf(stderr, "unknown option\n"); + break; + } + + } + + argc -= optind, argv += optind; + + if (!run(argc, argv)) + return 1; + else + return 0; +} diff --git a/sys/bootstrap b/sys/bootstrap new file mode 100755 index 000000000..e2265c1dc --- /dev/null +++ b/sys/bootstrap @@ -0,0 +1,86 @@ +#! /bin/sh + +. ./settings + +if ! ./mountloop; then + exit 1 +fi + +# Cleanup. +rm -rf $target/dev +rm -rf $target/proc + +# Create the basic directory structure. +mkdir $target +mkdir $target/dev +mkdir $target/proc +mkdir $target/pkg +mkdir $target/pkg/sys +mkdir $target/pkg/sys/bin +mkdir $target/pkg/sys/var +mkdir $target/mnt +mkdir $target/mnt/host +mkdir -m 1777 $target/tmp + +# Make package registrations. +pkgdb=$target/pkg/sys/var/pkginfo + +# Copy some programs and its libraries. +utils="/usr/bin/vi /bin/sh /bin/mount /bin/umount /bin/ls /bin/ln /bin/cp /bin/mv /bin/rm /bin/cat /bin/df /bin/pwd /usr/bin/ld /usr/bin/as /bin/sed /bin/chmod /bin/chown /usr/bin/expr /bin/mkdir /bin/rmdir /usr/bin/sort /usr/bin/uniq /bin/uname /usr/bin/grep /bin/sleep /usr/bin/rsync /usr/bin/make /usr/bin/cmp /bin/date /usr/bin/tr /usr/bin/ar /usr/bin/ranlib /usr/bin/basename /usr/bin/less ../src/nix" +bootlib=/pkg/prog-bootstrap/lib +bootbin=/pkg/prog-bootstrap/bin +mkdir -p $target/$bootlib +mkdir -p $target/$bootbin +cp -p $utils $target/$bootbin +libs=`ldd $utils | awk '{ print $3 }' | sort | uniq` +echo $libs +cp -p $libs $target/$bootlib +for i in libc.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libresolv.so.2 ld-linux.so.2; do rm $target/$bootlib/$i; done +../src/nix -d $pkgdb register-installed-pkg prog-bootstrap /pkg/prog-bootstrap + +mv $target/$bootbin/nix $target/pkg/sys/bin +../src/nix -d $pkgdb register-installed-pkg sys /pkg/sys + +# Copy the bootstrap gcc. +echo Copying gcc... +rsync -a ../bootstrap/gcc/inst/pkg $target +../src/nix -d $pkgdb register-installed-pkg gcc-bootstrap /pkg/gcc-bootstrap + +# Copy the bootstrap glibc. +echo Copying glibc... +glibcdir=/pkg/glibc-bootstrap +rsync -a ../bootstrap/glibc/inst/pkg $target +../src/nix -d $pkgdb register-installed-pkg glibc-bootstrap $glibcdir + +# Copy the bootstrap kernel header files. +echo Copying kernel headers... +kerneldir=/pkg/kernel-bootstrap +rsync -a ../bootstrap/kernel/inst/pkg $target +../src/nix -d $pkgdb register-installed-pkg kernel-bootstrap $kerneldir + +# Compatibility. +rm -rf $target/lib +mkdir $target/lib +ln -sf $glibcdir/lib/ld-linux.so.2 $target/lib/ld-linux.so.2 + +rm -rf $target/bin +mkdir $target/bin +ln -sf $bootbin/sh $target/bin/sh + +# Build ld.so.cache. +ldsoconf=$target/$glibcdir/etc/ld.so.conf +echo $glibcdir/lib > $ldsoconf +echo $bootlib >> $ldsoconf +$target/$glibcdir/sbin/ldconfig -r $target + +# Source repository. +rm -f $target/src +ln -sf /mnt/host/`pwd`/../src $target/src + +# Copy boot script. +cp -p ./start $target/pkg/sys/bin + +# Done. +echo Done! +umount $target +rmdir $target diff --git a/sys/makedisk b/sys/makedisk new file mode 100755 index 000000000..3d6ec9a2c --- /dev/null +++ b/sys/makedisk @@ -0,0 +1,11 @@ +#! /bin/sh + +. ./settings + +rm $image + +dd if=/dev/zero of=$image bs=1M count=1 seek=256 + +/sbin/mke2fs -F -j $image +/sbin/tune2fs -c 0 $image +/sbin/tune2fs -i 0 $image diff --git a/sys/mountloop b/sys/mountloop new file mode 100755 index 000000000..1d5fe32fc --- /dev/null +++ b/sys/mountloop @@ -0,0 +1,8 @@ +#! /bin/sh + +. ./settings + +mkdir $target +if ! mount -o loop -t ext3 $image $target; then + exit 1 +fi diff --git a/sys/runsystem b/sys/runsystem new file mode 100755 index 000000000..fd634bdcc --- /dev/null +++ b/sys/runsystem @@ -0,0 +1,5 @@ +#! /bin/sh + +. ./settings + +linux ubd0=$image init=/pkg/sys/bin/start diff --git a/sys/settings b/sys/settings new file mode 100644 index 000000000..3968b609a --- /dev/null +++ b/sys/settings @@ -0,0 +1,2 @@ +image=/var/tmp/nix.img +target=./loop diff --git a/sys/start b/sys/start new file mode 100755 index 000000000..f822b2fa7 --- /dev/null +++ b/sys/start @@ -0,0 +1,40 @@ +#! /pkg/prog-bootstrap/bin/sh + +# This directory contains nix. +export PATH=/pkg/sys/bin + +# Add in the utilities needed for booting. +export PATH=$PATH:`nix get-pkg prog-bootstrap`/bin + +echo +echo Starting up... + +echo Mounting file systems... +mount -n -o remount,rw /dev/root / +mount -n -t proc none /proc +mount -n -t hostfs none /mnt/host + +echo Registering available src packages... +( cd /src + for i in *; do + if test -d $i; then + echo " $i" + nix register-pkg $i /src/$i + fi + done +) + +export PATH=`nix get-pkg coreutils-4.5.7`/bin:$PATH + +echo +echo "=== starting interactive shell ===" + +sh + +echo +echo Shutting down... + +umount /proc +#sync +mount -n -o remount,ro /dev/root / +#sync