Merge pull request #8575 from keszybz/non-absolute-paths

Do not require absolute paths in ExecStart and friends
This commit is contained in:
Lennart Poettering 2018-04-17 15:54:10 +02:00 committed by GitHub
commit 2cb36f7c1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 261 additions and 178 deletions

View File

@ -39,7 +39,9 @@
<refsynopsisdiv> <refsynopsisdiv>
<cmdsynopsis> <cmdsynopsis>
<command>systemd-path <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt" rep="repeat">NAME</arg></command> <command>systemd-path</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="opt" rep="repeat">NAME</arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -68,8 +70,7 @@
<varlistentry> <varlistentry>
<term><option>--suffix=</option></term> <term><option>--suffix=</option></term>
<listitem><para>The printed paths are suffixed by the <listitem><para>Printed paths are suffixed by the specified string.</para></listitem>
specified string.</para></listitem>
</varlistentry> </varlistentry>
<xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="help" />

View File

@ -288,8 +288,9 @@
<varname>ExecStop=</varname> line set. (Services lacking both <varname>ExecStart=</varname> and <varname>ExecStop=</varname> line set. (Services lacking both <varname>ExecStart=</varname> and
<varname>ExecStop=</varname> are not valid.)</para> <varname>ExecStop=</varname> are not valid.)</para>
<para>For each of the specified commands, the first argument must be an absolute path to an <para>For each of the specified commands, the first argument must be either an absolute path to an executable
executable. Optionally, this filename may be prefixed with a number of special characters:</para> or a simple file name without any slashes. Optionally, this filename may be prefixed with a number of special
characters:</para>
<table> <table>
<title>Special executable prefixes</title> <title>Special executable prefixes</title>
@ -991,11 +992,9 @@
<literal>&amp;</literal>, and <emphasis>other elements of shell <literal>&amp;</literal>, and <emphasis>other elements of shell
syntax are not supported</emphasis>.</para> syntax are not supported</emphasis>.</para>
<para>The command to execute must be an absolute path name. It may <para>The command to execute may contain spaces, but control characters are not allowed.</para>
contain spaces, but control characters are not allowed.</para>
<para>The command line accepts <literal>%</literal> specifiers as <para>The command line accepts <literal>%</literal> specifiers as described in
described in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>Basic environment variable substitution is supported. Use <para>Basic environment variable substitution is supported. Use
@ -1009,10 +1008,21 @@
For this type of expansion, quotes are respected when splitting For this type of expansion, quotes are respected when splitting
into words, and afterwards removed.</para> into words, and afterwards removed.</para>
<para>If the command is not a full (absolute) path, it will be resolved to a full path using a
fixed search path determinted at compilation time. Searched directories include
<filename>/usr/local/bin/</filename>, <filename>/usr/bin/</filename>, <filename>/bin/</filename>
on systems using split <filename>/usr/bin/</filename> and <filename>/bin/</filename>
directories, and their <filename>sbin/</filename> counterparts on systems using split
<filename>bin/</filename> and <filename>sbin/</filename>. It is thus safe to use just the
executable name in case of executables located in any of the "standard" directories, and an
absolute path must be used in other cases. Using an absolute path is recommended to avoid
ambiguity. Hint: this search path may be queried using
<command>systemd-path search-binaries-default</command>.</para>
<para>Example:</para> <para>Example:</para>
<programlisting>Environment="ONE=one" 'TWO=two two' <programlisting>Environment="ONE=one" 'TWO=two two'
ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting> ExecStart=echo $ONE $TWO ${TWO}</programlisting>
<para>This will execute <command>/bin/echo</command> with four <para>This will execute <command>/bin/echo</command> with four
arguments: <literal>one</literal>, <literal>two</literal>, arguments: <literal>one</literal>, <literal>two</literal>,
@ -1022,7 +1032,7 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
<programlisting>Environment=ONE='one' "TWO='two two' too" THREE= <programlisting>Environment=ONE='one' "TWO='two two' too" THREE=
ExecStart=/bin/echo ${ONE} ${TWO} ${THREE} ExecStart=/bin/echo ${ONE} ${TWO} ${THREE}
ExecStart=/bin/echo $ONE $TWO $THREE</programlisting> ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
<para>This results in <filename>echo</filename> being <para>This results in <filename>/bin/echo</filename> being
called twice, the first time with arguments called twice, the first time with arguments
<literal>'one'</literal>, <literal>'one'</literal>,
<literal>'two two' too</literal>, <literal></literal>, <literal>'two two' too</literal>, <literal></literal>,
@ -1048,27 +1058,27 @@ ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
<para>Note that shell command lines are not directly supported. If <para>Note that shell command lines are not directly supported. If
shell command lines are to be used, they need to be passed shell command lines are to be used, they need to be passed
explicitly to a shell implementation of some kind. Example:</para> explicitly to a shell implementation of some kind. Example:</para>
<programlisting>ExecStart=/bin/sh -c 'dmesg | tac'</programlisting> <programlisting>ExecStart=sh -c 'dmesg | tac'</programlisting>
<para>Example:</para> <para>Example:</para>
<programlisting>ExecStart=/bin/echo one ; /bin/echo "two two"</programlisting> <programlisting>ExecStart=echo one ; echo "two two"</programlisting>
<para>This will execute <command>/bin/echo</command> two times, <para>This will execute <command>echo</command> two times,
each time with one argument: <literal>one</literal> and each time with one argument: <literal>one</literal> and
<literal>two two</literal>, respectively. Because two commands are <literal>two two</literal>, respectively. Because two commands are
specified, <varname>Type=oneshot</varname> must be used.</para> specified, <varname>Type=oneshot</varname> must be used.</para>
<para>Example:</para> <para>Example:</para>
<programlisting>ExecStart=/bin/echo / &gt;/dev/null &amp; \; \ <programlisting>ExecStart=echo / &gt;/dev/null &amp; \; \
/bin/ls</programlisting> ls</programlisting>
<para>This will execute <command>/bin/echo</command> <para>This will execute <command>echo</command>
with five arguments: <literal>/</literal>, with five arguments: <literal>/</literal>,
<literal>&gt;/dev/null</literal>, <literal>&gt;/dev/null</literal>,
<literal>&amp;</literal>, <literal>;</literal>, and <literal>&amp;</literal>, <literal>;</literal>, and
<literal>/bin/ls</literal>.</para> <literal>ls</literal>.</para>
<table> <table>
<title>C escapes supported in command lines and environment variables</title> <title>C escapes supported in command lines and environment variables</title>

