From cd43dadecd21124ff38f6868e9f77dd13e8f816b Mon Sep 17 00:00:00 2001 From: no92 Date: Fri, 15 Nov 2024 21:23:31 +0100 Subject: [PATCH] sysdeps/managarm: implement writev --- sysdeps/managarm/generic/file.cpp | 61 ++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/sysdeps/managarm/generic/file.cpp b/sysdeps/managarm/generic/file.cpp index e920f9c99a..bc5db68285 100644 --- a/sysdeps/managarm/generic/file.cpp +++ b/sysdeps/managarm/generic/file.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -847,7 +848,7 @@ int sys_socketpair(int domain, int type_and_flags, int proto, int *fds) { } int sys_msg_send(int sockfd, const struct msghdr *hdr, int flags, ssize_t *length) { - frg::vector sglist{getSysdepsAllocator()}; + frg::small_vector sglist{getSysdepsAllocator()}; auto handle = getHandleForFd(sockfd); if (!handle) return EBADF; @@ -1743,6 +1744,64 @@ int sys_write(int fd, const void *data, size_t size, ssize_t *bytes_written) { } } +int sys_writev(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_written) { + frg::small_vector sglist{getSysdepsAllocator()}; + + size_t overall_size = 0; + for(int i = 0; i < iovc; i++) { + HelSgItem item{ + .buffer = iovs[i].iov_base, + .length = iovs[i].iov_len, + }; + sglist.push_back(item); + overall_size += iovs[i].iov_len; + } + + SignalGuard sguard; + + auto handle = getHandleForFd(fd); + if (!handle) + return EBADF; + + managarm::fs::CntRequest req(getSysdepsAllocator()); + req.set_req_type(managarm::fs::CntReqType::WRITE); + req.set_fd(fd); + req.set_size(overall_size); + + auto [offer, send_req, imbue_creds, send_data, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::imbueCredentials(), + helix_ng::sendBufferSg(sglist.data(), iovc), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(imbue_creds.error()); + HEL_CHECK(send_data.error()); + HEL_CHECK(recv_resp.error()); + + managarm::fs::SvrResponse resp(getSysdepsAllocator()); + resp.ParseFromArray(recv_resp.data(), recv_resp.length()); + + if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { + return EINVAL; // FD does not support writes. + }else if(resp.error() == managarm::fs::Errors::NO_SPACE_LEFT) { + return ENOSPC; + }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { + return EAGAIN; + }else if(resp.error() == managarm::fs::Errors::NOT_CONNECTED) { + return ENOTCONN; + }else{ + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + if(bytes_written) + *bytes_written = resp.size(); + + return 0; + } +} + int sys_pread(int fd, void *buf, size_t n, off_t off, ssize_t *bytes_read) { SignalGuard sguard;