about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile2
-rw-r--r--src/nix.c314
-rwxr-xr-xsys/bootstrap86
-rwxr-xr-xsys/makedisk11
-rwxr-xr-xsys/mountloop8
-rwxr-xr-xsys/runsystem5
-rw-r--r--sys/settings2
-rwxr-xr-xsys/start40
8 files changed, 468 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 000000000000..5f42afd04476
--- /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 000000000000..e8b18934b9c8
--- /dev/null
+++ b/src/nix.c
@@ -0,0 +1,314 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <db4/db.h>
+
+
+#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 000000000000..e2265c1dcff0
--- /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 000000000000..3d6ec9a2ce0c
--- /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 000000000000..1d5fe32fc411
--- /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 000000000000..fd634bdcca2e
--- /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 000000000000..3968b609a2ef
--- /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 000000000000..f822b2fa7e13
--- /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