From 3251123a779636d6883032f158ff99ebe98c0da4 Mon Sep 17 00:00:00 2001 From: Daniel Olsen Date: Sat, 11 Jun 2022 11:18:54 +0200 Subject: nixos/lib.escapeSystemdPath: Implement the correct algorithm for escaping names in systemd units Co-authored-by: ajs124 --- nixos/lib/utils.nix | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'nixos/lib/utils.nix') diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix index f646f70323e..9eefa80d1c8 100644 --- a/nixos/lib/utils.nix +++ b/nixos/lib/utils.nix @@ -39,11 +39,19 @@ rec { || hasPrefix a'.mountPoint b'.mountPoint || any (hasPrefix a'.mountPoint) b'.depends; - # Escape a path according to the systemd rules, e.g. /dev/xyzzy - # becomes dev-xyzzy. FIXME: slow. - escapeSystemdPath = s: - replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"] - (removePrefix "/" s); + # Escape a path according to the systemd rules. FIXME: slow + # The rules are described in systemd.unit(5) as follows: + # The escaping algorithm operates as follows: given a string, any "/" character is replaced by "-", and all other characters which are not ASCII alphanumerics, ":", "_" or "." are replaced by C-style "\x2d" escapes. In addition, "." is replaced with such a C-style escape when it would appear as the first character in the escaped string. + # When the input qualifies as absolute file system path, this algorithm is extended slightly: the path to the root directory "/" is encoded as single dash "-". In addition, any leading, trailing or duplicate "/" characters are removed from the string before transformation. Example: /foo//bar/baz/ becomes "foo-bar-baz". + escapeSystemdPath = s: let + replacePrefix = p: r: s: (if (hasPrefix p s) then r + (removePrefix p s) else s); + trim = s: removeSuffix "/" (removePrefix "/" s); + normalizedPath = strings.normalizePath s; + in + replaceChars ["/"] ["-"] + (replacePrefix "." (strings.escapeC ["."] ".") + (strings.escapeC (stringToCharacters " !\"#$%&'()*+,;<=>=@[\\]^`{|}~-") + (if normalizedPath == "/" then normalizedPath else trim normalizedPath))); # Quotes an argument for use in Exec* service lines. # systemd accepts "-quoted strings with escape sequences, toJSON produces -- cgit 1.4.1