]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/dbus-manager.c
tree-wide: use -EBADF for fd initialization
[thirdparty/systemd.git] / src / core / dbus-manager.c
index 473c0bc5abbc8ac68c4b35949a9948c5481a970e..9e529d6375ca7cae3d8c20dc7e4732ca8eca39ea 100644 (file)
@@ -694,31 +694,31 @@ static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobTyp
 }
 
 static int method_start_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_start_unit_generic(message, userdata, JOB_START, false, error);
+        return method_start_unit_generic(message, userdata, JOB_START, /* reload_if_possible = */ false, error);
 }
 
 static int method_stop_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_start_unit_generic(message, userdata, JOB_STOP, false, error);
+        return method_start_unit_generic(message, userdata, JOB_STOP, /* reload_if_possible = */ false, error);
 }
 
 static int method_reload_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_start_unit_generic(message, userdata, JOB_RELOAD, false, error);
+        return method_start_unit_generic(message, userdata, JOB_RELOAD, /* reload_if_possible = */ false, error);
 }
 
 static int method_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_start_unit_generic(message, userdata, JOB_RESTART, false, error);
+        return method_start_unit_generic(message, userdata, JOB_RESTART, /* reload_if_possible = */ false, error);
 }
 
 static int method_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, false, error);
+        return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, /* reload_if_possible = */ false, error);
 }
 
 static int method_reload_or_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_start_unit_generic(message, userdata, JOB_RESTART, true, error);
+        return method_start_unit_generic(message, userdata, JOB_RESTART, /* reload_if_possible = */ true, error);
 }
 
 static int method_reload_or_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, true, error);
+        return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, /* reload_if_possible = */ true, error);
 }
 
 typedef enum GenericUnitOperationFlags {
@@ -786,7 +786,7 @@ static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd
         if (!u->job || u->job->type != JOB_START)
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
 
-        return method_start_unit_generic(message, m, JOB_START, false, error);
+        return method_start_unit_generic(message, m, JOB_START, /* reload_if_possible = */ false, error);
 }
 
 static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -957,7 +957,7 @@ static int transient_unit_from_message(
 
         if (!unit_is_pristine(u))
                 return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS,
-                                         "Unit %s already exists.", name);
+                                         "Unit %s was already loaded or has a fragment file.", name);
 
         /* OK, the unit failed to load and is unreferenced, now let's
          * fill in the transient data instead */
@@ -1344,7 +1344,13 @@ static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_er
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) {
+static int dump_impl(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error,
+                char **patterns,
+                int (*reply)(sd_bus_message *, char *)) {
+
         _cleanup_free_ char *dump = NULL;
         Manager *m = ASSERT_PTR(userdata);
         int r;
@@ -1357,7 +1363,7 @@ static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *erro
         if (r < 0)
                 return r;
 
-        r = manager_get_dump_string(m, &dump);
+        r = manager_get_dump_string(m, patterns, &dump);
         if (r < 0)
                 return r;
 
@@ -1369,11 +1375,11 @@ static int reply_dump(sd_bus_message *message, char *dump) {
 }
 
 static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return dump_impl(message, userdata, error, reply_dump);
+        return dump_impl(message, userdata, error, NULL, reply_dump);
 }
 
 static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = acquire_data_fd(dump, strlen(dump), 0);
         if (fd < 0)
@@ -1383,7 +1389,30 @@ static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
 }
 
 static int method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return dump_impl(message, userdata, error, reply_dump_by_fd);
+        return dump_impl(message, userdata, error, NULL, reply_dump_by_fd);
+}
+
+static int dump_units_matching_patterns(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error,
+                int (*reply)(sd_bus_message *, char *)) {
+        _cleanup_strv_free_ char **patterns = NULL;
+        int r;
+
+        r = sd_bus_message_read_strv(message, &patterns);
+        if (r < 0)
+                return r;
+
+        return dump_impl(message, userdata, error, patterns, reply);
+}
+
+static int method_dump_units_matching_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return dump_units_matching_patterns(message, userdata, error, reply_dump);
+}
+
+static int method_dump_units_matching_patterns_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return dump_units_matching_patterns(message, userdata, error, reply_dump_by_fd);
 }
 
 static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -1422,6 +1451,30 @@ int verify_run_space_and_log(const char *message) {
         return 0;
 }
 
