From b22481d03a686f59ee2a2dbba5ee4ff7b10c6594 Mon Sep 17 00:00:00 2001 From: Daiderd Jordan Date: Wed, 17 Jun 2020 18:29:20 +0200 Subject: [PATCH] etc: allow replacing files with known content This enables replacing existing system files like /etc/bashrc by default while keeping the safer behaviour for other files like /etc/passwd, etc. that could potentially cause major problems for the system when replaced. --- modules/lib/write-text.nix | 6 ++++++ modules/system/etc.nix | 24 +++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/modules/lib/write-text.nix b/modules/lib/write-text.nix index 7719a230..ddf40769 100644 --- a/modules/lib/write-text.nix +++ b/modules/lib/write-text.nix @@ -44,6 +44,12 @@ in Path of the source file. ''; }; + + knownSha256Hashes = mkOption { + internal = true; + type = types.listOf types.str; + default = []; + }; }; config = { diff --git a/modules/system/etc.nix b/modules/system/etc.nix index 6577aec5..fc1ff064 100644 --- a/modules/system/etc.nix +++ b/modules/system/etc.nix @@ -44,6 +44,9 @@ in # Set up the statically computed bits of /etc. echo "setting up /etc..." >&2 + declare -A etcSha256Hashes + ${concatMapStringsSep "\n" (attr: "etcSha256Hashes['/etc/${attr.target}']='${concatStringsSep " " attr.knownSha256Hashes}'") etc} + ln -sfn "$(readlink -f $systemConfig/etc)" /etc/static for f in $(find /etc/static/* -type l); do @@ -53,9 +56,24 @@ in mkdir -p "$d" fi if [ -e "$l" ]; then - if [ "$(readlink $l)" != "$f" ]; then + if [ "$(readlink "$l")" != "$f" ]; then if ! grep -q /etc/static "$l"; then - echo "warning: not linking environment.etc.\"''${l#/etc/}\" because $l exists, skipping..." >&2 + o=''$(shasum -a256 "$l") + o=''${o%% *} + for h in ''${etcSha256Hashes["$l"]}; do + if [ "$o" = "$h" ]; then + mv "$l" "$l.orig" + ln -s "$f" "$l" + break + else + h= + fi + done + + if [ -z "$h" ]; then + echo "error: not linking environment.etc.\"''${l#/etc/}\" because $l already exists, skipping..." >&2 + echo "existing file has unknown content $o, move and activate again to apply" >&2 + fi fi fi else @@ -66,7 +84,7 @@ in for l in $(find /etc/* -type l 2> /dev/null); do f="$(echo $l | sed 's,/etc/,/etc/static/,')" f=/etc/static/''${l#/etc/} - if [ "$(readlink $l)" = "$f" -a ! -e "$(readlink -f $l)" ]; then + if [ "$(readlink "$l")" = "$f" -a ! -e "$(readlink -f "$l")" ]; then rm "$l" fi done