]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: implement PathContext/Runtime for io.systemd.Unit.List + tests
authorIvan Kruglov <mail@ikruglov.com>
Thu, 7 May 2026 10:15:15 +0000 (03:15 -0700)
committerIvan Kruglov <mail@ikruglov.com>
Mon, 11 May 2026 10:03:32 +0000 (03:03 -0700)
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>
src/core/meson.build
src/core/varlink-path.c [new file with mode: 0644]
src/core/varlink-path.h [new file with mode: 0644]
src/core/varlink-unit.c
src/shared/varlink-io.systemd.Unit.c
src/shared/varlink-io.systemd.Unit.h
src/test/test-varlink-idl-unit.c
test/units/TEST-74-AUX-UTILS.varlinkctl.sh

index d24fc3b6d37884736bc81ea25a68cd787ca93826..0dae1e50cc9debf5151b37fbee0bc2ea8575dcdc 100644 (file)
@@ -73,6 +73,7 @@ libcore_sources = files(
         'varlink-manager.c',
         'varlink-metrics.c',
         'varlink-mount.c',
+        'varlink-path.c',
         'varlink-unit.c',
 )
 
diff --git a/src/core/varlink-path.c b/src/core/varlink-path.c
new file mode 100644 (file)
index 0000000..c6ba45a
--- /dev/null
@@ -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)));
+}
diff --git a/src/core/varlink-path.h b/src/core/varlink-path.h
new file mode 100644 (file)
index 0000000..a466949
--- /dev/null
@@ -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);
index 5b1dc77aae0b42f55cf91530f86ca6623b8334ea..ca357cf899e8a7729ea15a6483e77f9bbef8ae86 100644 (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(
index be5c942fcc717d92d54600774cec7b65dc6f5794..4e8e4f04b7fa2f9a6d7606cbaa0a813a4b3ad870 100644 (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,
index f12ac60701ee65116f205a82febb755e1507b9b3..bc43d7b59fba8f6271ccf3655296987194a8a3e1 100644 (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;
index 2469859411931182c346453a56281a5c281a2af0..6c0f834a7a3606ba31e4ae991cbd5d52e0508dee 100644 (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);
index 3e6d4a9a257e640a3c9978a678ac116c090c2a19..1db22b85c118b18148a5eab05158e1c9bb998f6f 100755 (executable)
@@ -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