+static void log_caller(sd_bus_message *message, Manager *manager, const char *method) {
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+        const char *comm = NULL;
+        Unit *caller;
+        pid_t pid;
+
+        assert(message);
+        assert(manager);
+        assert(method);
+
+        if (sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID|SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_COMM, &creds) < 0)
+                return;
+
+        /* We need at least the PID, otherwise there's nothing to log, the rest is optional */
+        if (sd_bus_creds_get_pid(creds, &pid) < 0)
+                return;
+
+        (void) sd_bus_creds_get_comm(creds, &comm);
+        caller = manager_get_unit_by_pid(manager, pid);
+
+        log_info("%s requested from client PID " PID_FMT " ('%s') (from unit '%s')...",
+                 method, pid, strna(comm), strna(caller ? caller->id : NULL));
+}
+
 static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = ASSERT_PTR(userdata);
         int r;
@@ -1442,6 +1495,17 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
+        /* Write a log message noting the unit or process who requested the Reload() */
+        log_caller(message, m, "Reloading");
+
+        /* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */
+        if (!ratelimit_below(&m->reload_ratelimit)) {
+                log_warning("Reloading request rejected due to rate limit.");
+                return sd_bus_error_setf(error,
+                                         SD_BUS_ERROR_LIMITS_EXCEEDED,
+                                         "Reload() request rejected due to rate limit.");
+        }
+
         /* Instead of sending the reply back right away, we just
          * remember that we need to and then send it after the reload
          * is finished. That way the caller knows when the reload
@@ -1477,6 +1541,9 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
+        /* Write a log message noting the unit or process who requested the Reexecute() */
+        log_caller(message, m, "Reexecuting");
+
         /* We don't send a reply back here, the client should
          * just wait for us disconnecting. */
 
@@ -2104,23 +2171,22 @@ static int send_unit_files_changed(sd_bus *bus, void *userdata) {
 /* Create an error reply, using the error information from changes[]
  * if possible, and fall back to generating an error from error code c.
  * The error message only describes the first error.
- *
- * Coordinate with unit_file_dump_changes() in install.c.
  */
 static int install_error(
                 sd_bus_error *error,
                 int c,
-                UnitFileChange *changes,
+                InstallChange *changes,
                 size_t n_changes) {
 
         int r;
 
         for (size_t i = 0; i < n_changes; i++)
 
-                switch (changes[i].type_or_errno) {
+                /* When making changes here, make sure to also change install_changes_dump() in install.c. */
 
-                case 0 ... _UNIT_FILE_CHANGE_TYPE_MAX: /* not errors */
-                        continue;
+                switch (changes[i].type) {
+                case 0 ... _INSTALL_CHANGE_TYPE_MAX: /* not errors */
+                        break;
 
                 case -EEXIST:
                         if (changes[i].source)
@@ -2143,6 +2209,21 @@ static int install_error(
                                               "Unit %s is transient or generated.", changes[i].path);
                         goto found;
 
+                case -ETXTBSY:
+                        r = sd_bus_error_setf(error, BUS_ERROR_UNIT_BAD_PATH,
+                                              "File %s is under the systemd unit hierarchy already.", changes[i].path);
+                        goto found;
+
+                case -EBADSLT:
+                        r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
+                                              "Invalid specifier in %s.", changes[i].path);
+                        goto found;
+
+                case -EIDRM:
+                        r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
+                                              "Destination unit %s is a non-template unit.", changes[i].path);
+                        goto found;
+
                 case -EUCLEAN:
                         r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
                                               "\"%s\" is not a valid unit name.",
@@ -2155,29 +2236,44 @@ static int install_error(
                                               changes[i].path);
                         goto found;
 
+                case -EXDEV:
+                        if (changes[i].source)
+                                r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
+                                                      "Cannot alias %s as %s.",
+                                                      changes[i].source, changes[i].path);
+                        else
+                                r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
+                                                      "Invalid unit reference %s.", changes[i].path);
+                        goto found;
+
                 case -ENOENT:
                         r = sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT,
                                               "Unit file %s does not exist.", changes[i].path);
                         goto found;
 
