blob: 1ac99389f318824252af8fa9ab77faa60b77a6be [file] [log] [blame]
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07001#include <fcntl.h>
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07002#include <sys/ioctl.h>
3#include <sys/socket.h>
4#include <unistd.h>
5
Patrick Williamsd1984dd2023-05-10 16:12:44 -05006#include <stdplus/exception.hpp>
7#include <stdplus/fd/impl.hpp>
8#include <stdplus/util/cexec.hpp>
9
William A. Kennington III6417c632023-07-17 02:56:52 -070010#include <format>
Patrick Williamsd1984dd2023-05-10 16:12:44 -050011#include <string_view>
12
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070013namespace stdplus
14{
15namespace fd
16{
17
18using namespace std::literals::string_view_literals;
19
William A. Kennington III40feead2023-12-19 14:52:27 -080020template <typename Byte>
21static std::span<Byte> fret(std::span<Byte> buf, const char* name, ssize_t r)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070022{
William A. Kennington III40feead2023-12-19 14:52:27 -080023 if (r == -1)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070024 {
25 if (errno == EAGAIN || errno == EWOULDBLOCK)
26 {
27 return {};
28 }
William A. Kennington III40feead2023-12-19 14:52:27 -080029 throw util::makeSystemError(errno, name);
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070030 }
William A. Kennington III40feead2023-12-19 14:52:27 -080031 else if (r == 0 && buf.size() > 0)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070032 {
William A. Kennington III40feead2023-12-19 14:52:27 -080033 throw exception::Eof(name);
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070034 }
William A. Kennington III40feead2023-12-19 14:52:27 -080035 return buf.subspan(0, r);
36}
37
38std::span<std::byte> FdImpl::read(std::span<std::byte> buf)
39{
40 return fret(buf, "read", ::read(get(), buf.data(), buf.size()));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070041}
42
Patrick Williams68975b92022-04-27 16:00:26 -050043std::span<std::byte> FdImpl::recv(std::span<std::byte> buf, RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070044{
William A. Kennington III40feead2023-12-19 14:52:27 -080045 return fret(buf, "recv",
46 ::recv(get(), buf.data(), buf.size(), static_cast<int>(flags)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070047}
48
Patrick Williams68975b92022-04-27 16:00:26 -050049std::span<const std::byte> FdImpl::write(std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070050{
William A. Kennington III40feead2023-12-19 14:52:27 -080051 return fret(data, "write", ::write(get(), data.data(), data.size()));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070052}
53
Patrick Williams68975b92022-04-27 16:00:26 -050054std::span<const std::byte> FdImpl::send(std::span<const std::byte> data,
55 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070056{
William A. Kennington III40feead2023-12-19 14:52:27 -080057 return fret(
58 data, "send",
59 ::send(get(), data.data(), data.size(), static_cast<int>(flags)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070060}
61
62static std::string_view whenceStr(Whence whence)
63{
64 switch (whence)
65 {
66 case Whence::Set:
67 return "set"sv;
68 case Whence::Cur:
69 return "cur"sv;
70 case Whence::End:
71 return "end"sv;
72 default:
73 return "Unknown whence"sv;
74 }
75}
76
77size_t FdImpl::lseek(off_t offset, Whence whence)
78{
79 return CHECK_ERRNO(::lseek(get(), offset, static_cast<int>(whence)),
William A. Kennington III6417c632023-07-17 02:56:52 -070080 std::format("lseek {}B {}", offset, whenceStr(whence)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070081}
82
83void FdImpl::truncate(off_t size)
84{
William A. Kennington III6417c632023-07-17 02:56:52 -070085 CHECK_ERRNO(::ftruncate(get(), size), std::format("ftruncate {}B", size));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070086}
87
Patrick Williams68975b92022-04-27 16:00:26 -050088void FdImpl::bind(std::span<const std::byte> sockaddr)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070089{
90 CHECK_ERRNO(
91 ::bind(get(), reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
92 sockaddr.size()),
93 "bind");
94}
95
William A. Kennington III1151c6d2022-02-08 15:11:12 -080096void FdImpl::listen(int backlog)
97{
98 CHECK_ERRNO(::listen(get(), backlog), "listen");
99}
100
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800101std::optional<std::tuple<int, std::span<std::byte>>>
Patrick Williams68975b92022-04-27 16:00:26 -0500102 FdImpl::accept(std::span<std::byte> sockaddr)
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800103{
104 socklen_t len = sockaddr.size();
105 auto fd = ::accept(
106 get(), reinterpret_cast<struct sockaddr*>(sockaddr.data()), &len);
107 if (fd == -1)
108 {
109 if (errno == EAGAIN || errno == EWOULDBLOCK)
110 {
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800111 return std::nullopt;
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800112 }
113 throw util::makeSystemError(errno, "accept");
114 }
115 return std::make_tuple(fd, sockaddr.subspan(0, len));
116}
117
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700118void FdImpl::setsockopt(SockLevel level, SockOpt optname,
Patrick Williams68975b92022-04-27 16:00:26 -0500119 std::span<const std::byte> opt)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700120{
121 CHECK_ERRNO(::setsockopt(get(), static_cast<int>(level),
122 static_cast<int>(optname), opt.data(), opt.size()),
123 "setsockopt");
124}
125
126int FdImpl::ioctl(unsigned long id, void* data)
127{
128 return constIoctl(id, data);
129}
130
131int FdImpl::constIoctl(unsigned long id, void* data) const
132{
133 return CHECK_ERRNO(::ioctl(get(), id, data),
William A. Kennington III6417c632023-07-17 02:56:52 -0700134 std::format("ioctl {:#x}", id));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700135}
136
137void FdImpl::fcntlSetfd(FdFlags flags)
138{
139 CHECK_ERRNO(::fcntl(get(), F_SETFD, static_cast<int>(flags)),
140 "fcntl setfd");
141}
142
143FdFlags FdImpl::fcntlGetfd() const
144{
145 return FdFlags(CHECK_ERRNO(::fcntl(get(), F_GETFD), "fcntl getfd"));
146}
147
148void FdImpl::fcntlSetfl(FileFlags flags)
149{
150 CHECK_ERRNO(::fcntl(get(), F_SETFL, static_cast<int>(flags)),
151 "fcntl setfl");
152}
153
154FileFlags FdImpl::fcntlGetfl() const
155{
156 return FileFlags(CHECK_ERRNO(::fcntl(get(), F_GETFL), "fcntl getfl"));
157}
158
William A. Kennington III891e6a32022-05-17 16:35:03 -0700159std::span<std::byte> FdImpl::mmap(std::span<std::byte> window, ProtFlags prot,
160 MMapFlags flags, off_t offset)
161{
162 auto ret = ::mmap(window.data(), window.size(), static_cast<int>(prot),
163 static_cast<int>(flags), get(), offset);
164 if (ret == MAP_FAILED)
165 {
166 util::doError(errno, "mmap");
167 }
168 return {reinterpret_cast<std::byte*>(ret), window.size()};
169}
170
171void FdImpl::munmap(std::span<std::byte> window)
172{
173 CHECK_ERRNO(::munmap(window.data(), window.size()), "munmap");
174}
175
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700176} // namespace fd
177} // namespace stdplus