summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-08-31 02:53:54 +0900
committerGitHub <noreply@github.com>2019-08-31 02:53:54 +0900
commit6bc536fc94795fee0f831ec8d213db8f379b1693 (patch)
tree2b6704c74bdc01fd6804e3b256d6a41c66b96042
parent07125d24eedb71693b3bf2b1f0730cd01aaac2dd (diff)
parent890befcf47b19c9aff4d9d92ab3a1231b29770ab (diff)
downloadsystemd-6bc536fc94795fee0f831ec8d213db8f379b1693.tar.gz
Merge pull request #13436 from systemd/hidden-units-are-good-units
Hidden units are good units
-rw-r--r--man/systemd.unit.xml28
-rw-r--r--src/basic/strv.h12
-rw-r--r--src/shared/unit-file.c13
-rw-r--r--src/test/test-unit-name.c3
4 files changed, 44 insertions, 12 deletions
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 8307be1d33..acb09d005d 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -104,16 +104,24 @@
<citerefentry><refentrytitle>systemd.scope</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
- <para>Unit files are loaded from a set of paths determined during
- compilation, described in the next section.</para>
-
- <para>Unit files can be parameterized by a single argument called the "instance name". The unit
- is then constructed based on a "template file" which serves as the definition of multiple
- services or other units. A template unit must have a single <literal>@</literal> at the end of
- the name (right before the type suffix). The name of the full unit is formed by inserting the
- instance name between <literal>@</literal> and the unit type suffix. In the unit file itself,
- the instance parameter may be referred to using <literal>%i</literal> and other specifiers, see
- below.</para>
+ <para>Unit files are loaded from a set of paths determined during compilation, described in the next
+ section.</para>
+
+ <para>Valid unit names consist of a "name prefix" and a dot and a suffix specifying the unit type. The
+ "unit prefix" must consist of one or more valid characters (ASCII letters, digits, <literal>:</literal>,
+ <literal>-</literal>, <literal>_</literal>, <literal>.</literal>, and <literal>\</literal>). The total
+ length of the unit name including the suffix must not exceed 256 characters. The type suffix must be one
+ of <literal>.service</literal>, <literal>.socket</literal>, <literal>.device</literal>,
+ <literal>.mount</literal>, <literal>.automount</literal>, <literal>.swap</literal>,
+ <literal>.target</literal>, <literal>.path</literal>, <literal>.timer</literal>,
+ <literal>.slice</literal>, or <literal>.scope</literal>.</para>
+
+ <para>Units names can be parameterized by a single argument called the "instance name". The unit is then
+ constructed based on a "template file" which serves as the definition of multiple services or other
+ units. A template unit must have a single <literal>@</literal> at the end of the name (right before the
+ type suffix). The name of the full unit is formed by inserting the instance name between
+ <literal>@</literal> and the unit type suffix. In the unit file itself, the instance parameter may be
+ referred to using <literal>%i</literal> and other specifiers, see below.</para>
<para>Unit files may contain additional options on top of those
listed here. If systemd encounters an unknown option, it will
diff --git a/src/basic/strv.h b/src/basic/strv.h
index e80964acd1..fbfa96a566 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -157,6 +157,18 @@ void strv_print(char **l);
_found; \
})
+#define ENDSWITH_SET(p, ...) \
+ ({ \
+ const char *_p = (p); \
+ char *_found = NULL, **_i; \
+ STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \
+ _found = endswith(_p, *_i); \
+ if (_found) \
+ break; \
+ } \
+ _found; \
+ })
+
#define FOREACH_STRING(x, y, ...) \
for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \
x; \
diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c
index e15ce26940..4a5f23e6c1 100644
--- a/src/shared/unit-file.c
+++ b/src/shared/unit-file.c
@@ -242,10 +242,19 @@ int unit_file_build_name_map(
if (!lookup_paths_mtime_exclude(lp, *dir))
mtime = MAX(mtime, timespec_load(&st.st_mtim));
- FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
+ FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
char *filename;
_cleanup_free_ char *_filename_free = NULL, *simplified = NULL;
const char *suffix, *dst = NULL;
+ bool valid_unit_name;
+
+ valid_unit_name = unit_name_is_valid(de->d_name, UNIT_NAME_ANY);
+
+ /* We only care about valid units and dirs with certain suffixes, let's ignore the
+ * rest. */
+ if (!valid_unit_name &&
+ !ENDSWITH_SET(de->d_name, ".wants", ".requires", ".d"))
+ continue;
filename = path_join(*dir, de->d_name);
if (!filename)
@@ -260,7 +269,7 @@ int unit_file_build_name_map(
} else
_filename_free = filename; /* Make sure we free the filename. */
- if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+ if (!valid_unit_name)
continue;
assert_se(suffix = strrchr(de->d_name, '.'));
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 7fe732cf2f..25c649828e 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -50,6 +50,9 @@ static void test_unit_name_is_valid(void) {
assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE));
assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE));
assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid(".test.service", UNIT_NAME_PLAIN));
+ assert_se( unit_name_is_valid(".test@.service", UNIT_NAME_TEMPLATE));
+ assert_se( unit_name_is_valid("_strange::::.service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY));
assert_se(!unit_name_is_valid("", UNIT_NAME_ANY));