+                case -EUNATCH:
+                        r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING,
+                                              "Cannot resolve specifiers in %s.", changes[i].path);
+                        goto found;
+
                 default:
-                        assert(changes[i].type_or_errno < 0); /* other errors */
-                        r = sd_bus_error_set_errnof(error, changes[i].type_or_errno, "File %s: %m", changes[i].path);
+                        assert(changes[i].type < 0); /* other errors */
+                        r = sd_bus_error_set_errnof(error, changes[i].type, "File %s: %m", changes[i].path);
                         goto found;
                 }
 
         r = c < 0 ? c : -EINVAL;
 
  found:
-        unit_file_changes_free(changes, n_changes);
+        install_changes_free(changes, n_changes);
         return r;
 }
 
-static int reply_unit_file_changes_and_free(
+static int reply_install_changes_and_free(
                 Manager *m,
                 sd_bus_message *message,
                 int carries_install_info,
-                UnitFileChange *changes,
+                InstallChange *changes,
                 size_t n_changes,
                 sd_bus_error *error) {
 
@@ -2185,7 +2281,7 @@ static int reply_unit_file_changes_and_free(
         bool bad = false, good = false;
         int r;
 
-        if (unit_file_changes_have_modification(changes, n_changes)) {
+        if (install_changes_have_modification(changes, n_changes)) {
                 r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
                 if (r < 0)
                         log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
@@ -2207,14 +2303,14 @@ static int reply_unit_file_changes_and_free(
 
         for (size_t i = 0; i < n_changes; i++) {
 
-                if (changes[i].type_or_errno < 0) {
+                if (changes[i].type < 0) {
                         bad = true;
                         continue;
                 }
 
                 r = sd_bus_message_append(
                                 reply, "(sss)",
-                                unit_file_change_type_to_string(changes[i].type_or_errno),
+                                install_change_type_to_string(changes[i].type),
                                 changes[i].path,
                                 changes[i].source);
                 if (r < 0)
@@ -2232,23 +2328,23 @@ static int reply_unit_file_changes_and_free(
         if (r < 0)
                 goto fail;
 
-        unit_file_changes_free(changes, n_changes);
+        install_changes_free(changes, n_changes);
         return sd_bus_send(NULL, reply, NULL);
 
 fail:
-        unit_file_changes_free(changes, n_changes);
+        install_changes_free(changes, n_changes);
         return r;
 }
 
 static int method_enable_unit_files_generic(
                 sd_bus_message *message,
                 Manager *m,
-                int (*call)(LookupScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes),
+                int (*call)(LookupScope scope, UnitFileFlags flags, const char *root_dir, char *files[], InstallChange **changes, size_t *n_changes),
                 bool carries_install_info,
                 sd_bus_error *error) {
 
         _cleanup_strv_free_ char **l = NULL;
-        UnitFileChange *changes = NULL;
+        InstallChange *changes = NULL;
         size_t n_changes = 0;
         UnitFileFlags flags;
         int r;
@@ -2288,41 +2384,41 @@ static int method_enable_unit_files_generic(
         if (r < 0)
                 return install_error(error, r, changes, n_changes);
 
-        return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error);
+        return reply_install_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);
+        return method_enable_unit_files_generic(message, userdata, unit_file_enable, /* carries_install_info = */ 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);
+        return method_enable_unit_files_generic(message, userdata, unit_file_enable, /* carries_install_info = */ true, error);
 }
 
 static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_enable_unit_files_generic(message, userdata, unit_file_reenable, true, error);
+        return method_enable_unit_files_generic(message, userdata, unit_file_reenable, /* carries_install_info = */ true, error);
 }
 
 static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_enable_unit_files_generic(message, userdata, unit_file_link, false, error);
+        return method_enable_unit_files_generic(message, userdata, unit_file_link, /* carries_install_info = */ false, error);
 }
 
-static int unit_file_preset_without_mode(LookupScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, size_t *n_changes) {
+static int unit_file_preset_without_mode(LookupScope scope, UnitFileFlags flags, const char *root_dir, char **files, InstallChange **changes, size_t *n_changes) {
         return unit_file_preset(scope, flags, root_dir, files, UNIT_FILE_PRESET_FULL, changes, n_changes);
 }
 
 static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_enable_unit_files_generic(message, userdata, unit_file_preset_without_mode, true, error);
+        return method_enable_unit_files_generic(message, userdata, unit_file_preset_without_mode, /* carries_install_info = */ true, error);
 }
 
 static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_enable_unit_files_generic(message, userdata, unit_file_mask, false, error);
+        return method_enable_unit_files_generic(message, userdata, unit_file_mask, /* carries_install_info = */ false, error);
 }
 
 static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) {
 
         _cleanup_strv_free_ char **l = NULL;
-        UnitFileChange *changes = NULL;
+        InstallChange *changes = NULL;
         size_t n_changes = 0;
         Manager *m = ASSERT_PTR(userdata);
         UnitFilePresetMode preset_mode;
@@ -2360,17 +2456,18 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use
         if (r < 0)
                 return install_error(error, r, changes, n_changes);
 
-        return reply_unit_file_changes_and_free(m, message, r, changes, n_changes, error);
+        return reply_install_changes_and_free(m, message, r, changes, n_changes, error);
 }
 
 static int method_disable_unit_files_generic(
                 sd_bus_message *message,
                 Manager *m,
-                int (*call)(LookupScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes),
+                int (*call)(LookupScope scope, UnitFileFlags flags, const char *root_dir, char *files[], InstallChange **changes, size_t *n_changes),
+                bool carries_install_info,
                 sd_bus_error *error) {
 
         _cleanup_strv_free_ char **l = NULL;
-        UnitFileChange *changes = NULL;
+        InstallChange *changes = NULL;
         UnitFileFlags flags;
         size_t n_changes = 0;
         int r;
@@ -2382,7 +2479,8 @@ static int method_disable_unit_files_generic(
         if (r < 0)
                 return r;
 
-        if (sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlags")) {
+        if (sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlags") ||
+            sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlagsAndInstallInfo")) {
                 uint64_t raw_flags;
 
                 r = sd_bus_message_read(message, "t", &raw_flags);
@@ -2411,24 +2509,28 @@ static int method_disable_unit_files_generic(
         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);
+        return reply_install_changes_and_free(m, message, carries_install_info ? r : -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);
+        return method_disable_unit_files_generic(message, userdata, unit_file_disable, /* carries_install_info = */ false, error);
+}
+
+static int method_disable_unit_files_with_flags_and_install_info(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return method_disable_unit_files_generic(message, userdata, unit_file_disable, /* carries_install_info = */ true, 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);
+        return method_disable_unit_files_generic(message, userdata, unit_file_disable, /* carries_install_info = */ false, error);
 }
 
 static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_disable_unit_files_generic(message, userdata, unit_file_unmask, error);
+        return method_disable_unit_files_generic(message, userdata, unit_file_unmask, /* carries_install_info = */ false, error);
 }
 
 static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_strv_free_ char **l = NULL;
-        UnitFileChange *changes = NULL;
+        InstallChange *changes = NULL;
         size_t n_changes = 0;
         Manager *m = ASSERT_PTR(userdata);
         int r;
@@ -2449,11 +2551,11 @@ static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_
         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);
+        return reply_install_changes_and_free(m, message, -1, changes, n_changes, error);
 }
 
 static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        UnitFileChange *changes = NULL;
+        InstallChange *changes = NULL;
         size_t n_changes = 0;
         Manager *m = ASSERT_PTR(userdata);
         const char *name;
@@ -2479,11 +2581,11 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd
         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);
+        return reply_install_changes_and_free(m, message, -1, changes, n_changes, error);
 }
 
 static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        UnitFileChange *changes = NULL;
+        InstallChange *changes = NULL;
         size_t n_changes = 0;
         Manager *m = ASSERT_PTR(userdata);
         UnitFilePresetMode preset_mode;
@@ -2521,13 +2623,13 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata,
         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);
