diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2010-09-13 17:26:42 +0000 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2010-09-13 17:26:42 +0000 |
commit | c8d1774f0977325ffa5bab56487ae48e072b3f2d (patch) | |
tree | 6379bd5a5817e1efb363daa7de81caae092b1160 | |
parent | 0fccd7bb492fabe8985087f2790ec6d2168978d1 (diff) | |
download | nixpkgs-c8d1774f0977325ffa5bab56487ae48e072b3f2d.tar nixpkgs-c8d1774f0977325ffa5bab56487ae48e072b3f2d.tar.gz nixpkgs-c8d1774f0977325ffa5bab56487ae48e072b3f2d.tar.bz2 nixpkgs-c8d1774f0977325ffa5bab56487ae48e072b3f2d.tar.lz nixpkgs-c8d1774f0977325ffa5bab56487ae48e072b3f2d.tar.xz nixpkgs-c8d1774f0977325ffa5bab56487ae48e072b3f2d.tar.zst nixpkgs-c8d1774f0977325ffa5bab56487ae48e072b3f2d.zip |
* Speed up the initialisation of /etc in the activation script a lot
by doing it in Perl instead of in Bash. Forking a zillion times is slow. svn path=/nixos/trunk/; revision=23766
-rw-r--r-- | modules/system/etc/etc.nix | 32 | ||||
-rw-r--r-- | modules/system/etc/setup-etc.pl | 65 |
2 files changed, 68 insertions, 29 deletions
diff --git a/modules/system/etc/etc.nix b/modules/system/etc/etc.nix index 0a2f6665be0..3dec801b407 100644 --- a/modules/system/etc/etc.nix +++ b/modules/system/etc/etc.nix @@ -37,7 +37,7 @@ let chmod ${mode} "$target" ''; - makeEtc = pkgs.stdenv.mkDerivation { + etc = pkgs.stdenv.mkDerivation { name = "etc"; builder = ./make-etc.sh; @@ -53,39 +53,13 @@ in { require = [option]; - system.build.etc = makeEtc; + system.build.etc = etc; system.activationScripts.etc = stringAfter [ "systemConfig" "stdio" ] '' # Set up the statically computed bits of /etc. echo "setting up /etc..." - staticEtc=/etc/static - rm -f $staticEtc - ln -s ${makeEtc}/etc $staticEtc - for i in $(cd $staticEtc && find * -type l); do - mkdir -p /etc/$(dirname $i) - rm -f /etc/$i - if test -e "$staticEtc/$i.mode"; then - # Create a regular file in /etc. - cp $staticEtc/$i /etc/$i - chown 0.0 /etc/$i - chmod "$(cat "$staticEtc/$i.mode")" /etc/$i - else - # Create a symlink in /etc. - ln -s $staticEtc/$i /etc/$i - fi - done - - # Remove dangling symlinks that point to /etc/static. These are - # configuration files that existed in a previous configuration but not - # in the current one. For efficiency, don't look under /etc/nixos - # (where all the NixOS sources live). - for i in $(find /etc/ \( -path /etc/nixos -prune \) -o -type l); do - target=$(readlink "$i") - if test "''${target:0:''${#staticEtc}}" = "$staticEtc" -a ! -e "$i"; then - rm -f "$i" - fi - done + ${pkgs.perl}/bin/perl ${./setup-etc.pl} ${etc}/etc ''; } diff --git a/modules/system/etc/setup-etc.pl b/modules/system/etc/setup-etc.pl new file mode 100644 index 00000000000..c6b932cf202 --- /dev/null +++ b/modules/system/etc/setup-etc.pl @@ -0,0 +1,65 @@ +use strict; +use File::Find; +use File::Copy; +use File::Path; +use File::Basename; + +my $etc = $ARGV[0] or die; +my $static = "/etc/static"; + +sub atomicSymlink { + my ($source, $target) = @_; + my $tmp = "$target.tmp"; + unlink $tmp; + symlink $source, $tmp or return 1; + rename $tmp, $target or return 1; + return 1; +} + + +# Atomically update /etc/static to point at the etc files of the +# current configuration. +atomicSymlink $etc, $static or die; + + +# For every file in the etc tree, create a corresponding symlink in +# /etc to /etc/static. The indirection through /etc/static is to make +# switching to a new configuration somewhat more atomic. +sub link { + my $fn = substr $File::Find::name, length($etc) + 1 or next; + my $target = "/etc/$fn"; + File::Path::make_path(dirname $target); + if (-e "$_.mode") { + open MODE, "<$_.mode"; + my $mode = <MODE>; chomp $mode; + close MODE; + copy "$static/$fn", "$target.tmp" or warn; + chmod oct($mode), "$target.tmp" or warn; + rename "$target.tmp", $target or warn; + } elsif (-l "$_") { + atomicSymlink "$static/$fn", $target or warn; + } +} + +find(\&link, $etc); + + +# Remove dangling symlinks that point to /etc/static. These are +# configuration files that existed in a previous configuration but not +# in the current one. For efficiency, don't look under /etc/nixos +# (where all the NixOS sources live). +sub cleanup { + if ($File::Find::name eq "/etc/nixos") { + $File::Find::prune = 1; + return; + } + if (-l $_) { + my $target = readlink $_; + if (substr($target, 0, length $static) eq $static) { + my $x = "/etc/static/" . substr($File::Find::name, length "/etc/"); + unlink "$_" unless -e "$x"; + } + } +} + +find(\&cleanup, "/etc"); |