]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machine: use machine_copy_from_to() in dbus implementation
authorIvan Kruglov <mail@ikruglov.com>
Tue, 17 Dec 2024 11:53:28 +0000 (12:53 +0100)
committerIvan Kruglov <mail@ikruglov.com>
Mon, 6 Jan 2025 13:51:57 +0000 (14:51 +0100)
src/machine/machine-dbus.c

index 2ed779d117f75c2d0171cfe35ecaefd12eb4449e..2d05c52608c39a312924664b239a3145a1ba9e28 100644 (file)
@@ -492,15 +492,11 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
 }
 
 int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        _cleanup_free_ char *host_basename = NULL, *container_basename = NULL;
         const char *src, *dest, *host_path, *container_path;
-        _cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
         CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS;
-        _cleanup_close_ int hostfd = -EBADF;
         Machine *m = ASSERT_PTR(userdata);
+        Manager *manager = m->manager;
         bool copy_from;
-        pid_t child;
-        uid_t uid_shift;
         int r;
 
         assert(message);
@@ -549,17 +545,13 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
                         message,
                         "org.freedesktop.machine1.manage-machines",
                         details,
-                        &m->manager->polkit_registry,
+                        &manager->polkit_registry,
                         error);
         if (r < 0)
                 return r;
         if (r == 0)
                 return 1; /* Will call us back */
 
-        r = machine_get_uid_shift(m, &uid_shift);
-        if (r < 0)
-                return r;
-
         copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
 
         if (copy_from) {
@@ -570,83 +562,12 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
                 container_path = dest;
         }
 
-        r = path_extract_filename(host_path, &host_basename);
+        Operation *op;
+        r = machine_copy_from_to(manager, m, host_path, container_path, copy_from, copy_flags, &op);
         if (r < 0)
-                return sd_bus_error_set_errnof(error, r, "Failed to extract file name of '%s' path: %m", host_path);
-
-        r = path_extract_filename(container_path, &container_basename);
-        if (r < 0)
-                return sd_bus_error_set_errnof(error, r, "Failed to extract file name of '%s' path: %m", container_path);
-
-        hostfd = open_parent(host_path, O_CLOEXEC, 0);
-        if (hostfd < 0)
-                return sd_bus_error_set_errnof(error, hostfd, "Failed to open host directory %s: %m", host_path);
-
-        if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
-                return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
-
-        r = safe_fork("(sd-copy)", FORK_RESET_SIGNALS, &child);
-        if (r < 0)
-                return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
-        if (r == 0) {
-                int containerfd;
-                const char *q;
-                int mntfd;
-
-                errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
-
-                q = procfs_file_alloca(m->leader.pid, "ns/mnt");
-                mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
-                if (mntfd < 0) {
-                        r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
-                        goto child_fail;
-                }
-
-                if (setns(mntfd, CLONE_NEWNS) < 0) {
-                        r = log_error_errno(errno, "Failed to join namespace of leader: %m");
-                        goto child_fail;
-                }
-
-                containerfd = open_parent(container_path, O_CLOEXEC, 0);
-                if (containerfd < 0) {
-                        r = log_error_errno(containerfd, "Failed to open destination directory: %m");
-                        goto child_fail;
-                }
-
-                /* Run the actual copy operation. Note that when a UID shift is set we'll either clamp the UID/GID to
-                 * 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy
-                 * the UID/GIDs as they are. */
-                if (copy_from)
-                        r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags, NULL, NULL);
-                else
-                        r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags, NULL, NULL);
-
-                hostfd = safe_close(hostfd);
-                containerfd = safe_close(containerfd);
-
-                if (r < 0) {
-                        r = log_error_errno(r, "Failed to copy tree: %m");
-                        goto child_fail;
-                }
-
-                _exit(EXIT_SUCCESS);
-
-        child_fail:
-                (void) write(errno_pipe_fd[1], &r, sizeof(r));
-                _exit(EXIT_FAILURE);
-        }
-
-        errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
-
-        /* Copying might take a while, hence install a watch on the child, and return */
-
-        r = operation_new_with_bus_reply(m->manager, m, child, message, errno_pipe_fd[0], /* ret= */ NULL);
-        if (r < 0) {
-                (void) sigkill_wait(child);
-                return r;
-        }
-        errno_pipe_fd[0] = -EBADF;
+                return sd_bus_error_set_errnof(error, r, "Failed to copy from/to machine '%s': %m", m->name);
 
+        operation_attach_bus_reply(op, message);
         return 1;
 }