+        return reply_install_changes_and_free(m, message, -1, changes, n_changes, error);
 }
 
 static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_strv_free_ char **l = NULL;
         Manager *m = ASSERT_PTR(userdata);
-        UnitFileChange *changes = NULL;
+        InstallChange *changes = NULL;
         size_t n_changes = 0;
         int runtime, force, r;
         char *target, *type;
@@ -2560,16 +2662,15 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd
         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);
+        return reply_install_changes_and_free(m, message, -1, changes, n_changes, error);
 }
 
 static int method_get_unit_file_links(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        UnitFileChange *changes = NULL;
+        Manager *m = ASSERT_PTR(userdata);
+        InstallChange *changes = NULL;
         size_t n_changes = 0, i;
-        UnitFileFlags flags;
         const char *name;
-        char **p;
         int runtime, r;
 
         r = sd_bus_message_read(message, "sb", &name, &runtime);
@@ -2584,26 +2685,30 @@ static int method_get_unit_file_links(sd_bus_message *message, void *userdata, s
         if (r < 0)
                 return r;
 
-        p = STRV_MAKE(name);
-        flags = UNIT_FILE_DRY_RUN |
-                (runtime ? UNIT_FILE_RUNTIME : 0);
-
-        r = unit_file_disable(LOOKUP_SCOPE_SYSTEM, flags, NULL, p, &changes, &n_changes);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get file links for %s: %m", name);
+        r = unit_file_disable(m->unit_file_scope,
+                              UNIT_FILE_DRY_RUN | (runtime ? UNIT_FILE_RUNTIME : 0),
+                              NULL, STRV_MAKE(name), &changes, &n_changes);
+        if (r < 0) {
+                log_error_errno(r, "Failed to get file links for %s: %m", name);
+                goto finish;
+        }
 
         for (i = 0; i < n_changes; i++)
-                if (changes[i].type_or_errno == UNIT_FILE_UNLINK) {
+                if (changes[i].type == INSTALL_CHANGE_UNLINK) {
                         r = sd_bus_message_append(reply, "s", changes[i].path);
                         if (r < 0)
-                                return r;
+                                goto finish;
                 }
 
         r = sd_bus_message_close_container(reply);
         if (r < 0)
-                return r;
+                goto finish;
 
-        return sd_bus_send(NULL, reply, NULL);
+        r = sd_bus_send(NULL, reply, NULL);
+
+finish:
+        install_changes_free(changes, n_changes);
+        return r;
 }
 
 static int method_get_job_waiting(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -3010,11 +3115,21 @@ const sd_bus_vtable bus_manager_vtable[] = {
                                 SD_BUS_RESULT("s", output),
                                 method_dump,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DumpUnitsMatchingPatterns",
+                                SD_BUS_ARGS("as", patterns),
+                                SD_BUS_RESULT("s", output),
+                                method_dump_units_matching_patterns,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("DumpByFileDescriptor",
                                 SD_BUS_NO_ARGS,
                                 SD_BUS_RESULT("h", fd),
                                 method_dump_by_fd,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DumpUnitsMatchingPatternsByFileDescriptor",
+                                SD_BUS_ARGS("as", patterns),
+                                SD_BUS_RESULT("h", fd),
+                                method_dump_units_matching_patterns_by_fd,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("CreateSnapshot",
                                 SD_BUS_ARGS("s", name, "b", cleanup),
                                 SD_BUS_RESULT("o", unit),
@@ -3120,6 +3235,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
                                 SD_BUS_RESULT("a(sss)", changes),
                                 method_disable_unit_files_with_flags,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DisableUnitFilesWithFlagsAndInstallInfo",
+                                SD_BUS_ARGS("as", files, "t", flags),
+                                SD_BUS_RESULT("b", carries_install_info, "a(sss)", changes),
+                                method_disable_unit_files_with_flags_and_install_info,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("ReenableUnitFiles",
                                 SD_BUS_ARGS("as", files, "b", runtime, "b", force),
                                 SD_BUS_RESULT("b", carries_install_info, "a(sss)", changes),