blob: 3147e6483c437a416fff886ad519cd56494e7306 [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 Williamsd8e0af52024-08-16 15:21:12 -040049std::tuple<std::span<std::byte>, std::span<std::byte>> FdImpl::recvfrom(
50 std::span<std::byte> buf, RecvFlags flags, std::span<std::byte> sockaddr)
William A. Kennington IIIc84bcc52023-12-19 15:23:35 -080051{
52 socklen_t sockaddrsize = sockaddr.size();
53 auto ret =
54 fret(buf, "recvfrom",
55 ::recvfrom(get(), buf.data(), buf.size(), static_cast<int>(flags),
56 reinterpret_cast<struct sockaddr*>(sockaddr.data()),
57 &sockaddrsize));
58 return std::make_tuple(ret, sockaddr.subspan(0, sockaddrsize));
59}
60
Patrick Williams68975b92022-04-27 16:00:26 -050061std::span<const std::byte> FdImpl::write(std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070062{
William A. Kennington III40feead2023-12-19 14:52:27 -080063 return fret(data, "write", ::write(get(), data.data(), data.size()));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070064}
65
Patrick Williams68975b92022-04-27 16:00:26 -050066std::span<const std::byte> FdImpl::send(std::span<const std::byte> data,
67 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070068{
Patrick Williamsd8e0af52024-08-16 15:21:12 -040069 return fret(data, "send",
70 ::send(get(), data.data(), data.size(),
71 static_cast<int>(flags)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070072}
73
Patrick Williamsd8e0af52024-08-16 15:21:12 -040074std::span<const std::byte>
75 FdImpl::sendto(std::span<const std::byte> data, SendFlags flags,
76 std::span<const std::byte> sockaddr)
William A. Kennington IIIc84bcc52023-12-19 15:23:35 -080077{
78 return fret(
79 data, "sendto",
80 ::sendto(get(), data.data(), data.size(), static_cast<int>(flags),
81 reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
82 sockaddr.size()));
83}
84
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070085static std::string_view whenceStr(Whence whence)
86{
87 switch (whence)
88 {
89 case Whence::Set:
90 return "set"sv;
91 case Whence::Cur:
92 return "cur"sv;
93 case Whence::End:
94 return "end"sv;
95 default:
96 return "Unknown whence"sv;
97 }
98}
99
100size_t FdImpl::lseek(off_t offset, Whence whence)
101{
102 return CHECK_ERRNO(::lseek(get(), offset, static_cast<int>(whence)),
William A. Kennington III6417c632023-07-17 02:56:52 -0700103 std::format("lseek {}B {}", offset, whenceStr(whence)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700104}
105
106void FdImpl::truncate(off_t size)
107{
William A. Kennington III6417c632023-07-17 02:56:52 -0700108 CHECK_ERRNO(::ftruncate(get(), size), std::format("ftruncate {}B", size));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700109}
110
Patrick Williams68975b92022-04-27 16:00:26 -0500111void FdImpl::bind(std::span<const std::byte> sockaddr)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700112{
113 CHECK_ERRNO(
114 ::bind(get(), reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
115 sockaddr.size()),
116 "bind");
117}
118
William A. Kennington III188f5712023-12-17 23:20:06 -0800119void FdImpl::connect(std::span<const std::byte> sockaddr)
120{
121 CHECK_ERRNO(
122 ::connect(get(),
123 reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
124 sockaddr.size()),
125 "connect");
126}
127
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800128void FdImpl::listen(int backlog)
129{
130 CHECK_ERRNO(::listen(get(), backlog), "listen");
131}
132
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800133std::optional<std::tuple<int, std::span<std::byte>>>
Patrick Williams68975b92022-04-27 16:00:26 -0500134 FdImpl::accept(std::span<std::byte> sockaddr)
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800135{
136 socklen_t len = sockaddr.size();
137 auto fd = ::accept(
138 get(), reinterpret_cast<struct sockaddr*>(sockaddr.data()), &len);
139 if (fd == -1)
140 {
141 if (errno == EAGAIN || errno == EWOULDBLOCK)
142 {
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800143 return std::nullopt;
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800144 }
145 throw util::makeSystemError(errno, "accept");
146 }
147 return std::make_tuple(fd, sockaddr.subspan(0, len));
148}
149
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700150void FdImpl::setsockopt(SockLevel level, SockOpt optname,
Patrick Williams68975b92022-04-27 16:00:26 -0500151 std::span<const std::byte> opt)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700152{
153 CHECK_ERRNO(::setsockopt(get(), static_cast<int>(level),
154 static_cast<int>(optname), opt.data(), opt.size()),
155 "setsockopt");
156}
157
158int FdImpl::ioctl(unsigned long id, void* data)
159{
160 return constIoctl(id, data);
161}
162
163int FdImpl::constIoctl(unsigned long id, void* data) const
164{
165 return CHECK_ERRNO(::ioctl(get(), id, data),
William A. Kennington III6417c632023-07-17 02:56:52 -0700166 std::format("ioctl {:#x}", id));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700167}
168
169void FdImpl::fcntlSetfd(FdFlags flags)
170{
171 CHECK_ERRNO(::fcntl(get(), F_SETFD, static_cast<int>(flags)),
172 "fcntl setfd");
173}
174
175FdFlags FdImpl::fcntlGetfd() const
176{
177 return FdFlags(CHECK_ERRNO(::fcntl(get(), F_GETFD), "fcntl getfd"));
178}
179
180void FdImpl::fcntlSetfl(FileFlags flags)
181{
182 CHECK_ERRNO(::fcntl(get(), F_SETFL, static_cast<int>(flags)),
183 "fcntl setfl");
184}
185
186FileFlags FdImpl::fcntlGetfl() const
187{
188 return FileFlags(CHECK_ERRNO(::fcntl(get(), F_GETFL), "fcntl getfl"));
189}
190
William A. Kennington III891e6a32022-05-17 16:35:03 -0700191std::span<std::byte> FdImpl::mmap(std::span<std::byte> window, ProtFlags prot,
192 MMapFlags flags, off_t offset)
193{
194 auto ret = ::mmap(window.data(), window.size(), static_cast<int>(prot),
195 static_cast<int>(flags), get(), offset);
196 if (ret == MAP_FAILED)
197 {
198 util::doError(errno, "mmap");
199 }
200 return {reinterpret_cast<std::byte*>(ret), window.size()};
201}
202
203void FdImpl::munmap(std::span<std::byte> window)
204{
205 CHECK_ERRNO(::munmap(window.data(), window.size()), "munmap");
206}
207
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700208} // namespace fd
209} // namespace stdplus