View File

@ -231,7 +231,6 @@ static int verify_unit(Unit *u, bool check_man) {
} }
int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators) { int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators) {
_cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;
_cleanup_free_ char *var = NULL; _cleanup_free_ char *var = NULL;
Manager *m = NULL; Manager *m = NULL;
FILE *serial = NULL; FILE *serial = NULL;
@ -284,12 +283,10 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
continue; continue;
} }
k = manager_load_unit(m, NULL, prepared, &err, &units[count]); k = manager_load_startable_unit_or_warn(m, NULL, prepared, &units[count]);
if (k < 0) { if (k < 0 && r == 0)
log_error_errno(k, "Failed to load %s: %m", *filename); r = k;
if (r == 0) else
r = k;
} else
count++; count++;
} }

View File

@ -17,17 +17,23 @@
#if HAVE_SPLIT_BIN #if HAVE_SPLIT_BIN
# define PATH_SBIN_BIN(x) x "sbin:" x "bin" # define PATH_SBIN_BIN(x) x "sbin:" x "bin"
# define PATH0_SBIN_BIN(x) x "sbin\0" x "bin"
#else #else
# define PATH0_SBIN_BIN(x) x "bin"
# define PATH_SBIN_BIN(x) x "bin" # define PATH_SBIN_BIN(x) x "bin"
#endif #endif
#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/") #define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
#define DEFAULT_PATH0_NORMAL PATH0_SBIN_BIN("/usr/local/") "\0" PATH0_SBIN_BIN("/usr/")
#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/") #define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
#define DEFAULT_PATH0_SPLIT_USR DEFAULT_PATH0_NORMAL "\0" PATH0_SBIN_BIN("/")
#if HAVE_SPLIT_USR #if HAVE_SPLIT_USR
# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR # define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
# define DEFAULT_PATH_NULSTR DEFAULT_PATH0_SPLIT_USR
#else #else
# define DEFAULT_PATH DEFAULT_PATH_NORMAL # define DEFAULT_PATH DEFAULT_PATH_NORMAL
# define DEFAULT_PATH_NULSTR DEFAULT_PATH0_NORMAL
#endif #endif
bool is_path(const char *p) _pure_; bool is_path(const char *p) _pure_;

View File

