diff options
author | Ivan Kruglov <mail@ikruglov.com> | 2024-10-24 12:19:56 +0200 |
---|---|---|
committer | Ivan Kruglov <mail@ikruglov.com> | 2025-01-06 14:51:57 +0100 |
commit | 453f2359ffcafaafe10297319dd8f85a11a4e1c4 (patch) | |
tree | ae1cd46719b8ebb4ee522ba8e867418d1ab83615 /src/machine | |
parent | machine: use machine_copy_from_to() in dbus implementation (diff) | |
download | systemd-453f2359ffcafaafe10297319dd8f85a11a4e1c4.tar.xz systemd-453f2359ffcafaafe10297319dd8f85a11a4e1c4.zip |
machine: introduce io.system.Machine.{CopyFrom, CopyTo} methods
Diffstat (limited to 'src/machine')
-rw-r--r-- | src/machine/machine-varlink.c | 94 | ||||
-rw-r--r-- | src/machine/machine-varlink.h | 1 | ||||
-rw-r--r-- | src/machine/machined-varlink.c | 10 |
3 files changed, 105 insertions, 0 deletions
diff --git a/src/machine/machine-varlink.c b/src/machine/machine-varlink.c index 4e5362783b..e932711311 100644 --- a/src/machine/machine-varlink.c +++ b/src/machine/machine-varlink.c @@ -7,6 +7,7 @@ #include "sd-varlink.h" #include "bus-polkit.h" +#include "copy.h" #include "fd-util.h" #include "hostname-util.h" #include "json-util.h" @@ -825,3 +826,96 @@ int vl_method_bind_mount(sd_varlink *link, sd_json_variant *parameters, sd_varli return sd_varlink_reply(link, NULL); } + +typedef struct MachineCopyParameters { + const char *name; + PidRef pidref; + const char *src; + const char *dest; + bool replace; +} MachineCopyParameters; + +static void machine_copy_paramaters_done(MachineCopyParameters *p) { + assert(p); + + pidref_done(&p->pidref); +} + +static int copy_done(Operation *operation, int ret, sd_bus_error *error) { + assert(operation); + assert(operation->link); + + if (ERRNO_IS_PRIVILEGE(ret)) + return sd_varlink_error(operation->link, SD_VARLINK_ERROR_PERMISSION_DENIED, NULL); + if (ERRNO_IS_NEG_NOT_SUPPORTED(ret)) + return sd_varlink_error(operation->link, "io.systemd.Machine.NotSupported", NULL); + if (ret < 0) + return sd_varlink_error_errno(operation->link, ret); + + return sd_varlink_reply(operation->link, NULL); +} + +int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata, bool copy_from) { + static const sd_json_dispatch_field dispatch_table[] = { + VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(MachineCopyParameters), + { "source", SD_JSON_VARIANT_STRING, json_dispatch_const_path, offsetof(MachineCopyParameters, src), SD_JSON_MANDATORY }, + { "destination", SD_JSON_VARIANT_STRING, json_dispatch_const_path, offsetof(MachineCopyParameters, dest), 0 }, + { "replace", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(MachineCopyParameters, replace), 0 }, + VARLINK_DISPATCH_POLKIT_FIELD, + {} + }; + + int r; + Manager *manager = ASSERT_PTR(userdata); + _cleanup_(machine_copy_paramaters_done) MachineCopyParameters p = { + .pidref = PIDREF_NULL + }; + + assert(link); + assert(parameters); + + if (manager->n_operations >= OPERATIONS_MAX) + return sd_varlink_error(link, "io.systemd.MachineImage.TooManyOperations", NULL); + + r = sd_varlink_dispatch(link, parameters, dispatch_table, &p); + if (r != 0) + return r; + + /* There is no need for extra validation since json_dispatch_path() does path_is_valid() and path_is_absolute().*/ + const char *dest = p.dest ?: p.src; + const char *container_path = copy_from ? p.src : dest; + const char *host_path = copy_from ? dest : p.src; + CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS; + copy_flags |= p.replace ? COPY_REPLACE : 0; + + Machine *machine; + r = lookup_machine_by_name_or_pidref(link, manager, p.name, &p.pidref, &machine); + if (r == -ESRCH) + return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL); + if (r != 0) + return r; + + if (machine->class != MACHINE_CONTAINER) + return sd_varlink_error(link, "io.systemd.Machine.NotSupported", NULL); + + r = varlink_verify_polkit_async( + link, + manager->bus, + "org.freedesktop.machine1.manage-machines", + (const char**) STRV_MAKE("name", machine->name, + "verb", "copy", + "src", p.src, + "dest", dest), + &manager->polkit_registry); + if (r <= 0) + return r; + + Operation *op; + r = machine_copy_from_to(manager, machine, host_path, container_path, copy_from, copy_flags, &op); + if (r < 0) + return r; + + operation_attach_varlink_reply(op, link); + op->done = copy_done; + return 1; +} diff --git a/src/machine/machine-varlink.h b/src/machine/machine-varlink.h index 401d8f5c68..bd80cb2653 100644 --- a/src/machine/machine-varlink.h +++ b/src/machine/machine-varlink.h @@ -28,3 +28,4 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met int vl_method_map_from(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_map_to(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_bind_mount(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata, bool copy_from); diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c index 68b31cf262..e0de3aca01 100644 --- a/src/machine/machined-varlink.c +++ b/src/machine/machined-varlink.c @@ -591,6 +591,14 @@ static int vl_method_terminate(sd_varlink *link, sd_json_variant *parameters, sd return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_terminate_internal); } +static int vl_method_copy_from(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + return vl_method_copy_internal(link, parameters, flags, userdata, /* copy_from = */ true); +} + +static int vl_method_copy_to(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + return vl_method_copy_internal(link, parameters, flags, userdata, /* copy_from = */ false); +} + static int list_image_one_and_maybe_read_metadata(sd_varlink *link, Image *image, bool more, AcquireMetadata am) { int r; @@ -775,6 +783,8 @@ static int manager_varlink_init_machine(Manager *m) { "io.systemd.Machine.MapFrom", vl_method_map_from, "io.systemd.Machine.MapTo", vl_method_map_to, "io.systemd.Machine.BindMount", vl_method_bind_mount, + "io.systemd.Machine.CopyFrom", vl_method_copy_from, + "io.systemd.Machine.CopyTo", vl_method_copy_to, "io.systemd.MachineImage.List", vl_method_list_images, "io.systemd.MachineImage.Update", vl_method_update_image, "io.systemd.MachineImage.Clone", vl_method_clone_image, |