diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 1093458e89..998caccc80 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -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 { + + + + @@ -1292,6 +1303,20 @@ node /org/freedesktop/systemd1 { Similarly, DisableUnitFiles() disables one or more units in the system, i.e. removes all symlinks to them in /etc and /run. + The EnableUnitFilesWithFlags() and DisableUnitFilesWithFlags() + take in options as flags instead of booleans to allow for extendability, defined as follows: + + +#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) + + + SD_SYSTEMD_UNIT_RUNTIME will enable or disable the unit for runtime only, + SD_SYSTEMD_UNIT_FORCE controls whether symlinks pointing to other units shall be + replaced if necessary. SD_SYSTEMD_UNIT_PORTABLE will add or remove the symlinks in + /etc/systemd/system.attached and /run/systemd/system.attached. + Similarly, ReenableUnitFiles() 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. @@ -1480,6 +1505,7 @@ node /org/freedesktop/systemd1 { RestartUnit() and similar, SetProperty()) require org.freedesktop.systemd1.manage-units. Operations which modify unit file enablement state (EnableUnitFiles(), DisableUnitFiles(), + EnableUnitFilesWithFlags(), DisableUnitFilesWithFlags(), ReenableUnitFiles(), LinkUnitFiles(), PresetUnitFiles, MaskUnitFiles, and similar) require org.freedesktop.systemd1.manage-unit-files. Operations which modify the diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 07e139c5ad..16945d09c4 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -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) diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c index aa6369864a..4369dfd156 100644 --- a/src/portable/portablectl.c +++ b/src/portable/portablectl.c @@ -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", diff --git a/src/shared/install.c b/src/shared/install.c index 0f21cdc3f7..cd14b2c4be 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -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; diff --git a/src/shared/install.h b/src/shared/install.h index 788517d23e..23ac995332 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -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.