FOREACH_ARRAY(i, c->directories[dt].items, c->directories[dt].n_items) {
_cleanup_free_ char *path_escaped = NULL;
- path_escaped = shell_escape(i->path, ":" WHITESPACE);
+ path_escaped = shell_escape(i->path, ":\"");
if (!path_escaped)
return log_oom_debug();
- if (!strextend(&value, " ", path_escaped))
+ if (!strextend(&value, " \"", path_escaped))
return log_oom_debug();
if (!strextend(&value, ":", yes_no(FLAGS_SET(i->flags, EXEC_DIRECTORY_ONLY_CREATE))))
STRV_FOREACH(d, i->symlinks) {
_cleanup_free_ char *link_escaped = NULL;
- link_escaped = shell_escape(*d, ":" WHITESPACE);
+ link_escaped = shell_escape(*d, ":\"");
if (!link_escaped)
return log_oom_debug();
if (!strextend(&value, ":", link_escaped))
return log_oom_debug();
}
+
+ if (!strextend(&value, "\""))
+ return log_oom_debug();
}
r = serialize_item(f, key, value);
ExecDirectoryFlags exec_directory_flags = 0;
const char *p;
- /* Use EXTRACT_UNESCAPE_RELAX here, as we unescape the colons in subsequent calls */
- r = extract_first_word(&val, &tuple, WHITESPACE, EXTRACT_UNESCAPE_SEPARATORS|EXTRACT_UNESCAPE_RELAX);
+ r = extract_first_word(&val, &tuple, WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
if (r == 0)
break;
p = tuple;
- r = extract_many_words(&p, ":", EXTRACT_UNESCAPE_SEPARATORS, &path, &only_create, &read_only);
+ r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &path, &only_create, &read_only);
if (r < 0)
return r;
if (r < 2)
for (;;) {
_cleanup_free_ char *link = NULL;
- r = extract_first_word(&p, &link, ":", EXTRACT_UNESCAPE_SEPARATORS);
+ r = extract_first_word(&p, &link, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS);
if (r < 0)
return r;
if (r == 0)
test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
(void) rm_rf("/run/test-exec_runtimedirectory2", REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf("/run/test-exec_runtimedirectory-escape", REMOVE_ROOT|REMOVE_PHYSICAL);
+ test(m, "exec-runtimedirectory@foo\\x2dv1.service", 0, CLD_EXITED);
+ (void) rm_rf("/run/test-exec_runtimedirectory-escape", REMOVE_ROOT|REMOVE_PHYSICAL);
+
test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
test(m, "exec-runtimedirectory-owner.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED);
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Unit]
+Description=Test for RuntimeDirectory (escape)
+
+[Service]
+ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/backsl\ash"'
+ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/foo bar:baz\\quux"'
+ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/%I"'
+ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/%i"'
+ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/hoge ho:ge"'
+ExecStart=bash -x -c 'test -L "%t/test-exec_runtimedirectory-escape/foo:bar"'
+ExecStart=bash -x -c 'test "$(readlink %t/test-exec_runtimedirectory-escape/foo:bar)" = "hoge ho:ge"'
+Type=oneshot
+RuntimeDirectory=test-exec_runtimedirectory-escape/backsl\ash
+RuntimeDirectory="test-exec_runtimedirectory-escape/foo bar\:baz\\quux"
+RuntimeDirectory=test-exec_runtimedirectory-escape/%I
+RuntimeDirectory=test-exec_runtimedirectory-escape/%i
+RuntimeDirectory="test-exec_runtimedirectory-escape/hoge ho\:ge:test-exec_runtimedirectory-escape/foo\:bar"