summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorJanne Heß <janne@hess.ooo>2022-02-17 19:08:02 +0100
committerGitHub <noreply@github.com>2022-02-17 19:08:02 +0100
commitdcbacb0f628f7974cf07ef4ebb4c283ecf3b7055 (patch)
tree49807e2b7c4702a2871d60817a704567f93e4bf9 /nixos
parenta9d2261b0ebce48a313393c1767c75fbc2f1a74e (diff)
parent3617ecb67f447f50f79ccd9b1bdaa5e151749ec7 (diff)
downloadnixpkgs-dcbacb0f628f7974cf07ef4ebb4c283ecf3b7055.tar
nixpkgs-dcbacb0f628f7974cf07ef4ebb4c283ecf3b7055.tar.gz
nixpkgs-dcbacb0f628f7974cf07ef4ebb4c283ecf3b7055.tar.bz2
nixpkgs-dcbacb0f628f7974cf07ef4ebb4c283ecf3b7055.tar.lz
nixpkgs-dcbacb0f628f7974cf07ef4ebb4c283ecf3b7055.tar.xz
nixpkgs-dcbacb0f628f7974cf07ef4ebb4c283ecf3b7055.tar.zst
nixpkgs-dcbacb0f628f7974cf07ef4ebb4c283ecf3b7055.zip
Merge pull request #160458 from helsinki-systems/fix/stc-backslashes
nixos/switch-to-configuration: Fix backslashes in unit names
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl25
-rw-r--r--nixos/tests/switch-test.nix36
2 files changed, 51 insertions, 10 deletions
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index 68333d43a5d..a8fe14c58f0 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -173,13 +173,18 @@ sub parseSystemdIni {
 #
 # If a directory with the same basename ending in .d exists next to the unit file, it will be
 # assumed to contain override files which will be parsed as well and handled properly.
-sub parseUnit {
-    my ($unitPath) = @_;
+sub parse_unit {
+    my ($unit_path) = @_;
 
     # Parse the main unit and all overrides
-    my %unitData;
-    parseSystemdIni(\%unitData, $_) for glob("${unitPath}{,.d/*.conf}");
-    return %unitData;
+    my %unit_data;
+    # Replace \ with \\ so glob() still works with units that have a \ in them
+    # Valid characters in unit names are ASCII letters, digits, ":", "-", "_", ".", and "\"
+    $unit_path =~ s/\\/\\\\/gmsx;
+    foreach (glob "${unit_path}{,.d/*.conf}") {
+        parseSystemdIni(\%unit_data, "$_")
+    }
+    return %unit_data;
 }
 
 # Checks whether a specified boolean in a systemd unit is true
@@ -310,7 +315,7 @@ sub handleModifiedUnit {
         # Revert of the attempt: https://github.com/NixOS/nixpkgs/pull/147609
         # More details: https://github.com/NixOS/nixpkgs/issues/74899#issuecomment-981142430
     } else {
-        my %unitInfo = $newUnitInfo ? %{$newUnitInfo} : parseUnit($newUnitFile);
+        my %unitInfo = $newUnitInfo ? %{$newUnitInfo} : parse_unit($newUnitFile);
         if (parseSystemdBool(\%unitInfo, "Service", "X-ReloadIfChanged", 0) and not $unitsToRestart->{$unit} and not $unitsToStop->{$unit}) {
             $unitsToReload->{$unit} = 1;
             recordUnit($reloadListFile, $unit);
@@ -412,12 +417,12 @@ while (my ($unit, $state) = each %{$activePrev}) {
 
     if (-e $prevUnitFile && ($state->{state} eq "active" || $state->{state} eq "activating")) {
         if (! -e $newUnitFile || abs_path($newUnitFile) eq "/dev/null") {
-            my %unitInfo = parseUnit($prevUnitFile);
+            my %unitInfo = parse_unit($prevUnitFile);
             $unitsToStop{$unit} = 1 if parseSystemdBool(\%unitInfo, "Unit", "X-StopOnRemoval", 1);
         }
 
         elsif ($unit =~ /\.target$/) {
-            my %unitInfo = parseUnit($newUnitFile);
+            my %unitInfo = parse_unit($newUnitFile);
 
             # Cause all active target units to be restarted below.
             # This should start most changed units we stop here as
@@ -451,8 +456,8 @@ while (my ($unit, $state) = each %{$activePrev}) {
         }
 
         else {
-            my %old_unit_info = parseUnit($prevUnitFile);
-            my %new_unit_info = parseUnit($newUnitFile);
+            my %old_unit_info = parse_unit($prevUnitFile);
+            my %new_unit_info = parse_unit($newUnitFile);
             my $diff = compare_units(\%old_unit_info, \%new_unit_info);
             if ($diff eq 1) {
                 handleModifiedUnit($unit, $baseName, $newUnitFile, \%new_unit_info, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
diff --git a/nixos/tests/switch-test.nix b/nixos/tests/switch-test.nix
index 3357d83342d..4f297b6521d 100644
--- a/nixos/tests/switch-test.nix
+++ b/nixos/tests/switch-test.nix
@@ -145,6 +145,23 @@ import ./make-test-python.nix ({ pkgs, ...} : {
           systemd.services.test.serviceConfig."X-Test" = "test";
         };
 
+        unitWithBackslash.configuration = {
+          systemd.services."escaped\\x2ddash" = {
+            wantedBy = [ "multi-user.target" ];
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+              ExecStart = "${pkgs.coreutils}/bin/true";
+              ExecReload = "${pkgs.coreutils}/bin/true";
+            };
+          };
+        };
+
+        unitWithBackslashModified.configuration = {
+          imports = [ unitWithBackslash.configuration ];
+          systemd.services."escaped\\x2ddash".serviceConfig.X-Test = "test";
+        };
+
         restart-and-reload-by-activation-script.configuration = {
           systemd.services = rec {
             simple-service = {
@@ -433,6 +450,25 @@ import ./make-test-python.nix ({ pkgs, ...} : {
         assert_lacks(out, "as well:")
         assert_contains(out, "would start the following units: test.service\n")
 
+        # Ensure \ works in unit names
+        out = switch_to_specialisation("${machine}", "unitWithBackslash")
+        assert_contains(out, "stopping the following units: test.service\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_contains(out, "the following new units were started: escaped\\x2ddash.service\n")
+        assert_lacks(out, "as well:")
+
+        out = switch_to_specialisation("${machine}", "unitWithBackslashModified")
+        assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_contains(out, "\nstarting the following units: escaped\\x2ddash.service\n")
+        assert_lacks(out, "the following new units were started:")
+        assert_lacks(out, "as well:")
+
     with subtest("failing units"):
         # Let the simple service fail
         switch_to_specialisation("${machine}", "simpleServiceModified")