blob: c2d5623b651424689c2b503575e67db6427ce63f [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
William A. Kennington IIIc84bcc52023-12-19 15:23:35 -080049std::tuple<std::span<std::byte>, std::span<std::byte>>
50 FdImpl::recvfrom(std::span<std::byte> buf, RecvFlags flags,
51 std::span<std::byte> sockaddr)
52{
53 socklen_t sockaddrsize = sockaddr.size();
54 auto ret =
55 fret(buf, "recvfrom",
56 ::recvfrom(get(), buf.data(), buf.size(), static_cast<int>(flags),
57 reinterpret_cast<struct sockaddr*>(sockaddr.data()),
58 &sockaddrsize));
59 return std::make_tuple(ret, sockaddr.subspan(0, sockaddrsize));
60}
61
Patrick Williams68975b92022-04-27 16:00:26 -050062std::span<const std::byte> FdImpl::write(std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070063{
William A. Kennington III40feead2023-12-19 14:52:27 -080064 return fret(data, "write", ::write(get(), data.data(), data.size()));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070065}
66
Patrick Williams68975b92022-04-27 16:00:26 -050067std::span<const std::byte> FdImpl::send(std::span<const std::byte> data,
68 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070069{
William A. Kennington III40feead2023-12-19 14:52:27 -080070 return fret(
71 data, "send",
72 ::send(get(), data.data(), data.size(), static_cast<int>(flags)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070073}
74
William A. Kennington IIIc84bcc52023-12-19 15:23:35 -080075std::span<const std::byte> FdImpl::sendto(std::span<const std::byte> data,
76 SendFlags flags,
77 std::span<const std::byte> sockaddr)
78{
79 return fret(
80 data, "sendto",
81 ::sendto(get(), data.data(), data.size(), static_cast<int>(flags),
82 reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
83 sockaddr.size()));
84}
85
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070086static std::string_view whenceStr(Whence whence)
87{
88 switch (whence)
89 {
90 case Whence::Set:
91 return "set"sv;
92 case Whence::Cur:
93 return "cur"sv;
94 case Whence::End:
95 return "end"sv;
96 default:
97 return "Unknown whence"sv;
98 }
99}
100
101size_t FdImpl::lseek(off_t offset, Whence whence)
102{
103 return CHECK_ERRNO(::lseek(get(), offset, static_cast<int>(whence)),
William A. Kennington III6417c632023-07-17 02:56:52 -0700104 std::format("lseek {}B {}", offset, whenceStr(whence)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700105}
106
107void FdImpl::truncate(off_t size)
108{
William A. Kennington III6417c632023-07-17 02:56:52 -0700109 CHECK_ERRNO(::ftruncate(get(), size), std::format("ftruncate {}B", size));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700110}
111
Patrick Williams68975b92022-04-27 16:00:26 -0500112void FdImpl::bind(std::span<const std::byte> sockaddr)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700113{
114 CHECK_ERRNO(
115 ::bind(get(), reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
116 sockaddr.size()),
117 "bind");
118}
119
William A. Kennington III188f5712023-12-17 23:20:06 -0800120void FdImpl::connect(std::span<const std::byte> sockaddr)
121{
122 CHECK_ERRNO(
123 ::connect(get(),
124 reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
125 sockaddr.size()),
126 "connect");
127}
128
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800129void FdImpl::listen(int backlog)
130{
131 CHECK_ERRNO(::listen(get(), backlog), "listen");
132}
133
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800134std::optional<std::tuple<int, std::span<std::byte>>>
Patrick Williams68975b92022-04-27 16:00:26 -0500135 FdImpl::accept(std::span<std::byte> sockaddr)
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800136{
137 socklen_t len = sockaddr.size();
138 auto fd = ::accept(
139 get(), reinterpret_cast<struct sockaddr*>(sockaddr.data()), &len);
140 if (fd == -1)
141 {
142 if (errno == EAGAIN || errno == EWOULDBLOCK)
143 {
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800144 return std::nullopt;
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800145 }
146 throw util::makeSystemError(errno, "accept");
147 }
148 return std::make_tuple(fd, sockaddr.subspan(0, len));
149}
150
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700151void FdImpl::setsockopt(SockLevel level, SockOpt optname,
Patrick Williams68975b92022-04-27 16:00:26 -0500152 std::span<const std::byte> opt)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700153{
154 CHECK_ERRNO(::setsockopt(get(), static_cast<int>(level),
155 static_cast<int>(optname), opt.data(), opt.size()),
156 "setsockopt");
157}
158
159int FdImpl::ioctl(unsigned long id, void* data)
160{
161 return constIoctl(id, data);
162}
163
164int FdImpl::constIoctl(unsigned long id, void* data) const
165{
166 return CHECK_ERRNO(::ioctl(get(), id, data),
William A. Kennington III6417c632023-07-17 02:56:52 -0700167 std::format("ioctl {:#x}", id));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700168}
169
170void FdImpl::fcntlSetfd(FdFlags flags)
171{
172 CHECK_ERRNO(::fcntl(get(), F_SETFD, static_cast<int>(flags)),
173 "fcntl setfd");
174}
175
176FdFlags FdImpl::fcntlGetfd() const
177{
178 return FdFlags(CHECK_ERRNO(::fcntl(get(), F_GETFD), "fcntl getfd"));
179}
180
181void FdImpl::fcntlSetfl(FileFlags flags)
182{
183 CHECK_ERRNO(::fcntl(get(), F_SETFL, static_cast<int>(flags)),
184 "fcntl setfl");
185}
186
187FileFlags FdImpl::fcntlGetfl() const
188{
189 return FileFlags(CHECK_ERRNO(::fcntl(get(), F_GETFL), "fcntl getfl"));
190}
191
William A. Kennington III891e6a32022-05-17 16:35:03 -0700192std::span<std::byte> FdImpl::mmap(std::span<std::byte> window, ProtFlags prot,
193 MMapFlags flags, off_t offset)
194{
195 auto ret = ::mmap(window.data(), window.size(), static_cast<int>(prot),
196 static_cast<int>(flags), get(), offset);
197 if (ret == MAP_FAILED)
198 {
199 util::doError(errno, "mmap");
200 }
201 return {reinterpret_cast<std::byte*>(ret), window.size()};
202}
203
204void FdImpl::munmap(std::span<std::byte> window)
205{
206 CHECK_ERRNO(::munmap(window.data(), window.size()), "munmap");
207}
208
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700209} // namespace fd
210} // namespace stdplus