summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Yuan <me@yhndnzj.com>2023-05-16 21:53:24 +0800
committerGitHub <noreply@github.com>2023-05-16 21:53:24 +0800
commit0313c41068a362178190eac81f64b60223bb4c0c (patch)
tree859c0475b13cc7dac6edb15fcfce44286deee0ce /src
parent3907b2563855f42562643fd26e9dec515d4ef928 (diff)
parentb5b1351317db64de1f2c944ec153208ba8174079 (diff)
downloadsystemd-0313c41068a362178190eac81f64b60223bb4c0c.tar.gz
Merge pull request #27638 from YHNdnzj/upheldby-unit-file
unit-file: support UpheldBy= in [Install] settings (adding Upholds= deps from .upholds/)
Diffstat (limited to 'src')
-rw-r--r--src/basic/unit-file.c5
-rw-r--r--src/core/load-dropin.c6
-rw-r--r--src/core/load-fragment-gperf.gperf.in1
-rw-r--r--src/shared/install.c21
-rw-r--r--src/shared/install.h1
-rw-r--r--src/systemctl/systemctl-enable.c6
-rw-r--r--src/test/test-install-root.c12
7 files changed, 39 insertions, 13 deletions
diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c
index 41422579d6..54f2137a36 100644
--- a/src/basic/unit-file.c
+++ b/src/basic/unit-file.c
@@ -250,9 +250,10 @@ bool lookup_paths_timestamp_hash_same(const LookupPaths *lp, uint64_t timestamp_
static int directory_name_is_valid(const char *name) {
- /* Accept a directory whose name is a valid unit file name ending in .wants/, .requires/ or .d/ */
+ /* Accept a directory whose name is a valid unit file name ending in .wants/, .requires/,
+ * .upholds/ or .d/ */
- FOREACH_STRING(suffix, ".wants", ".requires", ".d") {
+ FOREACH_STRING(suffix, ".wants", ".requires", ".upholds", ".d") {
_cleanup_free_ char *chopped = NULL;
const char *e;
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index 53d2a3daa1..fd45744261 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -88,7 +88,7 @@ int unit_load_dropin(Unit *u) {
assert(u);
- /* Load dependencies from .wants and .requires directories */
+ /* Load dependencies from .wants, .requires and .upholds directories */
r = process_deps(u, UNIT_WANTS, ".wants");
if (r < 0)
return r;
@@ -97,6 +97,10 @@ int unit_load_dropin(Unit *u) {
if (r < 0)
return r;
+ r = process_deps(u, UNIT_UPHOLDS, ".upholds");
+ if (r < 0)
+ return r;
+
/* Load .conf dropins */
r = unit_find_dropin_paths(u, &l);
if (r <= 0)
diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in
index 110bccb7ad..2a3c2c2cb8 100644
--- a/src/core/load-fragment-gperf.gperf.in
+++ b/src/core/load-fragment-gperf.gperf.in
@@ -580,5 +580,6 @@ Scope.OOMPolicy, config_parse_oom_policy,
Install.Alias, NULL, 0, 0
Install.WantedBy, NULL, 0, 0
Install.RequiredBy, NULL, 0, 0
+Install.UpheldBy, NULL, 0, 0
Install.Also, NULL, 0, 0
Install.DefaultInstance, NULL, 0, 0
diff --git a/src/shared/install.c b/src/shared/install.c
index 152e517ebc..7903de17b1 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -73,7 +73,8 @@ static bool install_info_has_rules(const InstallInfo *i) {
return !strv_isempty(i->aliases) ||
!strv_isempty(i->wanted_by) ||
- !strv_isempty(i->required_by);
+ !strv_isempty(i->required_by) ||
+ !strv_isempty(i->upheld_by);
}
static bool install_info_has_also(const InstallInfo *i) {
@@ -942,7 +943,7 @@ static int find_symlinks(
continue;
suffix = strrchr(de->d_name, '.');
- if (!STRPTR_IN_SET(suffix, ".wants", ".requires"))
+ if (!STRPTR_IN_SET(suffix, ".wants", ".requires", ".upholds"))
continue;
path = path_join(config_path, de->d_name);
@@ -967,7 +968,8 @@ static int find_symlinks(
log_debug_errno(r, "Failed to look up symlinks in \"%s\": %m", path);
}
- /* We didn't find any suitable symlinks in .wants or .requires directories, let's look for linked unit files in this directory. */
+ /* We didn't find any suitable symlinks in .wants, .requires or .upholds directories,
+ * let's look for linked unit files in this directory. */
rewinddir(config_dir);
return find_symlinks_in_directory(config_dir, config_path, root_dir, i,
/* ignore_destination= */ false,
@@ -1081,6 +1083,7 @@ static void install_info_clear(InstallInfo *i) {
i->aliases = strv_free(i->aliases);
i->wanted_by = strv_free(i->wanted_by);
i->required_by = strv_free(i->required_by);
+ i->upheld_by = strv_free(i->upheld_by);
i->also = strv_free(i->also);
i->default_instance = mfree(i->default_instance);
i->symlink_target = mfree(i->symlink_target);
@@ -1337,6 +1340,7 @@ static int unit_file_load(
{ "Install", "Alias", config_parse_alias, 0, &info->aliases },
{ "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
{ "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
+ { "Install", "UpheldBy", config_parse_strv, 0, &info->upheld_by },
{ "Install", "DefaultInstance", config_parse_default_instance, 0, info },
{ "Install", "Also", config_parse_also, 0, ctx },
{}
@@ -1440,7 +1444,8 @@ static int unit_file_load(
return
(int) strv_length(info->aliases) +
(int) strv_length(info->wanted_by) +
- (int) strv_length(info->required_by);
+ (int) strv_length(info->required_by) +
+ (int) strv_length(info->upheld_by);
}
static int unit_file_load_or_readlink(
@@ -2113,6 +2118,10 @@ static int install_info_apply(
if (r == 0)
r = q;
+ q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->upheld_by, ".upholds/", changes, n_changes);
+ if (r == 0)
+ r = q;
+
return r;
}
@@ -2733,8 +2742,10 @@ int unit_file_add_dependency(
if (dep == UNIT_WANTS)
l = &info->wanted_by;
- else
+ else if (dep == UNIT_REQUIRES)
l = &info->required_by;
+ else
+ l = &info->upheld_by;
strv_free(*l);
*l = strv_new(target_info->name);
diff --git a/src/shared/install.h b/src/shared/install.h
index 30b07a725f..bc0c6db828 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -92,6 +92,7 @@ struct InstallInfo {
char **aliases;
char **wanted_by;
char **required_by;
+ char **upheld_by;
char **also;
char *default_instance;
diff --git a/src/systemctl/systemctl-enable.c b/src/systemctl/systemctl-enable.c
index 6d3709705e..940f54607f 100644
--- a/src/systemctl/systemctl-enable.c
+++ b/src/systemctl/systemctl-enable.c
@@ -248,9 +248,9 @@ int verb_enable(int argc, char *argv[], void *userdata) {
}
if (carries_install_info == 0 && !ignore_carries_install_info)
- log_notice("The unit files have no installation config (WantedBy=, RequiredBy=, Also=,\n"
- "Alias= settings in the [Install] section, and DefaultInstance= for template\n"
- "units). This means they are not meant to be enabled or disabled using systemctl.\n"
+ log_notice("The unit files have no installation config (WantedBy=, RequiredBy=, UpheldBy=,\n"
+ "Also=, or Alias= settings in the [Install] section, and DefaultInstance= for\n"
+ "template units). This means they are not meant to be enabled or disabled using systemctl.\n"
" \n" /* trick: the space is needed so that the line does not get stripped from output */
"Possible reasons for having this kind of units are:\n"
"%1$s A unit may be statically enabled by being symlinked from another unit's\n"
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index 55b8894ecc..80166b17c6 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -1135,6 +1135,9 @@ TEST(verify_alias) {
verify_one(&plain_service, "alias.socket", -EXDEV, NULL);
verify_one(&plain_service, "alias@.service", -EXDEV, NULL);
verify_one(&plain_service, "alias@inst.service", -EXDEV, NULL);
+
+ /* Setting WantedBy= and RequiredBy= through Alias= is supported for the sake of backwards
+ * compatibility. */
verify_one(&plain_service, "foo.target.wants/plain.service", 0, NULL);
verify_one(&plain_service, "foo.target.wants/plain.socket", -EXDEV, NULL);
verify_one(&plain_service, "foo.target.wants/plain@.service", -EXDEV, NULL);
@@ -1143,9 +1146,14 @@ TEST(verify_alias) {
verify_one(&plain_service, "foo.target.requires/plain.socket", -EXDEV, NULL);
verify_one(&plain_service, "foo.target.requires/plain@.service", -EXDEV, NULL);
verify_one(&plain_service, "foo.target.requires/service", -EXDEV, NULL);
- verify_one(&plain_service, "foo.target.conf/plain.service", -EXDEV, NULL);
- verify_one(&plain_service, "foo.service/plain.service", -EXDEV, NULL); /* missing dir suffix */
verify_one(&plain_service, "asdf.requires/plain.service", -EXDEV, NULL); /* invalid unit name component */
+ /* The newly-added UpheldBy= (.upholds/) and other suffixes should be rejected */
+ verify_one(&plain_service, "foo.target.upholds/plain.service", -EXDEV, NULL);
+ verify_one(&plain_service, "foo.target.upholds/plain.socket", -EXDEV, NULL);
+ verify_one(&plain_service, "foo.target.upholds/plain@.service", -EXDEV, NULL);
+ verify_one(&plain_service, "foo.target.upholds/service", -EXDEV, NULL);
+ verify_one(&plain_service, "foo.service/plain.service", -EXDEV, NULL); /* missing dir suffix */
+ verify_one(&plain_service, "foo.target.conf/plain.service", -EXDEV, NULL);
verify_one(&bare_template, "alias.service", -EXDEV, NULL);
verify_one(&bare_template, "alias.socket", -EXDEV, NULL);