]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
portable: use send_one_fd_iov/receive_one_fd_iov instead of custom helpers
authorLuca Boccassi <luca.boccassi@microsoft.com>
Thu, 16 Sep 2021 11:43:51 +0000 (12:43 +0100)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Mon, 20 Sep 2021 13:23:55 +0000 (14:23 +0100)
Will be useful for the next commit switching to multiple IOVs

src/portable/portable.c

index 3f841b925825dee40cb828b619de79597d3e5178..8af7fe2aefb2e4cdb546e77b51657f8acc8ce588 100644 (file)
@@ -134,96 +134,23 @@ int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetad
         return 0;
 }
 
-static int send_item(
+static int send_one_fd_iov_with_data_fd(
                 int socket_fd,
-                const char *name,
+                const struct iovec *iov,
+                size_t iovlen,
                 int fd) {
 
-        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control = {};
-        struct iovec iovec;
-        struct msghdr mh = {
-                .msg_control = &control,
-                .msg_controllen = sizeof(control),
-                .msg_iov = &iovec,
-                .msg_iovlen = 1,
-        };
-        struct cmsghdr *cmsg;
         _cleanup_close_ int data_fd = -1;
 
+        assert(iov || iovlen == 0);
         assert(socket_fd >= 0);
-        assert(name);
         assert(fd >= 0);
 
         data_fd = copy_data_fd(fd);
         if (data_fd < 0)
                 return data_fd;
 
-        cmsg = CMSG_FIRSTHDR(&mh);
-        cmsg->cmsg_level = SOL_SOCKET;
-        cmsg->cmsg_type = SCM_RIGHTS;
-        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
-        memcpy(CMSG_DATA(cmsg), &data_fd, sizeof(int));
-
-        iovec = IOVEC_MAKE_STRING(name);
-
-        if (sendmsg(socket_fd, &mh, MSG_NOSIGNAL) < 0)
-                return -errno;
-
-        return 0;
-}
-
-static int recv_item(
-                int socket_fd,
-                char **ret_name,
-                int *ret_fd) {
-
-        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
-        char buffer[PATH_MAX+2];
-        struct iovec iov = IOVEC_INIT(buffer, sizeof(buffer)-1);
-        struct msghdr mh = {
-                .msg_control = &control,
-                .msg_controllen = sizeof(control),
-                .msg_iov = &iov,
-                .msg_iovlen = 1,
-        };
-        struct cmsghdr *cmsg;
-        _cleanup_close_ int found_fd = -1;
-        char *copy;
-        ssize_t n;
-
-        assert(socket_fd >= 0);
-        assert(ret_name);
-        assert(ret_fd);
-
-        n = recvmsg_safe(socket_fd, &mh, MSG_CMSG_CLOEXEC);
-        if (n < 0)
-                return (int) n;
-
-        CMSG_FOREACH(cmsg, &mh) {
-                if (cmsg->cmsg_level == SOL_SOCKET &&
-                    cmsg->cmsg_type == SCM_RIGHTS) {
-
-                        if (cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
-                                assert(found_fd < 0);
-                                found_fd = *(int*) CMSG_DATA(cmsg);
-                                break;
-                        }
-
-                        cmsg_close_all(&mh);
-                        return -EIO;
-                }
-        }
-
-        buffer[n] = 0;
-
-        copy = strdup(buffer);
-        if (!copy)
-                return -ENOMEM;
-
-        *ret_name = copy;
-        *ret_fd = TAKE_FD(found_fd);
-
-        return 0;
+        return send_one_fd_iov(socket_fd, data_fd, iov, iovlen, 0);
 }
 
 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(portable_metadata_hash_ops, char, string_hash_func, string_compare_func,
@@ -272,7 +199,11 @@ static int extract_now(
                                 path_is_extension ? "extension-release " : "os-release");
         else {
                 if (socket_fd >= 0) {
-                        r = send_item(socket_fd, os_release_id, os_release_fd);
+                        struct iovec iov[] = {
+                                IOVEC_MAKE_STRING(os_release_id),
+                        };
+
+                        r = send_one_fd_iov_with_data_fd(socket_fd, iov, ELEMENTSOF(iov), os_release_fd);
                         if (r < 0)
                                 return log_debug_errno(r, "Failed to send os-release file: %m");
                 }
@@ -333,7 +264,11 @@ static int extract_now(
                         }
 
                         if (socket_fd >= 0) {
-                                r = send_item(socket_fd, de->d_name, fd);
+                                struct iovec iov[] = {
+                                        IOVEC_MAKE_STRING(de->d_name),
+                                };
+
+                                r = send_one_fd_iov_with_data_fd(socket_fd, iov, ELEMENTSOF(iov), fd);
                                 if (r < 0)
                                         return log_debug_errno(r, "Failed to send unit metadata to parent: %m");
                         }
@@ -465,23 +400,27 @@ static int portable_extract_by_path(
 
                 for (;;) {
                         _cleanup_(portable_metadata_unrefp) PortableMetadata *add = NULL;
-                        _cleanup_free_ char *name = NULL;
                         _cleanup_close_ int fd = -1;
+                        char iov_buffer[PATH_MAX + 2];
+                        struct iovec iov = IOVEC_INIT(iov_buffer, sizeof(iov_buffer));
 
-                        r = recv_item(seq[0], &name, &fd);
-                        if (r < 0)
-                                return log_debug_errno(r, "Failed to receive item: %m");
+                        ssize_t n = receive_one_fd_iov(seq[0], &iov, 1, 0, &fd);
+                        if (n == -EIO)
+                                break;
+                        if (n < 0)
+                                return log_debug_errno(n, "Failed to receive item: %m");
+                        iov_buffer[n] = 0;
 
                         /* We can't really distinguish a zero-length datagram without any fds from EOF (both are signalled the
                          * same way by recvmsg()). Hence, accept either as end notification. */
-                        if (isempty(name) && fd < 0)
+                        if (isempty(iov_buffer) && fd < 0)
                                 break;
 
-                        if (isempty(name) || fd < 0)
+                        if (isempty(iov_buffer) || fd < 0)
                                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "Invalid item sent from child.");
 
-                        add = portable_metadata_new(name, path, fd);
+                        add = portable_metadata_new(iov_buffer, path, fd);
                         if (!add)
                                 return -ENOMEM;
                         fd = -1;