@ -639,23 +639,51 @@ int config_parse_exec(
} }
if (!string_is_safe(path)) { if (!string_is_safe(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0, log_syntax(unit, LOG_ERR, filename, line, 0,
"Executable path contains special characters%s: %s", "Executable name contains special characters%s: %s",
ignore ? ", ignoring" : "", rvalue); ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC;
}
if (!path_is_absolute(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Executable path is not absolute%s: %s",
ignore ? ", ignoring" : "", rvalue);
return ignore ? 0 : -ENOEXEC; return ignore ? 0 : -ENOEXEC;
} }
if (endswith(path, "/")) { if (endswith(path, "/")) {
log_syntax(unit, LOG_ERR, filename, line, 0, log_syntax(unit, LOG_ERR, filename, line, 0,
"Executable path specifies a directory%s: %s", "Executable path specifies a directory%s: %s",
ignore ? ", ignoring" : "", rvalue); ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC; return ignore ? 0 : -ENOEXEC;
} }
if (!path_is_absolute(path)) {
const char *prefix;
bool found = false;
if (!filename_is_valid(path)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Neither a valid executable name nor an absolute path%s: %s",
ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC;
}
/* Resolve a single-component name to a full path */
NULSTR_FOREACH(prefix, DEFAULT_PATH_NULSTR) {
_cleanup_free_ char *fullpath = NULL;
fullpath = strjoin(prefix, "/", path);
if (!fullpath)
return log_oom();
if (access(fullpath, F_OK) >= 0) {
free_and_replace(path, fullpath);
found = true;
break;
}
}
if (!found) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Executable \"%s\" not found in path \"%s\"%s",
path, DEFAULT_PATH, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
}
if (!separate_argv0) { if (!separate_argv0) {
char *w = NULL; char *w = NULL;

View File

@ -1890,28 +1890,15 @@ static int do_queue_default_job(
log_debug("Activating default unit: %s", arg_default_unit); log_debug("Activating default unit: %s", arg_default_unit);
r = manager_load_unit(m, arg_default_unit, NULL, &error, &target); r = manager_load_startable_unit_or_warn(m, arg_default_unit, NULL, &target);
if (r < 0) if (r < 0) {
log_error("Failed to load default target: %s", bus_error_message(&error, r)); log_info("Falling back to rescue target: " SPECIAL_RESCUE_TARGET);
else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND))
log_error_errno(target->load_error, "Failed to load default target: %m");
else if (target->load_state == UNIT_MASKED)
log_error("Default target masked.");
if (!target || target->load_state != UNIT_LOADED) { r = manager_load_startable_unit_or_warn(m, SPECIAL_RESCUE_TARGET, NULL, &target);
log_info("Trying to load rescue target...");
r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
if (r < 0) { if (r < 0) {
*ret_error_message = "Failed to load rescue target"; *ret_error_message = r == -ERFKILL ? "Rescue target masked"
return log_emergency_errno(r, "Failed to load rescue target: %s", bus_error_message(&error, r)); : "Failed to load rescue target";
} else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND)) { return r;
*ret_error_message = "Failed to load rescue target";
return log_emergency_errno(target->load_error, "Failed to load rescue target: %m");
} else if (target->load_state == UNIT_MASKED) {
*ret_error_message = "Rescue target masked";
log_emergency("Rescue target masked.");
return -ERFKILL;
} }
} }

View File

@ -1810,7 +1810,36 @@ int manager_load_unit(
manager_dispatch_load_queue(m); manager_dispatch_load_queue(m);
*_ret = unit_follow_merge(*_ret); *_ret = unit_follow_merge(*_ret);
return 0;
}
int manager_load_startable_unit_or_warn(
Manager *m,
const char *name,
const char *path,
Unit **ret) {
/* Load a unit, make sure it loaded fully and is not masked. */
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Unit *unit;
int r;
r = manager_load_unit(m, name, path, &error, &unit);
if (r < 0)
return log_error_errno(r, "Failed to load %s %s: %s",
name ? "unit" : "file", name ?: path,
bus_error_message(&error, r));
else if (IN_SET(unit->load_state, UNIT_ERROR, UNIT_NOT_FOUND))
return log_error_errno(unit->load_error, "Failed to load %s %s: %m",
name ? "unit" : "file", name ?: path);
else if (unit->load_state == UNIT_MASKED) {
log_error("%s %s is masked.",
name ? "Unit" : "File", name ?: path);
return -ERFKILL;
}
*ret = unit;
return 0; return 0;
} }

View File

@ -383,6 +383,7 @@ int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u); int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret); int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret);

View File

