liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

default.nix (3605B)


      1 # The ideal is that a Liminix system can boot with only the files in
      2 # /nix/store.  This package generates a small program that is run at early
      3 # boot (from the initramfs) to populate directories such as /etc,
      4 # /bin, /home according to whatever the configuration says
      5 # they should contain
      6 
      7 {
      8   writeText,
      9   writeFennel,
     10   buildPackages,
     11   lib,
     12   s6-init-bin,
     13   closureInfo,
     14   stdenv,
     15 }:
     16 let
     17   inherit (lib.attrsets) mapAttrsToList;
     18   escaped =
     19     msg: builtins.replaceStrings [ "\n" "=" "\"" "$" ] [ "\\x0a" "\\x3d" "\\x22" "\\x24" ] msg;
     20 
     21   visit =
     22     prefix: attrset:
     23     let
     24       makeFile =
     25         prefix: filename:
     26         {
     27           type ? "f",
     28           mode ? null,
     29           target ? null,
     30           contents ? null,
     31           file ? null,
     32           major ? null,
     33           minor ? null,
     34           uid ? 0,
     35           gid ? 0,
     36         }:
     37         let
     38           pathname = "${prefix}/${filename}";
     39           qpathname = builtins.toJSON pathname;
     40           mode' = if mode != null then mode else (if type == "d" then "0755" else "0644");
     41           cmds = {
     42             "f" = "PRINTFILE(${qpathname}, ${mode'}, ${builtins.toJSON (escaped file)});";
     43             "d" =
     44               "MKDIR(${qpathname}, ${mode'});\n" + (builtins.concatStringsSep "\n" (visit pathname contents));
     45             "c" = "MKNOD_C(${qpathname}, ${mode'}, ${major}, ${minor});";
     46             "b" = "MKNOD_B(${qpathname}, ${mode'}, ${major}, ${minor});";
     47             "s" = "LN_S(${builtins.toJSON target}, ${qpathname});";
     48             "l" = "LN(${builtins.toJSON target}, ${qpathname})";
     49             "i" = "MKNOD_P(${qpathname}, ${mode'});";
     50           };
     51           cmd = cmds.${type};
     52           chown =
     53             if uid > 0 || gid > 0 then "\nCHOWN(${qpathname},${toString uid},${toString gid});\n" else "";
     54         in
     55         "unlink(${qpathname}); ${cmd} ${chown}";
     56     in
     57     mapAttrsToList (makeFile prefix) attrset;
     58 in
     59 attrset:
     60 let
     61   activateScript = writeText "activate.c" ''
     62     #include "defs.h"
     63     int main(int argc, char* argv[]) {
     64       chdir(argv[1]);
     65       ${(builtins.concatStringsSep "\n" (visit "." attrset))}
     66     }
     67   '';
     68 in
     69 stdenv.mkDerivation {
     70   name = "system-configuration";
     71   src = ./.;
     72 
     73   CFLAGS = "-Os";
     74   LDFLAGS = "-static -Xlinker -static";
     75 
     76   postConfigure = ''
     77     cp ${activateScript} activate.c
     78   '';
     79   makeFlags = [ "activate" ];
     80   installPhase = ''
     81     closure=${closureInfo { rootPaths = [ activateScript ]; }}
     82     mkdir -p $out/bin $out/etc
     83     cp $closure/store-paths $out/etc/nix-store-paths
     84     $STRIP --remove-section=.note  --remove-section=.comment --strip-all activate -o $out/bin/activate
     85     ln -s ${s6-init-bin}/bin/init $out/bin/init
     86     cp -p ${writeFennel "restart-services" { } ./restart-services.fnl} $out/bin/restart-services
     87     cat > $out/bin/install <<EOF
     88     #!/bin/sh -e
     89     prefix=\''${1-/}
     90     src=\''${prefix}$out
     91     dest=\$prefix
     92     ${
     93       # if we are running on a normal mounted system then
     94       # the actual device root is mounted on /persist
     95       # and /nix is bind mounted from /persist/nix
     96       # (see the code in preinit). So we need to check for this
     97       # case otherwise we will install into a ramfs/rootfs
     98       ""
     99     }
    100     if test -d \$dest/persist; then dest=\$dest/persist; fi
    101     cp -v -fP \$src/bin/* \$src/etc/* \$dest
    102     ${
    103       if attrset ? boot then
    104         ''
    105           (cd \$dest
    106            test -d boot || mkdir boot
    107            cd boot
    108            cp ../${lib.strings.removePrefix "/" attrset.boot.target}/* .
    109            sync; sync
    110           )
    111         ''
    112       else
    113         ""
    114     }
    115     EOF
    116     chmod +x $out/bin/install
    117   '';
    118 }