systemd: Add functions.escapeSystemdExecArg[s]

This makes it available outside the NixOS `utils` context.

Changed files
+90 -25
nixos
lib
pkgs
os-specific
linux
systemd
+1 -25
nixos/lib/utils.nix
···
)
);
-
# Quotes an argument for use in Exec* service lines.
-
# systemd accepts "-quoted strings with escape sequences, toJSON produces
-
# a subset of these.
-
# Additionally we escape % to disallow expansion of % specifiers. Any lone ;
-
# in the input will be turned it ";" and thus lose its special meaning.
-
# Every $ is escaped to $$, this makes it unnecessary to disable environment
-
# substitution for the directive.
-
escapeSystemdExecArg =
-
arg:
-
let
-
s =
-
if isPath arg then
-
"${arg}"
-
else if isString arg then
-
arg
-
else if isInt arg || isFloat arg || isDerivation arg then
-
toString arg
-
else
-
throw "escapeSystemdExecArg only allows strings, paths, numbers and derivations";
-
in
-
replaceStrings [ "%" "$" ] [ "%%" "$$" ] (toJSON s);
-
-
# Quotes a list of arguments into a single string for use in a Exec*
-
# line.
-
escapeSystemdExecArgs = concatMapStringsSep " " escapeSystemdExecArg;
+
inherit (config.systemd.package.functions) escapeSystemdExecArg escapeSystemdExecArgs;
# Returns a system path for a given shell package
toShellPath =
+11
pkgs/os-specific/linux/systemd/default.nix
···
# needed - and therefore `interfaceVersion` should be incremented.
interfaceVersion = 2;
+
functions = import ./functions/default.nix {
+
inherit lib;
+
systemd = finalAttrs.finalPackage;
+
};
+
inherit
withBootloader
withCryptsetup
···
pkgsCross.${systemString}.systemd;
pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
+
+
functions = import ./functions/test.nix {
+
inherit lib;
+
systemd = finalAttrs.finalPackage;
+
ok = buildPackages.emptyFile;
+
};
};
};
+55
pkgs/os-specific/linux/systemd/functions/default.nix
···
+
/**
+
Build the `systemd.functions` library (where `systemd` is the package)
+
*/
+
{ lib, systemd }:
+
let
+
inherit (lib)
+
concatMapStringsSep
+
isDerivation
+
isFloat
+
isInt
+
isPath
+
isString
+
replaceStrings
+
;
+
inherit (builtins)
+
toJSON
+
;
+
+
/**
+
Quotes an argument for use in `Exec*` service lines.
+
Additionally we escape `%` to disallow expansion of `%` specifiers. Any lone `;`
+
in the input will be turned into `";"` and thus lose its special meaning.
+
Every `$` is escaped to `$$`, this makes it unnecessary to disable environment
+
substitution for the directive.
+
*/
+
escapeSystemdExecArg =
+
arg:
+
let
+
s =
+
if isPath arg then
+
"${arg}"
+
else if isString arg then
+
arg
+
else if isInt arg || isFloat arg || isDerivation arg then
+
toString arg
+
else
+
throw "escapeSystemdExecArg only allows strings, paths, numbers and derivations";
+
in
+
# systemd accepts "-quoted strings with escape sequences, toJSON produces
+
# a subset of these.
+
replaceStrings [ "%" "$" ] [ "%%" "$$" ] (toJSON s);
+
+
/**
+
Quotes a list of arguments into a single string for use in a Exec* line.
+
*/
+
escapeSystemdExecArgs = concatMapStringsSep " " escapeSystemdExecArg;
+
in
+
# Instead of requiring v2, we can make this library conditional on the version as needed.
+
assert systemd.interfaceVersion == 2;
+
{
+
inherit
+
escapeSystemdExecArg
+
escapeSystemdExecArgs
+
;
+
}
+23
pkgs/os-specific/linux/systemd/functions/test.nix
···
+
{
+
lib,
+
systemd,
+
ok,
+
}:
+
+
# This function is also tested in nixosTests.systemd-escaping
+
assert systemd.functions.escapeSystemdExecArg "hi" == ''"hi"'';
+
assert systemd.functions.escapeSystemdExecArg "hi there" == ''"hi there"'';
+
assert systemd.functions.escapeSystemdExecArg ''"hi there"'' == ''"\"hi there\""'';
+
assert systemd.functions.escapeSystemdExecArg ''"%$'' == ''"\"%%$$"'';
+
assert
+
systemd.functions.escapeSystemdExecArgs [
+
"hi"
+
"there"
+
] == ''"hi" "there"'';
+
assert
+
systemd.functions.escapeSystemdExecArgs [
+
"hi"
+
"%"
+
"there"
+
] == ''"hi" "%%" "there"'';
+
ok