@ -335,6 +335,7 @@ _public_ int sd_path_home(uint64_t type, const char *suffix, char **path) {
if (IN_SET(type, if (IN_SET(type,
SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES,
SD_PATH_SEARCH_BINARIES_DEFAULT,
SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH, SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_SHARED,
@ -553,7 +554,17 @@ static int get_search(uint64_t type, char ***list) {
false, false,
"/etc", "/etc",
NULL); NULL);
}
case SD_PATH_SEARCH_BINARIES_DEFAULT: {
char **t;
t = strv_split_nulstr(DEFAULT_PATH_NULSTR);
if (!t)
return -ENOMEM;
*list = t;
return 0;
}}
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
@ -566,6 +577,7 @@ _public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) {
if (!IN_SET(type, if (!IN_SET(type,
SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES,
SD_PATH_SEARCH_BINARIES_DEFAULT,
SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH, SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_SHARED,

View File

@ -54,6 +54,7 @@ static const char* const path_table[_SD_PATH_MAX] = {
[SD_PATH_USER_TEMPLATES] = "user-templates", [SD_PATH_USER_TEMPLATES] = "user-templates",
[SD_PATH_USER_DESKTOP] = "user-desktop", [SD_PATH_USER_DESKTOP] = "user-desktop",
[SD_PATH_SEARCH_BINARIES] = "search-binaries", [SD_PATH_SEARCH_BINARIES] = "search-binaries",
[SD_PATH_SEARCH_BINARIES_DEFAULT] = "search-binaries-default",
[SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private", [SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private",
[SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch", [SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch",
[SD_PATH_SEARCH_SHARED] = "search-shared", [SD_PATH_SEARCH_SHARED] = "search-shared",

View File

@ -74,6 +74,7 @@ enum {
/* Search paths */ /* Search paths */
SD_PATH_SEARCH_BINARIES, SD_PATH_SEARCH_BINARIES,
SD_PATH_SEARCH_BINARIES_DEFAULT,
SD_PATH_SEARCH_LIBRARY_PRIVATE, SD_PATH_SEARCH_LIBRARY_PRIVATE,
SD_PATH_SEARCH_LIBRARY_ARCH, SD_PATH_SEARCH_LIBRARY_ARCH,
SD_PATH_SEARCH_SHARED, SD_PATH_SEARCH_SHARED,

View File

@ -553,7 +553,8 @@ tests += [
libseccomp, libseccomp,
libselinux, libselinux,
libmount, libmount,
libblkid]], libblkid],
'', 'timeout=360'],
[['src/test/test-siphash24.c'], [['src/test/test-siphash24.c'],
[], [],

View File

@ -53,16 +53,11 @@ static int test_cgroup_mask(void) {
assert_se(manager_startup(m, serial, fdset) >= 0); assert_se(manager_startup(m, serial, fdset) >= 0);
/* Load units and verify hierarchy. */ /* Load units and verify hierarchy. */
assert_se(manager_load_unit(m, "parent.slice", NULL, NULL, &parent) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "parent.slice", NULL, &parent) >= 0);
assert_se(manager_load_unit(m, "son.service", NULL, NULL, &son) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "son.service", NULL, &son) >= 0);
assert_se(manager_load_unit(m, "daughter.service", NULL, NULL, &daughter) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "daughter.service", NULL, &daughter) >= 0);
assert_se(manager_load_unit(m, "grandchild.service", NULL, NULL, &grandchild) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "grandchild.service", NULL, &grandchild) >= 0);
assert_se(manager_load_unit(m, "parent-deep.slice", NULL, NULL, &parent_deep) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "parent-deep.slice", NULL, &parent_deep) >= 0);
assert_se(parent->load_state == UNIT_LOADED);
assert_se(son->load_state == UNIT_LOADED);
assert_se(daughter->load_state == UNIT_LOADED);
assert_se(grandchild->load_state == UNIT_LOADED);
assert_se(parent_deep->load_state == UNIT_LOADED);
assert_se(UNIT_DEREF(son->slice) == parent); assert_se(UNIT_DEREF(son->slice) == parent);
assert_se(UNIT_DEREF(daughter->slice) == parent); assert_se(UNIT_DEREF(daughter->slice) == parent);
assert_se(UNIT_DEREF(parent_deep->slice) == parent); assert_se(UNIT_DEREF(parent_deep->slice) == parent);

View File

@ -47,9 +47,9 @@ int main(int argc, char *argv[]) {
assert_se(manager_startup(m, serial, fdset) >= 0); assert_se(manager_startup(m, serial, fdset) >= 0);
printf("Load1:\n"); printf("Load1:\n");
assert_se(manager_load_unit(m, "a.service", NULL, NULL, &a) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "a.service", NULL, &a) >= 0);
assert_se(manager_load_unit(m, "b.service", NULL, NULL, &b) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "b.service", NULL, &b) >= 0);
assert_se(manager_load_unit(m, "c.service", NULL, NULL, &c) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "c.service", NULL, &c) >= 0);
manager_dump_units(m, stdout, "\t"); manager_dump_units(m, stdout, "\t");
printf("Test1: (Trivial)\n"); printf("Test1: (Trivial)\n");
@ -61,8 +61,8 @@ int main(int argc, char *argv[]) {
printf("Load2:\n"); printf("Load2:\n");
manager_clear_jobs(m); manager_clear_jobs(m);
assert_se(manager_load_unit(m, "d.service", NULL, NULL, &d) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "d.service", NULL, &d) >= 0);
assert_se(manager_load_unit(m, "e.service", NULL, NULL, &e) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "e.service", NULL, &e) >= 0);
manager_dump_units(m, stdout, "\t"); manager_dump_units(m, stdout, "\t");
printf("Test2: (Cyclic Order, Unfixable)\n"); printf("Test2: (Cyclic Order, Unfixable)\n");
@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
manager_dump_jobs(m, stdout, "\t"); manager_dump_jobs(m, stdout, "\t");
printf("Load3:\n"); printf("Load3:\n");
assert_se(manager_load_unit(m, "g.service", NULL, NULL, &g) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "g.service", NULL, &g) >= 0);
manager_dump_units(m, stdout, "\t"); manager_dump_units(m, stdout, "\t");
printf("Test5: (Colliding transaction, fail)\n"); printf("Test5: (Colliding transaction, fail)\n");
@ -100,7 +100,7 @@ int main(int argc, char *argv[]) {
manager_dump_jobs(m, stdout, "\t"); manager_dump_jobs(m, stdout, "\t");
printf("Load4:\n"); printf("Load4:\n");
assert_se(manager_load_unit(m, "h.service", NULL, NULL, &h) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "h.service", NULL, &h) >= 0);
manager_dump_units(m, stdout, "\t"); manager_dump_units(m, stdout, "\t");
printf("Test10: (Unmergeable job type of auxiliary job, fail)\n"); printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");

View File

@ -132,7 +132,7 @@ static void test(Manager *m, const char *unit_name, int status_expected, int cod
assert_se(unit_name); assert_se(unit_name);
assert_se(manager_load_unit(m, unit_name, NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
check(m, unit, status_expected, code_expected); check(m, unit, status_expected, code_expected);
} }
@ -536,6 +536,10 @@ static void test_exec_capabilityboundingset(Manager *m) {
test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED); test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
} }
static void test_exec_basic(Manager *m) {
test(m, "exec-basic.service", 0, CLD_EXITED);
}
static void test_exec_ambientcapabilities(Manager *m) { static void test_exec_ambientcapabilities(Manager *m) {
int r; int r;
@ -635,6 +639,7 @@ static int run_tests(UnitFileScope scope, const test_function_t *tests) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
static const test_function_t user_tests[] = { static const test_function_t user_tests[] = {
test_exec_basic,
test_exec_ambientcapabilities, test_exec_ambientcapabilities,
test_exec_bindpaths, test_exec_bindpaths,
test_exec_capabilityboundingset, test_exec_capabilityboundingset,

View File

@ -121,7 +121,7 @@ static void test_path_exists(Manager *m) {
assert_se(m); assert_se(m);
assert_se(manager_load_unit(m, "path-exists.path", NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
assert_se(touch(test_path) >= 0); assert_se(touch(test_path) >= 0);
@ -134,7 +134,7 @@ static void test_path_existsglob(Manager *m) {
Unit *unit = NULL; Unit *unit = NULL;
assert_se(m); assert_se(m);
assert_se(manager_load_unit(m, "path-existsglob.path", NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
assert_se(touch(test_path) >= 0); assert_se(touch(test_path) >= 0);
@ -151,7 +151,7 @@ static void test_path_changed(Manager *m) {
assert_se(touch(test_path) >= 0); assert_se(touch(test_path) >= 0);
assert_se(manager_load_unit(m, "path-changed.path", NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
f = fopen(test_path, "w"); f = fopen(test_path, "w");
@ -170,7 +170,7 @@ static void test_path_modified(Manager *m) {
assert_se(touch(test_path) >= 0); assert_se(touch(test_path) >= 0);
assert_se(manager_load_unit(m, "path-modified.path", NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
f = fopen(test_path, "w"); f = fopen(test_path, "w");
@ -186,7 +186,7 @@ static void test_path_unit(Manager *m) {
assert_se(m); assert_se(m);
assert_se(manager_load_unit(m, "path-unit.path", NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
assert_se(touch(test_path) >= 0); assert_se(touch(test_path) >= 0);
@ -202,7 +202,7 @@ static void test_path_directorynotempty(Manager *m) {
assert_se(access(test_path, F_OK) < 0); assert_se(access(test_path, F_OK) < 0);
assert_se(manager_load_unit(m, "path-directorynotempty.path", NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
/* MakeDirectory default to no */ /* MakeDirectory default to no */
@ -223,7 +223,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
assert_se(access(test_path, F_OK) < 0); assert_se(access(test_path, F_OK) < 0);
assert_se(manager_load_unit(m, "path-makedirectory.path", NULL, NULL, &unit) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit) >= 0);
assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
/* Check if the directory has been created */ /* Check if the directory has been created */

View File

@ -40,8 +40,7 @@ int main(int argc, char *argv[]) {
assert_se(manager_startup(m, serial, fdset) >= 0); assert_se(manager_startup(m, serial, fdset) >= 0);
/* load idle ok */ /* load idle ok */
assert_se(manager_load_unit(m, "sched_idle_ok.service", NULL, NULL, &idle_ok) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_ok.service", NULL, &idle_ok) >= 0);
assert_se(idle_ok->load_state == UNIT_LOADED);
ser = SERVICE(idle_ok); ser = SERVICE(idle_ok);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER);
assert_se(ser->exec_context.cpu_sched_priority == 0); assert_se(ser->exec_context.cpu_sched_priority == 0);
@ -49,8 +48,7 @@ int main(int argc, char *argv[]) {
/* /*
* load idle bad. This should print a warning but we have no way to look at it. * load idle bad. This should print a warning but we have no way to look at it.
*/ */
assert_se(manager_load_unit(m, "sched_idle_bad.service", NULL, NULL, &idle_bad) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_bad.service", NULL, &idle_bad) >= 0);
assert_se(idle_bad->load_state == UNIT_LOADED);
ser = SERVICE(idle_ok); ser = SERVICE(idle_ok);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER);
assert_se(ser->exec_context.cpu_sched_priority == 0); assert_se(ser->exec_context.cpu_sched_priority == 0);
@ -59,8 +57,7 @@ int main(int argc, char *argv[]) {
* load rr ok. * load rr ok.
* Test that the default priority is moving from 0 to 1. * Test that the default priority is moving from 0 to 1.
*/ */
assert_se(manager_load_unit(m, "sched_rr_ok.service", NULL, NULL, &rr_ok) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_ok.service", NULL, &rr_ok) >= 0);
assert_se(rr_ok->load_state == UNIT_LOADED);
ser = SERVICE(rr_ok); ser = SERVICE(rr_ok);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
assert_se(ser->exec_context.cpu_sched_priority == 1); assert_se(ser->exec_context.cpu_sched_priority == 1);
@ -69,8 +66,7 @@ int main(int argc, char *argv[]) {
* load rr bad. * load rr bad.
* Test that the value of 0 and 100 is ignored. * Test that the value of 0 and 100 is ignored.
*/ */
assert_se(manager_load_unit(m, "sched_rr_bad.service", NULL, NULL, &rr_bad) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_bad.service", NULL, &rr_bad) >= 0);
assert_se(rr_bad->load_state == UNIT_LOADED);
ser = SERVICE(rr_bad); ser = SERVICE(rr_bad);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
assert_se(ser->exec_context.cpu_sched_priority == 1); assert_se(ser->exec_context.cpu_sched_priority == 1);
@ -79,8 +75,7 @@ int main(int argc, char *argv[]) {
* load rr change. * load rr change.
* Test that anything between 1 and 99 can be set. * Test that anything between 1 and 99 can be set.
*/ */
assert_se(manager_load_unit(m, "sched_rr_change.service", NULL, NULL, &rr_sched) >= 0); assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_change.service", NULL, &rr_sched) >= 0);
assert_se(rr_sched->load_state == UNIT_LOADED);
ser = SERVICE(rr_sched); ser = SERVICE(rr_sched);
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
assert_se(ser->exec_context.cpu_sched_priority == 99); assert_se(ser->exec_context.cpu_sched_priority == 99);

View File

@ -32,6 +32,7 @@ test_data_files = '''
sockets.target sockets.target
son.service son.service
sysinit.target sysinit.target
test-execute/exec-basic.service
test-execute/exec-ambientcapabilities-merge-nfsnobody.service test-execute/exec-ambientcapabilities-merge-nfsnobody.service
test-execute/exec-ambientcapabilities-merge-nobody.service test-execute/exec-ambientcapabilities-merge-nobody.service
test-execute/exec-ambientcapabilities-merge.service test-execute/exec-ambientcapabilities-merge.service

View File

@ -0,0 +1,13 @@
[Unit]
Description=Test for basic execution
[Service]
ExecStart=touch /tmp/a ; /bin/touch /tmp/b ; touch /tmp/c
ExecStart=test -f /tmp/a
ExecStart=!test -f /tmp/b
ExecStart=!!test -f /tmp/c
ExecStart=+test -f /tmp/c
ExecStartPost=rm /tmp/a /tmp/b /tmp/c
PrivateTmp=true
Type=oneshot

View File

@ -4,14 +4,14 @@ Description=Test for BindPaths= and BindReadOnlyPaths=
[Service] [Service]
Type=oneshot Type=oneshot
# Create a file in /tmp/test-exec-bindpaths # Create a file in /tmp/test-exec-bindpaths
ExecStart=/bin/sh -c 'touch /tmp/test-exec-bindpaths/thisisasimpletest' ExecStart=touch /tmp/test-exec-bindpaths/thisisasimpletest
# Then, the file can be access through /tmp # Then, the file can be access through /tmp
ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest' ExecStart=test -f /tmp/thisisasimpletest
# Also, through /tmp/test-exec-bindreadonlypaths # Also, through /tmp/test-exec-bindreadonlypaths
ExecStart=/bin/sh -c 'test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest' ExecStart=test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest
# The file cannot modify through /tmp/test-exec-bindreadonlypaths # The file cannot modify through /tmp/test-exec-bindreadonlypaths
ExecStart=/bin/sh -x -c '! touch /tmp/test-exec-bindreadonlypaths/thisisasimpletest' ExecStart=/bin/sh -x -c '! touch /tmp/test-exec-bindreadonlypaths/thisisasimpletest'
# Cleanup # Cleanup
ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest' ExecStart=rm /tmp/thisisasimpletest
BindPaths=/tmp:/tmp/test-exec-bindpaths BindPaths=/tmp:/tmp/test-exec-bindpaths
BindReadOnlyPaths=/tmp:/tmp/test-exec-bindreadonlypaths BindReadOnlyPaths=/tmp:/tmp/test-exec-bindreadonlypaths

View File

@ -2,14 +2,14 @@
Description=Test DynamicUser= migrate StateDirectory= (preparation) Description=Test DynamicUser= migrate StateDirectory= (preparation)
[Service] [Service]
ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate' ExecStart=test -w /var/lib/test-dynamicuser-migrate
ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate2/hoge' ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
ExecStart=/bin/sh -c 'test ! -L /var/lib/test-dynamicuser-migrate' ExecStart=test ! -L /var/lib/test-dynamicuser-migrate
ExecStart=/bin/sh -c 'test ! -L /var/lib/test-dynamicuser-migrate2/hoge' ExecStart=test ! -L /var/lib/test-dynamicuser-migrate2/hoge
ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate' ExecStart=test -d /var/lib/test-dynamicuser-migrate
ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate2/hoge' ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate/yay' ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay' ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
Type=oneshot Type=oneshot
DynamicUser=no DynamicUser=no

View File

@ -2,22 +2,22 @@
Description=Test DynamicUser= migrate StateDirectory= (preparation) Description=Test DynamicUser= migrate StateDirectory= (preparation)
[Service] [Service]
ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate' ExecStart=test -w /var/lib/test-dynamicuser-migrate
ExecStart=/bin/sh -c 'test -w /var/lib/test-dynamicuser-migrate2/hoge' ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
ExecStart=/bin/sh -c 'test -L /var/lib/test-dynamicuser-migrate' ExecStart=test -L /var/lib/test-dynamicuser-migrate
ExecStart=/bin/sh -c 'test -L /var/lib/test-dynamicuser-migrate2/hoge' ExecStart=test -L /var/lib/test-dynamicuser-migrate2/hoge
ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate' ExecStart=test -d /var/lib/test-dynamicuser-migrate
ExecStart=/bin/sh -c 'test -d /var/lib/test-dynamicuser-migrate2/hoge' ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
ExecStart=/bin/sh -c 'test -f /var/lib/test-dynamicuser-migrate/yay' ExecStart=test -f /var/lib/test-dynamicuser-migrate/yay
ExecStart=/bin/sh -c 'test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay' ExecStart=test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay
ExecStart=/bin/sh -c 'test -d /var/lib/private/test-dynamicuser-migrate' ExecStart=test -d /var/lib/private/test-dynamicuser-migrate
ExecStart=/bin/sh -c 'test -d /var/lib/private/test-dynamicuser-migrate2/hoge' ExecStart=test -d /var/lib/private/test-dynamicuser-migrate2/hoge
ExecStart=/bin/sh -c 'test -f /var/lib/private/test-dynamicuser-migrate/yay' ExecStart=test -f /var/lib/private/test-dynamicuser-migrate/yay
ExecStart=/bin/sh -c 'test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay' ExecStart=test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate/yay' ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
ExecStart=/bin/sh -c 'touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay' ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
ExecStart=/bin/sh -c 'touch /var/lib/private/test-dynamicuser-migrate/yay' ExecStart=touch /var/lib/private/test-dynamicuser-migrate/yay
ExecStart=/bin/sh -c 'touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay' ExecStart=touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
Type=oneshot Type=oneshot
DynamicUser=yes DynamicUser=yes

View File

@ -2,17 +2,17 @@
Description=Test DynamicUser= with StateDirectory= Description=Test DynamicUser= with StateDirectory=
[Service] [Service]
ExecStart=/bin/sh -c 'test -w /var/lib/waldo' ExecStart=test -w /var/lib/waldo
ExecStart=/bin/sh -c 'test -w /var/lib/quux/pief' ExecStart=test -w /var/lib/quux/pief
ExecStart=/bin/sh -c 'touch /var/lib/waldo/yay' ExecStart=touch /var/lib/waldo/yay
ExecStart=/bin/sh -c 'touch /var/lib/quux/pief/yayyay' ExecStart=touch /var/lib/quux/pief/yayyay
ExecStart=/bin/sh -c 'test -f /var/lib/waldo/yay' ExecStart=test -f /var/lib/waldo/yay
ExecStart=/bin/sh -c 'test -f /var/lib/quux/pief/yayyay' ExecStart=test -f /var/lib/quux/pief/yayyay
ExecStart=/bin/sh -c 'test -f /var/lib/private/waldo/yay' ExecStart=test -f /var/lib/private/waldo/yay
ExecStart=/bin/sh -c 'test -f /var/lib/private/quux/pief/yayyay' ExecStart=test -f /var/lib/private/quux/pief/yayyay
# Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates # Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates
ExecStart=/bin/sh -x -c 'test $$(find / -type d -writable 2> /dev/null | egrep -v -e \'^(/var/tmp$$|/tmp$$|/proc/|/dev/mqueue$$|/dev/shm$$|/sys/fs/bpf$$)\' | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo' ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo'
Type=oneshot Type=oneshot
DynamicUser=yes DynamicUser=yes

View File

@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=~mnt
[Service] [Service]
RestrictNamespaces=~mnt RestrictNamespaces=~mnt
ExecStart=/bin/sh -x -c 'unshare -m' ExecStart=unshare -m
Type=oneshot Type=oneshot

View File

@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=mnt
[Service] [Service]
RestrictNamespaces=mnt RestrictNamespaces=mnt
ExecStart=/bin/sh -x -c 'unshare -m' ExecStart=unshare -m
Type=oneshot Type=oneshot

View File

@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=no
[Service] [Service]
RestrictNamespaces=no RestrictNamespaces=no
ExecStart=/bin/sh -x -c 'unshare -m -u -i -n -p -f' ExecStart=unshare -m -u -i -n -p -f
Type=oneshot Type=oneshot

View File

@ -3,5 +3,5 @@ Description=Test RestrictNamespaces=yes
[Service] [Service]
RestrictNamespaces=yes RestrictNamespaces=yes
ExecStart=/bin/sh -x -c 'unshare -m' ExecStart=unshare -m
Type=oneshot Type=oneshot

View File

@ -3,22 +3,22 @@ Description=Test for specifiers
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/usr/bin/test %n = exec-specifier.service ExecStart=test %n = exec-specifier.service
ExecStart=/usr/bin/test %N = exec-specifier ExecStart=test %N = exec-specifier
ExecStart=/usr/bin/test %p = exec-specifier ExecStart=test %p = exec-specifier
ExecStart=/usr/bin/test %P = exec/specifier ExecStart=test %P = exec/specifier
ExecStart=/usr/bin/test %i = "" ExecStart=test %i = ""
ExecStart=/usr/bin/test %I = "" ExecStart=test %I = ""
ExecStart=/usr/bin/test %f = /exec/specifier ExecStart=test %f = /exec/specifier
ExecStart=/usr/bin/test %t = /run ExecStart=test %t = /run
ExecStart=/usr/bin/test %S = /var/lib ExecStart=test %S = /var/lib
ExecStart=/usr/bin/test %C = /var/cache ExecStart=test %C = /var/cache
ExecStart=/usr/bin/test %L = /var/log ExecStart=test %L = /var/log
ExecStart=/bin/sh -c 'test %u = $$(id -un 0)' ExecStart=sh -c 'test %u = $$(id -un 0)'
ExecStart=/usr/bin/test %U = 0 ExecStart=test %U = 0
ExecStart=/bin/sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6) ExecStart=sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)'
ExecStart=/bin/sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7) ExecStart=sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)'
ExecStart=/bin/sh -c 'test %m = $$(cat /etc/machine-id)' ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
ExecStart=/bin/sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')' ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
ExecStart=/bin/sh -c 'test %H = $$(hostname)' ExecStart=sh -c 'test %H = $$(hostname)'
ExecStart=/bin/sh -c 'test %v = $$(uname -r)' ExecStart=sh -c 'test %v = $$(uname -r)'

View File

@ -3,22 +3,22 @@ Description=Test for specifiers (template unit)
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/usr/bin/test %n = exec-specifier@foo-bar.service ExecStart=test %n = exec-specifier@foo-bar.service
ExecStart=/usr/bin/test %N = exec-specifier@foo-bar ExecStart=test %N = exec-specifier@foo-bar
ExecStart=/usr/bin/test %p = exec-specifier ExecStart=test %p = exec-specifier
ExecStart=/usr/bin/test %P = exec/specifier ExecStart=test %P = exec/specifier
ExecStart=/usr/bin/test %i = foo-bar ExecStart=test %i = foo-bar
ExecStart=/usr/bin/test %I = foo/bar ExecStart=test %I = foo/bar
ExecStart=/usr/bin/test %f = /foo/bar ExecStart=test %f = /foo/bar
ExecStart=/usr/bin/test %t = /run ExecStart=test %t = /run
ExecStart=/usr/bin/test %S = /var/lib ExecStart=test %S = /var/lib
ExecStart=/usr/bin/test %C = /var/cache ExecStart=test %C = /var/cache
ExecStart=/usr/bin/test %L = /var/log ExecStart=test %L = /var/log
ExecStart=/bin/sh -c 'test %u = $$(id -un 0)' ExecStart=sh -c 'test %u = $$(id -un 0)'
ExecStart=/usr/bin/test %U = 0 ExecStart=test %U = 0
ExecStart=/bin/sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6) ExecStart=sh -c 'test %h = $$(getent passwd 0 | cut -d: -f 6)'
ExecStart=/bin/sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7) ExecStart=sh -c 'test %s = $$(getent passwd 0 | cut -d: -f 7)'
ExecStart=/bin/sh -c 'test %m = $$(cat /etc/machine-id)' ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
ExecStart=/bin/sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')' ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
ExecStart=/bin/sh -c 'test %H = $$(hostname)' ExecStart=sh -c 'test %H = $$(hostname)'
ExecStart=/bin/sh -c 'test %v = $$(uname -r)' ExecStart=sh -c 'test %v = $$(uname -r)'

View File

@ -5,28 +5,28 @@ Description=Test for TemporaryFileSystem
Type=oneshot Type=oneshot
# Check directories exist # Check directories exist
ExecStart=/bin/sh -c 'test -d /var/test-exec-temporaryfilesystem/rw && test -d /var/test-exec-temporaryfilesystem/ro' ExecStart=test -d /var/test-exec-temporaryfilesystem/rw -a -d /var/test-exec-temporaryfilesystem/ro
# Check TemporaryFileSystem= are empty # Check TemporaryFileSystem= are empty
ExecStart=/bin/sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done' ExecStart=sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
# Create a file in /var # Create a file in /var
ExecStart=/bin/sh -c 'touch /var/hoge' ExecStart=touch /var/hoge
# Create a file in /var/test-exec-temporaryfilesystem/rw # Create a file in /var/test-exec-temporaryfilesystem/rw
ExecStart=/bin/sh -c 'touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem' ExecStart=touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem
# Then, the file can be access through /tmp # Then, the file can be access through /tmp
ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest-temporaryfilesystem' ExecStart=test -f /tmp/thisisasimpletest-temporaryfilesystem
# Also, through /var/test-exec-temporaryfilesystem/ro # Also, through /var/test-exec-temporaryfilesystem/ro
ExecStart=/bin/sh -c 'test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem' ExecStart=test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem
# The file cannot modify through /var/test-exec-temporaryfilesystem/ro # The file cannot modify through /var/test-exec-temporaryfilesystem/ro
ExecStart=/bin/sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem' ExecStart=sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
# Cleanup # Cleanup
ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest-temporaryfilesystem' ExecStart=rm /tmp/thisisasimpletest-temporaryfilesystem
TemporaryFileSystem=/var TemporaryFileSystem=/var
BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw