]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add [Enable|Disable]UnitFilesWithFlags DBUS methods
authorLuca Boccassi <luca.boccassi@microsoft.com>
Tue, 1 Sep 2020 16:08:29 +0000 (17:08 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 4 Sep 2020 15:56:37 +0000 (17:56 +0200)
The new methods work as the unflavoured ones, but takes flags as a
single uint64_t DBUS parameters instead of different booleans, so
that it can be extended without breaking backward compatibility.
Add new flag to allow adding/removing symlinks in
[/etc|/run]/systemd/system.attached so that portable services
configuration files can be self-contained in those directories, without
affecting the system services directories.
Use the new methods and flags from portablectl --enable.

Useful in case /etc is read-only, with only the portable services
directories being mounted read-write.

man/org.freedesktop.systemd1.xml
src/core/dbus-manager.c
src/portable/portablectl.c
src/shared/install.c
src/shared/install.h

index 1093458e8927d256a53c52186e9ec3d8749d331b..998caccc80ef1ae292181094ce39a50afc5ad3c6 100644 (file)
@@ -179,6 +179,13 @@ node /org/freedesktop/systemd1 {
       DisableUnitFiles(in  as files,
                        in  b runtime,
                        out a(sss) changes);
+      EnableUnitFilesWithFlags(in  as files,
+                               in  t flags,
+                               out b carries_install_info,
+                               out a(sss) changes);
+      DisableUnitFilesWithFlags(in  as files,
+                                in  t flags,
+                                out a(sss) changes);
       ReenableUnitFiles(in  as files,
                         in  b runtime,
                         in  b force,
@@ -836,6 +843,10 @@ node /org/freedesktop/systemd1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="DisableUnitFiles()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="EnableUnitFilesWithFlags()"/>
+
+    <variablelist class="dbus-method" generated="True" extra-ref="DisableUnitFilesWithFlags()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="ReenableUnitFiles()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="LinkUnitFiles()"/>
@@ -1292,6 +1303,20 @@ node /org/freedesktop/systemd1 {
       <para>Similarly, <function>DisableUnitFiles()</function> disables one or more units in the system,
       i.e. removes all symlinks to them in <filename>/etc</filename> and <filename>/run</filename>.</para>
 
+      <para>The <function>EnableUnitFilesWithFlags()</function> and <function>DisableUnitFilesWithFlags()</function>
+      take in options as flags instead of booleans to allow for extendability, defined as follows:</para>
+
+      <programlisting>
+#define SD_SYSTEMD_UNIT_RUNTIME  (UINT64_C(1) &lt;&lt; 0)
+#define SD_SYSTEMD_UNIT_FORCE    (UINT64_C(1) &lt;&lt; 1)
+#define SD_SYSTEMD_UNIT_PORTABLE (UINT64_C(1) &lt;&lt; 2)
+      </programlisting>
+
+      <para><varname>SD_SYSTEMD_UNIT_RUNTIME</varname> will enable or disable the unit for runtime only,
+      <varname>SD_SYSTEMD_UNIT_FORCE</varname> controls whether symlinks pointing to other units shall be
+      replaced if necessary. <varname>SD_SYSTEMD_UNIT_PORTABLE</varname> will add or remove the symlinks in
+      <filename>/etc/systemd/system.attached</filename> and <filename>/run/systemd/system.attached</filename>.</para>
+
       <para>Similarly, <function>ReenableUnitFiles()</function> applies the changes to one or more units that
       would result from disabling and enabling the unit quickly one after the other in an atomic
       fashion. This is useful to apply updated [Install] information contained in unit files.</para>
@@ -1480,6 +1505,7 @@ node /org/freedesktop/systemd1 {
       <function>RestartUnit()</function> and similar, <function>SetProperty()</function>) require
       <interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file
       enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>,
+      <function>EnableUnitFilesWithFlags()</function>, <function>DisableUnitFilesWithFlags()</function>,
       <function>ReenableUnitFiles()</function>, <function>LinkUnitFiles()</function>,
       <function>PresetUnitFiles</function>, <function>MaskUnitFiles</function>, and similar) require
       <interfacename>org.freedesktop.systemd1.manage-unit-files</interfacename>. Operations which modify the
index 07e139c5ad265680de5bf1a9b1b849b97637e816..16945d09c484851bdfadb8e09665f41ed6d7da9a 100644 (file)
@@ -2083,7 +2083,7 @@ static int method_enable_unit_files_generic(
         UnitFileChange *changes = NULL;
         size_t n_changes = 0;
         UnitFileFlags flags;
-        int runtime, force, r;
+        int r;
 
         assert(message);
         assert(m);
@@ -2092,11 +2092,23 @@ static int method_enable_unit_files_generic(
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_read(message, "bb", &runtime, &force);
-        if (r < 0)
-                return r;
+        if (sd_bus_message_is_method_call(message, NULL, "EnableUnitFilesWithFlags")) {
+                uint64_t raw_flags;
 
-        flags = unit_file_bools_to_flags(runtime, force);
+                r = sd_bus_message_read(message, "t", &raw_flags);
+                if (r < 0)
+                        return r;
+                if ((raw_flags & ~_UNIT_FILE_FLAGS_MASK_PUBLIC) != 0)
+                        return -EINVAL;
+                flags = raw_flags;
+        } else {
+                int runtime, force;
+
+                r = sd_bus_message_read(message, "bb", &runtime, &force);
+                if (r < 0)
+                        return r;
+                flags = unit_file_bools_to_flags(runtime, force);
+        }
 
         r = bus_verify_manage_unit_files_async(m, message, error);
         if (r < 0)
@@ -2111,6 +2123,10 @@ static int method_enable_unit_files_generic(
         return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error);
 }
 
+static int method_enable_unit_files_with_flags(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error);
+}
+
 static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error);
 }
@@ -2188,8 +2204,9 @@ static int method_disable_unit_files_generic(
 
         _cleanup_strv_free_ char **l = NULL;
         UnitFileChange *changes = NULL;
+        UnitFileFlags flags;
         size_t n_changes = 0;
-        int r, runtime;
+        int r;
 
         assert(message);
         assert(m);
@@ -2198,9 +2215,24 @@ static int method_disable_unit_files_generic(
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_read(message, "b", &runtime);
-        if (r < 0)
-                return r;
+        if (sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlags")) {
+                uint64_t raw_flags;
+
+                r = sd_bus_message_read(message, "t", &raw_flags);
+                if (r < 0)
+                        return r;
+                if ((raw_flags & ~_UNIT_FILE_FLAGS_MASK_PUBLIC) != 0 ||
+                                FLAGS_SET(raw_flags, UNIT_FILE_FORCE))
+                        return -EINVAL;
+                flags = raw_flags;
+        } else {
+                int runtime;
+
+                r = sd_bus_message_read(message, "b", &runtime);
+                if (r < 0)
+                        return r;
+                flags = unit_file_bools_to_flags(runtime, false);
+        }
 
         r = bus_verify_manage_unit_files_async(m, message, error);
         if (r < 0)
@@ -2208,13 +2240,17 @@ static int method_disable_unit_files_generic(
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
-        r = call(m->unit_file_scope, runtime ? UNIT_FILE_RUNTIME : 0, NULL, l, &changes, &n_changes);
+        r = call(m->unit_file_scope, flags, NULL, l, &changes, &n_changes);
         if (r < 0)
                 return install_error(error, r, changes, n_changes);
 
         return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
 }
 
+static int method_disable_unit_files_with_flags(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
+}
+
 static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
 }
@@ -2984,6 +3020,23 @@ const sd_bus_vtable bus_manager_vtable[] = {
                                  SD_BUS_PARAM(changes),
                                  method_disable_unit_files,
                                  SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_NAMES("EnableUnitFilesWithFlags",
+                                 "ast",
+                                 SD_BUS_PARAM(files)
+                                 SD_BUS_PARAM(flags),
+                                 "ba(sss)",
+                                 SD_BUS_PARAM(carries_install_info)
+                                 SD_BUS_PARAM(changes),
+                                 method_enable_unit_files_with_flags,
+                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_NAMES("DisableUnitFilesWithFlags",
+                                 "ast",
+                                 SD_BUS_PARAM(files)
+                                 SD_BUS_PARAM(flags),
+                                 "a(sss)",
+                                 SD_BUS_PARAM(changes),
+                                 method_disable_unit_files_with_flags,
+                                 SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_NAMES("ReenableUnitFiles",
                                  "asbb",
                                  SD_BUS_PARAM(files)
index aa6369864a4e4240cdbded6083d3cb5111ee8f36..4369dfd1563b8acbff9961735741aedda65cdd87 100644 (file)
@@ -392,6 +392,7 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_strv_free_ char **names = NULL;
         UnitFileChange *changes = NULL;
+        const uint64_t flags = UNIT_FILE_PORTABLE | (arg_runtime ? UNIT_FILE_RUNTIME : 0);
         size_t n_changes = 0;
         int r;
 
@@ -408,7 +409,7 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) {
                 "org.freedesktop.systemd1",
                 "/org/freedesktop/systemd1",
                 "org.freedesktop.systemd1.Manager",
-                enable ? "EnableUnitFiles" : "DisableUnitFiles");
+                enable ? "EnableUnitFilesWithFlags" : "DisableUnitFilesWithFlags");
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -416,16 +417,10 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) {
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_message_append(m, "b", arg_runtime);
+        r = sd_bus_message_append(m, "t", flags);
         if (r < 0)
                 return bus_log_create_error(r);
 
-        if (enable) {
-                r = sd_bus_message_append(m, "b", false);
-                if (r < 0)
-                        return bus_log_create_error(r);
-        }
-
         r = sd_bus_call(bus, m, 0, &error, &reply);
         if (r < 0)
                 return log_error_errno(r, "Failed to %s the portable service %s: %s",
index 0f21cdc3f7730b838ab9eae455af563c4f2688df..cd14b2c4beb40dca02b830b503e5d1110f0609c9 100644 (file)
@@ -249,6 +249,15 @@ static int path_is_vendor_or_generator(const LookupPaths *p, const char *path) {
         return path_equal(rpath, SYSTEM_DATA_UNIT_PATH);
 }
 
+static const char* config_path_from_flags(const LookupPaths *paths, UnitFileFlags flags) {
+        assert(paths);
+
+        if (FLAGS_SET(flags, UNIT_FILE_PORTABLE))
+                return FLAGS_SET(flags, UNIT_FILE_RUNTIME) ? paths->runtime_attached : paths->persistent_attached;
+        else
+                return FLAGS_SET(flags, UNIT_FILE_RUNTIME) ? paths->runtime_config : paths->persistent_config;
+}
+
 int unit_file_changes_add(
                 UnitFileChange **changes,
                 size_t *n_changes,
@@ -2582,7 +2591,7 @@ int unit_file_enable(
         if (r < 0)
                 return r;
 
-        config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
+        config_path = config_path_from_flags(&paths, flags);
         if (!config_path)
                 return -ENXIO;
 
@@ -2625,7 +2634,7 @@ int unit_file_disable(
         if (r < 0)
                 return r;
 
-        config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
+        config_path = config_path_from_flags(&paths, flags);
         if (!config_path)
                 return -ENXIO;
 
index 788517d23e91b4f0f19b01b047d606d7691caf56..23ac9953328ff523918dba3f0c2be9e1b49dbf7f 100644 (file)
@@ -35,9 +35,11 @@ enum UnitFileChangeType {
 };
 
 enum UnitFileFlags {
-        UNIT_FILE_RUNTIME = 1 << 0,
-        UNIT_FILE_FORCE   = 1 << 1,
-        UNIT_FILE_DRY_RUN = 1 << 2,
+        UNIT_FILE_RUNTIME  = 1 << 0, /* Public API via DBUS, do not change */
+        UNIT_FILE_FORCE    = 1 << 1, /* Public API via DBUS, do not change */
+        UNIT_FILE_PORTABLE = 1 << 2, /* Public API via DBUS, do not change */
+        UNIT_FILE_DRY_RUN  = 1 << 3,
+        _UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE,
 };
 
 /* type can either one of the UnitFileChangeTypes listed above, or a negative error.