]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machine: io.systemd.Machine.List supports 'pid' filter
authorIvan Kruglov <mail@ikruglov.com>
Mon, 7 Oct 2024 09:22:11 +0000 (11:22 +0200)
committerIvan Kruglov <mail@ikruglov.com>
Mon, 7 Oct 2024 12:45:48 +0000 (14:45 +0200)
src/machine/machine-varlink.c
src/machine/machine-varlink.h
src/machine/machined-varlink.c
src/shared/varlink-io.systemd.Machine.c

index fb64bde9205213a02cea4b39fb323c9b4b89d6c1..37bcf266f790138a526dba17a27dd35c024fb33d 100644 (file)
@@ -188,3 +188,90 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
 
         return sd_varlink_reply(link, NULL);
 }
+
+static int lookup_machine_by_name(sd_varlink *link, Manager *manager, const char *machine_name, Machine **ret_machine) {
+        assert(link);
+        assert(manager);
+        assert(ret_machine);
+
+        if (!machine_name)
+                return -EINVAL;
+
+        if (!hostname_is_valid(machine_name, /* flags= */ VALID_HOSTNAME_DOT_HOST))
+                return -EINVAL;
+
+        Machine *machine = hashmap_get(manager->machines, machine_name);
+        if (!machine)
+                return -ESRCH;
+
+        *ret_machine = machine;
+        return 0;
+}
+
+static int lookup_machine_by_pid(sd_varlink *link, Manager *manager, pid_t pid, Machine **ret_machine) {
+        Machine *machine;
+        int r;
+
+        assert(link);
+        assert(manager);
+        assert(ret_machine);
+        assert_cc(sizeof(pid_t) == sizeof(uint32_t));
+
+        if (pid == 0) {
+                int pidfd = sd_varlink_get_peer_pidfd(link);
+                if (pidfd < 0)
+                        return log_debug_errno(pidfd, "Failed to get peer pidfd: %m");
+
+                r = pidfd_get_pid(pidfd, &pid);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to get pid from pidfd: %m");
+        }
+
+        if (pid <= 0)
+                return -EINVAL;
+
+        r = manager_get_machine_by_pid(manager, pid, &machine);
+        if (r < 0)
+                return r;
+        if (!machine)
+                return -ESRCH;
+
+        *ret_machine = machine;
+        return 0;
+}
+
+int lookup_machine_by_name_or_pid(sd_varlink *link, Manager *manager, const char *machine_name, pid_t pid, Machine **ret_machine) {
+        Machine *machine = NULL, *pid_machine = NULL;
+        int r;
+
+        assert(link);
+        assert(manager);
+        assert(ret_machine);
+
+        if (machine_name) {
+                r = lookup_machine_by_name(link, manager, machine_name, &machine);
+                if (r == -EINVAL)
+                        return sd_varlink_error_invalid_parameter_name(link, "name");
+                if (r < 0)
+                        return r;
+        }
+
+        if (pid >= 0) {
+                r = lookup_machine_by_pid(link, manager, pid, &pid_machine);
+                if (r == -EINVAL)
+                        return sd_varlink_error_invalid_parameter_name(link, "pid");
+                if (r < 0)
+                        return r;
+        }
+
+        if (machine && pid_machine && machine != pid_machine)
+                return log_debug_errno(SYNTHETIC_ERRNO(ESRCH), "Search by machine name '%s' and pid %d resulted in two different machines", machine_name, pid);
+        else if (machine)
+                *ret_machine = machine;
+        else if (pid_machine)
+                *ret_machine = pid_machine;
+        else
+                return -ESRCH;
+
+        return 0;
+}
index 3b5eb2c8f72b6a8171c50df23fe130dc5c3c8769..4ec68d526035eefabf0c2a67bc373fdee165e59f 100644 (file)
@@ -3,4 +3,20 @@
 
 #include "sd-varlink.h"
 
+#include "machine.h"
+
+#define VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(t) {         \
+                .name = "name",                             \
+                .type = SD_JSON_VARIANT_STRING,             \
+                .callback = sd_json_dispatch_const_string,  \
+                .offset = offsetof(t, machine_name)         \
+        }, {                                                \
+                .name = "pid",                              \
+                .type = _SD_JSON_VARIANT_TYPE_INVALID,      \
+                .callback = sd_json_dispatch_uint32,        \
+                .offset = offsetof(t, pid)                  \
+        }
+
+int lookup_machine_by_name_or_pid(sd_varlink *link, Manager *manager, const char *machine_name, pid_t pid, Machine **ret_machine);
+
 int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
index 942b0a96b3ea060ffe2a806d8d36e5a68cd7c4cf..4189ff2cf24aefd09645fd1911f79ddc94cba199 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "sd-varlink.h"
 
+#include "bus-polkit.h"
 #include "format-util.h"
 #include "hostname-util.h"
 #include "json-util.h"
@@ -415,29 +416,36 @@ static int list_machine_one(sd_varlink *link, Machine *m, bool more) {
         return sd_varlink_reply(link, v);
 }
 
+typedef struct MachineLookupParameters {
+        const char *machine_name;
+        pid_t pid;
+} MachineLookupParameters;
+
 static int vl_method_list(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, sd_json_dispatch_const_string, 0, 0 },
+                VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(MachineLookupParameters),
+                VARLINK_DISPATCH_POLKIT_FIELD,
                 {}
         };
 
         Manager *m = ASSERT_PTR(userdata);
-        const char *mn = NULL;
+        MachineLookupParameters p = { .pid = -1 };
+        Machine *machine;
         int r;
 
+        assert(link);
         assert(parameters);
 
-        r = sd_varlink_dispatch(link, parameters, dispatch_table, &mn);
+        r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
         if (r != 0)
                 return r;
 
-        if (mn) {
-                if (!hostname_is_valid(mn, /* flags= */ VALID_HOSTNAME_DOT_HOST))
-                        return sd_varlink_error_invalid_parameter_name(link, "name");
-
-                Machine *machine = hashmap_get(m->machines, mn);
-                if (!machine)
+        if (p.machine_name || p.pid >= 0) {
+                r = lookup_machine_by_name_or_pid(link, m, p.machine_name, p.pid, &machine);
+                if (r == -ESRCH)
                         return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
+                if (r < 0)
+                        return r;
 
                 return list_machine_one(link, machine, /* more= */ false);
         }
index 5841bf02ced7b8fb8eb5d799fa5feb4bddb6b78b..334e4c7d9387eff451440dc171a9da0b744542b0 100644 (file)
@@ -31,8 +31,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
 static SD_VARLINK_DEFINE_METHOD_FULL(
                 List,
                 SD_VARLINK_SUPPORTS_MORE,
-                SD_VARLINK_FIELD_COMMENT("If non-null the name of a running machine to report details on. If null/unspecified enumerates all running machines."),
+                SD_VARLINK_FIELD_COMMENT("If non-null the name of a running machine to report details on. If both 'name' and 'pid' are null/unspecified enumerates all running machines."),
                 SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("If non-null the PID of a running machine to report details on."),
+                SD_VARLINK_DEFINE_INPUT(pid, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
                 SD_VARLINK_FIELD_COMMENT("Name of the machine"),
                 SD_VARLINK_DEFINE_OUTPUT(name, SD_VARLINK_STRING, 0),
                 SD_VARLINK_FIELD_COMMENT("128bit ID identifying this machine, formatted in hexadecimal"),