Blob Blame History Raw
From 6d8d68c8077d2ad8b2b5d8cea78ce4ef4500252d Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 21 May 2012 15:27:26 +0200
Subject: [PATCH] unit: introduce RequiredBy= setting in [Install], to
 complement WantedBy= (cherry picked from commit
 78d54bd42b87818f5d0ef862d247f9db4844fadd)

---
 man/systemd.unit.xml             |    2 ++
 src/install.c                    |   57 ++++++++++++++++++++++++++++++++++----
 src/load-fragment-gperf.gperf.m4 |    1 +
 3 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 30559b9..f2e28dc 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -914,9 +914,11 @@
 
                         <varlistentry>
                                 <term><varname>WantedBy=</varname></term>
+                                <term><varname>RequiredBy=</varname></term>
 
                                 <listitem><para>Installs a symlink in
                                 the <filename>.wants/</filename>
+                                resp. <filename>.requires/</filename>
                                 subdirectory for a unit. This has the
                                 effect that when the listed unit name
                                 is activated the unit listing it is
diff --git a/src/install.c b/src/install.c
index b5c49bd..be610e4 100644
--- a/src/install.c
+++ b/src/install.c
@@ -40,6 +40,7 @@ typedef struct {
 
         char **aliases;
         char **wanted_by;
+        char **required_by;
 } InstallInfo;
 
 typedef struct {
@@ -880,6 +881,7 @@ static void install_info_free(InstallInfo *i) {
         free(i->path);
         strv_free(i->aliases);
         strv_free(i->wanted_by);
+        strv_free(i->required_by);
         free(i);
 }
 
@@ -1018,9 +1020,10 @@ static int unit_file_load(
                 bool allow_symlink) {
 
         const ConfigTableItem items[] = {
-                { "Install", "Alias",    config_parse_strv, 0, &info->aliases   },
-                { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
-                { "Install", "Also",     config_parse_also, 0, c                },
+                { "Install", "Alias",      config_parse_strv, 0, &info->aliases     },
+                { "Install", "WantedBy",   config_parse_strv, 0, &info->wanted_by   },
+                { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
+                { "Install", "Also",       config_parse_also, 0, c                  },
                 { NULL, NULL, NULL, 0, NULL }
         };
 
@@ -1047,7 +1050,10 @@ static int unit_file_load(
         if (r < 0)
                 return r;
 
-        return strv_length(info->aliases) + strv_length(info->wanted_by);
+        return
+                strv_length(info->aliases) +
+                strv_length(info->wanted_by) +
+                strv_length(info->required_by);
 }
 
 static int unit_file_search(
@@ -1118,7 +1124,10 @@ static int unit_file_can_install(
         r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
 
         if (r >= 0)
-                r = strv_length(i->aliases) + strv_length(i->wanted_by);
+                r =
+                        strv_length(i->aliases) +
+                        strv_length(i->wanted_by) +
+                        strv_length(i->required_by);
 
         install_context_done(&c);
 
@@ -1238,6 +1247,40 @@ static int install_info_symlink_wants(
         return r;
 }
 
+static int install_info_symlink_requires(
+                InstallInfo *i,
+                const char *config_path,
+                bool force,
+                UnitFileChange **changes,
+                unsigned *n_changes) {
+
+        char **s;
+        int r = 0, q;
+
+        assert(i);
+        assert(config_path);
+
+        STRV_FOREACH(s, i->required_by) {
+                char *path;
+
+                if (!unit_name_is_valid_no_type(*s, true)) {
+                        r = -EINVAL;
+                        continue;
+                }
+
+                if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
+                        return -ENOMEM;
+
+                q = create_symlink(i->path, path, force, changes, n_changes);
+                free(path);
+
+                if (r == 0)
+                        r = q;
+        }
+
+        return r;
+}
+
 static int install_info_symlink_link(
                 InstallInfo *i,
                 LookupPaths *paths,
@@ -1287,6 +1330,10 @@ static int install_info_apply(
         if (r == 0)
                 r = q;
 
+        q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
+        if (r == 0)
+                r = q;
+
         q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
         if (r == 0)
                 r = q;
diff --git a/src/load-fragment-gperf.gperf.m4 b/src/load-fragment-gperf.gperf.m4
index e2b6522..9f0b20d 100644
--- a/src/load-fragment-gperf.gperf.m4
+++ b/src/load-fragment-gperf.gperf.m4
@@ -220,4 +220,5 @@ Path.DirectoryMode,              config_parse_mode,                  0,
 m4_dnl The [Install] section is ignored here.
 Install.Alias,                   NULL,                               0,                             0
 Install.WantedBy,                NULL,                               0,                             0
+Install.RequiredBy,              NULL,                               0,                             0
 Install.Also,                    NULL,                               0,                             0