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,
<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()"/>
<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) << 0)
+#define SD_SYSTEMD_UNIT_FORCE (UINT64_C(1) << 1)
+#define SD_SYSTEMD_UNIT_PORTABLE (UINT64_C(1) << 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>
<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
UnitFileChange *changes = NULL;
size_t n_changes = 0;
UnitFileFlags flags;
- int runtime, force, r;
+ int r;
assert(message);
assert(m);
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)
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);
}
_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);
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)
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);
}
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)
_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;
"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);
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",
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,
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;
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;
};
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.