assert(u);
- r = unit_queue_job_check_and_mangle_type(u, &type, /* reload_if_possible= */ FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE));
- if (r == -ENOENT)
- return sd_bus_error_setf(reterr_error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
- if (r == -ELIBEXEC)
- return sd_bus_error_setf(reterr_error,
- BUS_ERROR_ONLY_BY_DEPENDENCY,
- "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).",
- u->id);
- if (r == -ESHUTDOWN)
- return sd_bus_error_setf(reterr_error,
- BUS_ERROR_SHUTTING_DOWN,
- "Operation for unit %s refused, D-Bus is shutting down.",
- u->id);
+ r = unit_queue_job_check_and_mangle_type(
+ u,
+ &type,
+ /* reload_if_possible= */ FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE),
+ reterr_error);
if (r < 0)
return r;
int unit_queue_job_check_and_mangle_type(
Unit *u,
JobType *type, /* input and output */
- bool reload_if_possible) {
-
- /* Returns:
- *
- * -ENOENT → Unit not loaded
- * -ELIBEXEC → Unit can only be activated via dependency, not directly
- * -ESHUTDOWN → System bus is shutting down */
+ bool reload_if_possible,
+ sd_bus_error *reterr_error) {
JobType t;
/* Our transaction logic allows units not properly loaded to be stopped. But if already dead
* let's return clear error to caller. */
if (t == JOB_STOP && UNIT_IS_LOAD_ERROR(u->load_state) && unit_active_state(u) == UNIT_INACTIVE)
- return -ENOENT;
+ return sd_bus_error_setf(reterr_error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
if ((t == JOB_START && u->refuse_manual_start) ||
(t == JOB_STOP && u->refuse_manual_stop) ||
(IN_SET(t, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
(t == JOB_RELOAD_OR_START && job_type_collapse(t, u) == JOB_START && u->refuse_manual_start))
- return -ELIBEXEC;
+ return sd_bus_error_setf(reterr_error,
+ BUS_ERROR_ONLY_BY_DEPENDENCY,
+ "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).",
+ u->id);
/* dbus-broker issues StartUnit for activation requests, and Type=dbus services automatically
* gain dependency on dbus.socket. Therefore, if dbus has a pending stop job, the new start
FOREACH_STRING(dbus_unit, SPECIAL_DBUS_SOCKET, SPECIAL_DBUS_SERVICE) {
Unit *dbus = manager_get_unit(u->manager, dbus_unit);
if (dbus && unit_stop_pending(dbus))
- return -ESHUTDOWN;
+ return sd_bus_error_setf(reterr_error,
+ BUS_ERROR_SHUTTING_DOWN,
+ "Operation for unit %s refused, D-Bus is shutting down.",
+ u->id);
}
*type = t;
DECLARE_STRING_TABLE_LOOKUP(oom_policy, OOMPolicy);
-int unit_queue_job_check_and_mangle_type(Unit *u, JobType *type, bool reload_if_possible);
+int unit_queue_job_check_and_mangle_type(Unit *u, JobType *type, bool reload_if_possible, sd_bus_error *reterr_error);
/* Macros which append UNIT= or USER_UNIT= to the message */
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "sd-bus.h"
+
+#include "bus-common-errors.h"
#include "cpu-set-util.h"
#include "json-util.h"
#include "rlimit-util.h"
#include "varlink-common.h"
+#include "varlink-unit.h"
+
+const char* varlink_error_id_from_bus_error(const sd_bus_error *e) {
+ static const struct {
+ const char *bus_error;
+ const char *varlink_error;
+ } map[] = {
+ { BUS_ERROR_NO_SUCH_UNIT, VARLINK_ERROR_UNIT_NO_SUCH_UNIT },
+ { BUS_ERROR_ONLY_BY_DEPENDENCY, VARLINK_ERROR_UNIT_ONLY_BY_DEPENDENCY },
+ { BUS_ERROR_SHUTTING_DOWN, VARLINK_ERROR_UNIT_DBUS_SHUTTING_DOWN },
+ };
+
+ if (!sd_bus_error_is_set(e))
+ return NULL;
+
+ FOREACH_ELEMENT(i, map)
+ if (sd_bus_error_has_name(e, i->bus_error))
+ return i->varlink_error;
+
+ return NULL;
+}
int rlimit_build_json(sd_json_variant **ret, const char *name, void *userdata) {
const struct rlimit *rl = userdata;
int rlimit_build_json(sd_json_variant **ret, const char *name, void *userdata);
int rlimit_table_build_json(sd_json_variant **ret, const char *name, void *userdata);
int cpuset_build_json(sd_json_variant **ret, const char *name, void *userdata);
+
+const char* varlink_error_id_from_bus_error(const sd_bus_error *e);
bool reload_if_possible,
uint32_t *ret_job_id) {
+ _cleanup_(sd_bus_error_free) sd_bus_error bus_error = SD_BUS_ERROR_NULL;
int r;
assert(u);
- r = unit_queue_job_check_and_mangle_type(u, &type, reload_if_possible);
- if (r == -ENOENT)
- return varlink_error_no_such_unit(link, "name");
- if (r == -ELIBEXEC)
- return sd_varlink_error(link, VARLINK_ERROR_UNIT_ONLY_BY_DEPENDENCY);
- if (r == -ESHUTDOWN)
- return sd_varlink_error(link, VARLINK_ERROR_UNIT_DBUS_SHUTTING_DOWN);
- if (r < 0)
+ r = unit_queue_job_check_and_mangle_type(u, &type, reload_if_possible, &bus_error);
+ if (r < 0) {
+ const char *error_id = varlink_error_id_from_bus_error(&bus_error);
+ if (error_id)
+ return sd_varlink_error(link, error_id);
+
return r;
+ }
Job *j;
r = manager_add_job(u->manager, type, u, mode, /* reterr_error= */ NULL, &j);