about summary refs log tree commit diff
path: root/nixos/modules/system/activation/switch-to-configuration.pl
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2015-10-22 19:40:00 +0200
committeraszlig <aszlig@redmoonstudios.org>2015-10-22 19:40:00 +0200
commit26963cfc2dfd8ba6bce927535317d799dda15102 (patch)
tree9fc66fc6d3bb6d78f2865930d2dfd4e99eafe3ac /nixos/modules/system/activation/switch-to-configuration.pl
parentf15420b0fe28e35a18aab348bbccdecef19e58c8 (diff)
downloadnixlib-26963cfc2dfd8ba6bce927535317d799dda15102.tar
nixlib-26963cfc2dfd8ba6bce927535317d799dda15102.tar.gz
nixlib-26963cfc2dfd8ba6bce927535317d799dda15102.tar.bz2
nixlib-26963cfc2dfd8ba6bce927535317d799dda15102.tar.lz
nixlib-26963cfc2dfd8ba6bce927535317d799dda15102.tar.xz
nixlib-26963cfc2dfd8ba6bce927535317d799dda15102.tar.zst
nixlib-26963cfc2dfd8ba6bce927535317d799dda15102.zip
switch-to-configuration: Fix unit name quoting.
Clearly it would be the best if we'd directly generate mount units
instead of converting /etc/fstab. But in order to do that we need to
test it throughly so this approach is for the next stable release.

This fix however is intended for inclusion into release-14.12 and
release-15.09.

Using a simple regular expression unfortunately isn't sufficient for
proper mount unit name quoting/escaping and there is a utility in
systemd called systemd-escape which does nothing less than that.

Of course, using an external program to escape the unit name is way more
expensive and causes us to fork for each mount point.

But given that we already do quite a lot of forks just for unit starting
and stopping, I think it doesn't matter that much. Well, except if you
have a whole bunch of mount points.

However, if the latter is the case and you have thousands of mount
points, you probably have stumbled over this already if your mount point
contains a dash.

As for my motivation to fix this: I've stumbled on this while trying to
fix the "none" backend test for NixOps (see NixOS/nixops#350), where the
target machines use /nix/.ro-store and /nix/.rw-store as mount points.

The implementation we had so far did improperly escape it so those mount
points got the following unit files:

 * nix-.ro-store.mount
 * nix-.rw-store.mount

The correct names for these units are however:

 * nix-.ro\x2dstore.mount
 * nix-.rw\x2dstore.mount

So using systemd-escape now properly generates these names.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Diffstat (limited to 'nixos/modules/system/activation/switch-to-configuration.pl')
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl14
1 files changed, 7 insertions, 7 deletions
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index 655fbab2a843..747de89905dc 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -261,12 +261,12 @@ while (my ($unit, $state) = each %{$activePrev}) {
 
 sub pathToUnitName {
     my ($path) = @_;
-    die unless substr($path, 0, 1) eq "/";
-    return "-" if $path eq "/";
-    $path = substr($path, 1);
-    $path =~ s/\//-/g;
-    # FIXME: handle - and unprintable characters.
-    return $path;
+    open my $cmd, "-|", "systemd-escape", "--suffix=mount", "-p", $path
+        or die "Unable to escape $path!\n";
+    my $escaped = join "", <$cmd>;
+    chomp $escaped;
+    close $cmd or die;
+    return $escaped;
 }
 
 sub unique {
@@ -290,7 +290,7 @@ my ($newFss, $newSwaps) = parseFstab "$out/etc/fstab";
 foreach my $mountPoint (keys %$prevFss) {
     my $prev = $prevFss->{$mountPoint};
     my $new = $newFss->{$mountPoint};
-    my $unit = pathToUnitName($mountPoint) . ".mount";
+    my $unit = pathToUnitName($mountPoint);
     if (!defined $new) {
         # Filesystem entry disappeared, so unmount it.
         $unitsToStop{$unit} = 1;