core: implement PathContext/Runtime for io.systemd.Unit.List + tests

Add varlink context and runtime builders for .path units:

PathContext: Paths (array of PathType enum + path specs), Unit, MakeDirectory, DirectoryMode, TriggerLimit
PathRuntime: Result (PathResult enum)

Both PathType and PathResult are exposed as proper varlink enum types.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ivan Kruglov
2026-05-11 03:03:32 -07:00
parent 20594fdd6e
commit 8787415123
8 changed files with 128 additions and 2 deletions
+1
View File
@@ -73,6 +73,7 @@ libcore_sources = files(
'varlink-manager.c',
'varlink-metrics.c',
'varlink-mount.c',
'varlink-path.c',
'varlink-unit.c',
)
+48
View File
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-json.h"
#include "json-util.h"
#include "path.h"
#include "varlink-path.h"
static int path_specs_build_json(sd_json_variant **ret, const char *name, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
PathSpec *specs = userdata;
int r;
assert(ret);
LIST_FOREACH(spec, k, specs) {
r = sd_json_variant_append_arraybo(
&v,
JSON_BUILD_PAIR_ENUM("type", path_type_to_string(k->type)),
SD_JSON_BUILD_PAIR_STRING("path", k->path));
if (r < 0)
return r;
}
*ret = TAKE_PTR(v);
return 0;
}
int path_context_build_json(sd_json_variant **ret, const char *name, void *userdata) {
Path *p = ASSERT_PTR(PATH(userdata));
Unit *trigger = UNIT_TRIGGER(UNIT(p));
return sd_json_buildo(
ASSERT_PTR(ret),
JSON_BUILD_PAIR_CALLBACK_NON_NULL("Paths", path_specs_build_json, p->specs),
JSON_BUILD_PAIR_STRING_NON_EMPTY("Unit", trigger ? trigger->id : NULL),
SD_JSON_BUILD_PAIR_BOOLEAN("MakeDirectory", p->make_directory),
SD_JSON_BUILD_PAIR_UNSIGNED("DirectoryMode", p->directory_mode),
JSON_BUILD_PAIR_RATELIMIT("TriggerLimit", &p->trigger_limit));
}
int path_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) {
Path *p = ASSERT_PTR(PATH(userdata));
return sd_json_buildo(
ASSERT_PTR(ret),
JSON_BUILD_PAIR_ENUM("Result", path_result_to_string(p->result)));
}
+7
View File
@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "core-forward.h"
int path_context_build_json(sd_json_variant **ret, const char *name, void *userdata);
int path_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata);
+3
View File
@@ -29,6 +29,7 @@
#include "varlink-execute.h"
#include "varlink-kill.h"
#include "varlink-mount.h"
#include "varlink-path.h"
#include "varlink-unit.h"
#include "varlink-util.h"
@@ -162,6 +163,7 @@ static int unit_context_build_json(sd_json_variant **ret, const char *name, void
static const sd_json_build_callback_t unit_type_callbacks[_UNIT_TYPE_MAX] = {
[UNIT_AUTOMOUNT] = automount_context_build_json,
[UNIT_MOUNT] = mount_context_build_json,
[UNIT_PATH] = path_context_build_json,
[UNIT_SERVICE] = service_context_build_json,
};
@@ -328,6 +330,7 @@ static int unit_runtime_build_json(sd_json_variant **ret, const char *name, void
static const sd_json_build_callback_t unit_type_callbacks[_UNIT_TYPE_MAX] = {
[UNIT_AUTOMOUNT] = automount_runtime_build_json,
[UNIT_MOUNT] = mount_runtime_build_json,
[UNIT_PATH] = path_runtime_build_json,
};
return sd_json_buildo(
+54 -2
View File
@@ -973,6 +973,49 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("Remount command"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExecRemount, ExecCommand, SD_VARLINK_NULLABLE));
/* PathContext
* https://www.freedesktop.org/software/systemd/man/latest/systemd.path.html */
SD_VARLINK_DEFINE_ENUM_TYPE(
PathType,
SD_VARLINK_DEFINE_ENUM_VALUE(PathExists),
SD_VARLINK_DEFINE_ENUM_VALUE(PathExistsGlob),
SD_VARLINK_DEFINE_ENUM_VALUE(DirectoryNotEmpty),
SD_VARLINK_DEFINE_ENUM_VALUE(PathChanged),
SD_VARLINK_DEFINE_ENUM_VALUE(PathModified));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
PathSpec,
SD_VARLINK_FIELD_COMMENT("Path spec type"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(type, PathType, 0),
SD_VARLINK_FIELD_COMMENT("Path"),
SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, 0));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
PathContext,
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.path.html#PathExists="),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Paths, PathSpec, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.path.html#Unit="),
SD_VARLINK_DEFINE_FIELD(Unit, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.path.html#MakeDirectory="),
SD_VARLINK_DEFINE_FIELD(MakeDirectory, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.path.html#DirectoryMode="),
SD_VARLINK_DEFINE_FIELD(DirectoryMode, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.path.html#TriggerLimitIntervalSec="),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(TriggerLimit, RateLimit, SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_ENUM_TYPE(
PathResult,
SD_VARLINK_DEFINE_ENUM_VALUE(success),
SD_VARLINK_DEFINE_ENUM_VALUE(resources),
SD_VARLINK_DEFINE_ENUM_VALUE(start_limit_hit),
SD_VARLINK_DEFINE_ENUM_VALUE(unit_start_limit_hit),
SD_VARLINK_DEFINE_ENUM_VALUE(trigger_limit_hit));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
PathRuntime,
SD_VARLINK_FIELD_COMMENT("Result of path operation"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Result, PathResult, 0));
/* Service-specific types */
/* Keep in sync with service_type_table[] in src/core/service.c */
@@ -1165,7 +1208,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("The automount context of the unit"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Automount, AutomountContext, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The mount context of the unit"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Mount, MountContext, SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Mount, MountContext, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The path context of the unit"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Path, PathContext, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
ActivationDetails,
@@ -1339,7 +1384,9 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("The automount runtime of the unit"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Automount, AutomountRuntime, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The mount runtime of the unit"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Mount, MountRuntime, SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Mount, MountRuntime, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The path runtime of the unit"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(Path, PathRuntime, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_METHOD_FULL(
List,
@@ -1501,6 +1548,11 @@ SD_VARLINK_DEFINE_INTERFACE(
&vl_type_MountContext,
&vl_type_MountResult,
&vl_type_MountRuntime,
&vl_type_PathType,
&vl_type_PathSpec,
&vl_type_PathContext,
&vl_type_PathResult,
&vl_type_PathRuntime,
/* UnitContext enums */
&vl_type_CollectMode,
+2
View File
@@ -30,6 +30,8 @@ extern const sd_varlink_symbol vl_type_MountPropagationFlag;
extern const sd_varlink_symbol vl_type_KillMode;
extern const sd_varlink_symbol vl_type_AutomountResult;
extern const sd_varlink_symbol vl_type_MountResult;
extern const sd_varlink_symbol vl_type_PathType;
extern const sd_varlink_symbol vl_type_PathResult;
extern const sd_varlink_symbol vl_type_CollectMode;
extern const sd_varlink_symbol vl_type_JobMode;
extern const sd_varlink_symbol vl_type_ServiceType;
+7
View File
@@ -6,6 +6,7 @@
#include "kill.h"
#include "mount.h"
#include "numa-util.h"
#include "path.h"
#include "process-util.h"
#include "service.h"
#include "tests.h"
@@ -63,6 +64,12 @@ TEST(unit_enums_idl) {
/* ServiceContext enums */
TEST_IDL_ENUM(ServiceType, service_type, vl_type_ServiceType);
/* PathContext enums */
TEST_IDL_ENUM(PathType, path_type, vl_type_PathType);
/* PathRuntime enums */
TEST_IDL_ENUM(PathResult, path_result, vl_type_PathResult);
/* UnitContext enums */
TEST_IDL_ENUM(CollectMode, collect_mode, vl_type_CollectMode);
TEST_IDL_ENUM(EmergencyAction, emergency_action, vl_type_EmergencyAction);
@@ -246,6 +246,12 @@ test -n "$mount_id"
mount_params=$(jq -cn --arg name "$mount_id" '{name: $name}')
varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$mount_params" | jq -e '.context.Mount'
varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$mount_params" | jq -e '.runtime.Mount'
# test for PathContext/Runtime
path_id=$(varlinkctl call --collect /run/systemd/io.systemd.Manager io.systemd.Unit.List '{}' | jq -r '.[] | select(.context.Type == "path" and .runtime.LoadState == "loaded") .context.ID' | grep -v null | tail -n 1)
test -n "$path_id"
path_params=$(jq -cn --arg name "$path_id" '{name: $name}')
varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$path_params" | jq -e '.context.Path'
varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "$path_params" | jq -e '.runtime.Path'
# test io.systemd.Metrics
varlinkctl info /run/systemd/report/io.systemd.Manager