mirror of
https://github.com/systemd/systemd.git
synced 2025-02-01 09:47:35 +03:00
portable: use send_one_fd_iov/receive_one_fd_iov instead of custom helpers
Will be useful for the next commit switching to multiple IOVs
This commit is contained in:
parent
6f7ccbcc74
commit
447d46879c
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user