]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
unit-file: support UpheldBy= in [Install] settings (adding Upholds= deps
authorMike Yuan <me@yhndnzj.com>
Sun, 14 May 2023 09:48:25 +0000 (17:48 +0800)
committerMike Yuan <me@yhndnzj.com>
Mon, 15 May 2023 07:04:38 +0000 (15:04 +0800)
from .upholds/)

Closes #26896

man/systemctl.xml
man/systemd.unit.xml
src/basic/unit-file.c
src/core/load-dropin.c
src/core/load-fragment-gperf.gperf.in
src/shared/install.c
src/shared/install.h
src/systemctl/systemctl-enable.c

index 009aabacb9dc92d0e1198c7a26a917416be294a1..0e786fd966c9174731cf9757316567d9bd155f4e 100644 (file)
@@ -367,10 +367,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
           <listitem>
             <para>Shows units required and wanted by the specified
             units. This recursively lists units following the
-            <varname>Requires=</varname>,
-            <varname>Requisite=</varname>,
-            <varname>ConsistsOf=</varname>,
-            <varname>Wants=</varname>, <varname>BindsTo=</varname>
+            <varname>Requires=</varname>, <varname>Requisite=</varname>,
+            <varname>Wants=</varname>, <varname>ConsistsOf=</varname>,
+            <varname>BindsTo=</varname>, and <varname>Upholds=</varname>
             dependencies. If no units are specified,
             <filename>default.target</filename> is implied.</para>
 
@@ -1791,7 +1790,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
           <para>Show reverse dependencies between units with
           <command>list-dependencies</command>, i.e. follow
           dependencies of type <varname>WantedBy=</varname>,
-          <varname>RequiredBy=</varname>,
+          <varname>RequiredBy=</varname>, <varname>UpheldBy=</varname>,
           <varname>PartOf=</varname>, <varname>BoundBy=</varname>,
           instead of <varname>Wants=</varname> and similar.
           </para>
index c618e403f71ed8b9a62de7f71af33316174ad7ff..e28bfe845e6cc4971fde7ba68960018592541442 100644 (file)
 
         <para>When <varname>Upholds=b.service</varname> is used on <filename>a.service</filename>, this
         dependency will show as <varname>UpheldBy=a.service</varname> in the property listing of
-        <filename>b.service</filename>. The <varname>UpheldBy=</varname> dependency cannot be specified
-        directly.</para>
+        <filename>b.service</filename>.</para>
         </listitem>
       </varlistentry>
 
             <entry>[Unit] section</entry>
             <entry>[Install] section</entry>
           </row>
+          <row>
+            <entry><varname>Upholds=</varname></entry>
+            <entry><varname>UpheldBy=</varname></entry>
+            <entry>[Unit] section</entry>
+            <entry>[Install] section</entry>
+          </row>
           <row>
             <entry><varname>PartOf=</varname></entry>
             <entry><varname>ConsistsOf=</varname></entry>
       </tgroup>
     </table>
 
-    <para>Note: <varname>WantedBy=</varname> and <varname>RequiredBy=</varname> are
-    used in the [Install] section to create symlinks in <filename>.wants/</filename>
-    and <filename>.requires/</filename> directories. They cannot be used directly as a
-    unit configuration setting.</para>
+    <para>Note: <varname>WantedBy=</varname>, <varname>RequiredBy=</varname>, and <varname>UpheldBy=</varname>
+    are used in the [Install] section to create symlinks in <filename>.wants/</filename>,
+    <filename>.requires/</filename>, and <filename>.upholds/</filename> directories. They cannot be used
+    directly as a unit configuration setting.</para>
 
     <para>Note: <varname>ConsistsOf=</varname>, <varname>BoundBy=</varname>,
     <varname>RequisiteOf=</varname>, <varname>ConflictedBy=</varname> are created
       <varlistentry>
         <term><varname>WantedBy=</varname></term>
         <term><varname>RequiredBy=</varname></term>
+        <term><varname>UpheldBy=</varname></term>
 
         <listitem><para>This option may be used more than once, or a space-separated list of unit names may
-        be given. A symbolic link is created in the <filename>.wants/</filename> or
-        <filename>.requires/</filename> directory of each of the listed units when this unit is installed by
-        <command>systemctl enable</command>. This has the effect of a dependency of type
-        <varname>Wants=</varname> or <varname>Requires=</varname> being added from the listed unit to the
-        current unit. The primary result is that the current unit will be started when the listed unit is
-        started, see the description of <varname>Wants=</varname> and <varname>Requires=</varname> in the
-        [Unit] section for details.</para>
+        be given. A symbolic link is created in the <filename>.wants/</filename>, <filename>.requires/</filename>,
+        or <filename>.upholds/</filename> directory of each of the listed units when this unit is installed
+        by <command>systemctl enable</command>. This has the effect of a dependency of type
+        <varname>Wants=</varname>, <varname>Requires=</varname>, or <varname>Upholds=</varname> being added
+        from the listed unit to the current unit. See the description of the mentioned dependency types
+        in the [Unit] section for details.</para>
 
         <para>In case of template units listing non template units, the listing unit must have
         <varname>DefaultInstance=</varname> set, or <command>systemctl enable</command> must be called with
         an instance name. The instance (default or specified) will be added to the
-        <filename>.wants/</filename> or <filename>.requires/</filename> list of the listed unit. For example,
-        <command>WantedBy=getty.target</command> in a service <filename>getty@.service</filename> will result
-        in <command>systemctl enable getty@tty2.service</command> creating a
-        <filename>getty.target.wants/getty@tty2.service</filename> link to
+        <filename>.wants/</filename>, <filename>.requires/</filename>, or <filename>.upholds/</filename>
+        list of the listed unit. For example, <command>WantedBy=getty.target</command> in a service
+        <filename>getty@.service</filename> will result in <command>systemctl enable getty@tty2.service</command>
+        creating a <filename>getty.target.wants/getty@tty2.service</filename> link to
         <filename>getty@.service</filename>. This also applies to listing specific instances of templated
         units: this specific instance will gain the dependency. A template unit may also list a template
         unit, in which case a generic dependency will be added where each instance of the listing unit will
index 41422579d6415ecdca607043e7e9cd4dd0570a3c..54f2137a3662fa12940686daf808c1e2d1a22791 100644 (file)
@@ -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;
 
index 53d2a3daa12813df5ac480375c942e6749934e0e..fd45744261d3fd4ae2a0111d42109a5f7088825b 100644 (file)
@@ -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)
index 110bccb7ad444bc1f0fc62be973c8280b9d5f72c..2a3c2c2cb8e1a5443e7976d1e5459ca436fa43ca 100644 (file)
@@ -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
index 152e517ebc155fa4ef64ab898f5d22e5953442a5..7903de17b1a5e71b0ed5456cff2b6e9664ec8e63 100644 (file)
@@ -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);
index 30b07a725fe028ce5be9cfcffca11110a6473e58..bc0c6db828ddebcfb63e63e595239fb23111def0 100644 (file)
@@ -92,6 +92,7 @@ struct InstallInfo {
         char **aliases;
         char **wanted_by;
         char **required_by;
+        char **upheld_by;
         char **also;
 
         char *default_instance;
index 6d3709705e036fc2f12822b49f88d586d2d863a3..940f54607ff09865f9162eaadfaf15ffd32b2a26 100644 (file)
@@ -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"