From: Ivan Kruglov Date: Thu, 15 May 2025 10:04:28 +0000 (-0700) Subject: core: add basic lookup by name/pidref in io.systemd.Unit.List X-Git-Tag: v258-rc1~479^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d2a8dbabf5e2676f436515cc821040bd24eb6003;p=thirdparty%2Fsystemd.git core: add basic lookup by name/pidref in io.systemd.Unit.List --- diff --git a/src/core/varlink-unit.c b/src/core/varlink-unit.c index f2ab708b237..23f4e65b83f 100644 --- a/src/core/varlink-unit.c +++ b/src/core/varlink-unit.c @@ -3,11 +3,13 @@ #include "sd-json.h" #include "bitfield.h" +#include "cgroup.h" #include "condition.h" #include "execute.h" #include "install.h" #include "json-util.h" #include "manager.h" +#include "pidref.h" #include "set.h" #include "strv.h" #include "unit.h" @@ -316,17 +318,85 @@ static int list_unit_one(sd_varlink *link, Unit *unit, bool more) { return sd_varlink_reply(link, v); } +static int lookup_unit_by_pidref(sd_varlink *link, Manager *manager, PidRef *pidref, Unit **ret_unit) { + _cleanup_(pidref_done) PidRef peer = PIDREF_NULL; + Unit *unit; + int r; + + assert(link); + assert(manager); + assert(ret_unit); + + if (pidref_is_automatic(pidref)) { + r = varlink_get_peer_pidref(link, &peer); + if (r < 0) + return log_debug_errno(r, "Failed to get peer pidref: %m"); + + pidref = &peer; + } else if (!pidref_is_set(pidref)) + return -EINVAL; + + unit = manager_get_unit_by_pidref(manager, pidref); + if (!unit) + return -ESRCH; + + *ret_unit = unit; + return 0; +} + +typedef struct UnitLookupParameters { + const char *name; + PidRef pidref; +} UnitLookupParameters; + +static void unit_lookup_parameters_done(UnitLookupParameters *p) { + assert(p); + pidref_done(&p->pidref); +} + int vl_method_list_units(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + static const sd_json_dispatch_field dispatch_table[] = { + { "name", SD_JSON_VARIANT_STRING, json_dispatch_const_unit_name, offsetof(UnitLookupParameters, name), 0 /* allows UNIT_NAME_PLAIN | UNIT_NAME_INSTANCE */ }, + { "pid", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_pidref, offsetof(UnitLookupParameters, pidref), SD_JSON_RELAX /* allows PID_AUTOMATIC */ }, + {} + }; + Manager *manager = ASSERT_PTR(userdata); + _cleanup_(unit_lookup_parameters_done) UnitLookupParameters p = { + .pidref = PIDREF_NULL, + }; int r; assert(link); assert(parameters); - r = sd_varlink_dispatch(link, parameters, /* dispatch_table = */ NULL, /* userdata = */ NULL); + r = sd_varlink_dispatch(link, parameters, dispatch_table, &p); if (r != 0) return r; + if (p.name) { + Unit *unit = manager_get_unit(manager, p.name); + if (!unit) + return sd_varlink_error(link, VARLINK_ERROR_UNIT_NO_SUCH_UNIT, NULL); + + return list_unit_one(link, unit, /* more = */ false); + } + + if (pidref_is_set(&p.pidref) || pidref_is_automatic(&p.pidref)) { + Unit *unit; + r = lookup_unit_by_pidref(link, manager, &p.pidref, &unit); + if (r == -EINVAL) + return sd_varlink_error_invalid_parameter_name(link, "pid"); + if (r == -ESRCH) + return sd_varlink_error(link, VARLINK_ERROR_UNIT_NO_SUCH_UNIT, NULL); + if (r < 0) + return r; + + return list_unit_one(link, unit, /* more = */ false); + } + + // TODO lookup by invocationID, CGroup + if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); diff --git a/src/core/varlink-unit.h b/src/core/varlink-unit.h index b04f322f4ae..28748f74619 100644 --- a/src/core/varlink-unit.h +++ b/src/core/varlink-unit.h @@ -3,4 +3,6 @@ #include "sd-varlink.h" +#define VARLINK_ERROR_UNIT_NO_SUCH_UNIT "io.systemd.Unit.NoSuchUnit" + int vl_method_list_units(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c index 5c134ecd5dc..291646446c9 100644 --- a/src/shared/varlink-io.systemd.Unit.c +++ b/src/shared/varlink-io.systemd.Unit.c @@ -225,6 +225,10 @@ static SD_VARLINK_DEFINE_ERROR(NoSuchUnit); static SD_VARLINK_DEFINE_METHOD_FULL( List, SD_VARLINK_SUPPORTS_MORE, + SD_VARLINK_FIELD_COMMENT("If non-null the name of a unit."), + SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("If non-null the PID of a unit. Special value 0 means to take pid of the caller."), + SD_VARLINK_DEFINE_INPUT_BY_TYPE(pid, ProcessId, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration of the unit"), SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(context, UnitContext, 0), SD_VARLINK_FIELD_COMMENT("Runtime information of the unit"), @@ -246,5 +250,7 @@ SD_VARLINK_DEFINE_INTERFACE( &vl_type_Timestamp, SD_VARLINK_SYMBOL_COMMENT("An object to represent a unit's activation details"), &vl_type_ActivationDetails, + SD_VARLINK_SYMBOL_COMMENT("An object for referencing UNIX processes"), + &vl_type_ProcessId, SD_VARLINK_SYMBOL_COMMENT("No matching unit found"), &vl_error_NoSuchUnit);