blob: 22a1b3b5d277e869b2b1d5a26ead4c87cb507ae8 [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 III1151c6d2022-02-08 15:11:12 -0800120void FdImpl::listen(int backlog)
121{
122 CHECK_ERRNO(::listen(get(), backlog), "listen");
123}
124
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800125std::optional<std::tuple<int, std::span<std::byte>>>
Patrick Williams68975b92022-04-27 16:00:26 -0500126 FdImpl::accept(std::span<std::byte> sockaddr)
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800127{
128 socklen_t len = sockaddr.size();
129 auto fd = ::accept(
130 get(), reinterpret_cast<struct sockaddr*>(sockaddr.data()), &len);
131 if (fd == -1)
132 {
133 if (errno == EAGAIN || errno == EWOULDBLOCK)
134 {
William A. Kennington III76e5e3a2023-12-17 23:16:35 -0800135 return std::nullopt;
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800136 }
137 throw util::makeSystemError(errno, "accept");
138 }
139 return std::make_tuple(fd, sockaddr.subspan(0, len));
140}
141
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700142void FdImpl::setsockopt(SockLevel level, SockOpt optname,
Patrick Williams68975b92022-04-27 16:00:26 -0500143 std::span<const std::byte> opt)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700144{
145 CHECK_ERRNO(::setsockopt(get(), static_cast<int>(level),
146 static_cast<int>(optname), opt.data(), opt.size()),
147 "setsockopt");
148}
149
150int FdImpl::ioctl(unsigned long id, void* data)
151{
152 return constIoctl(id, data);
153}
154
155int FdImpl::constIoctl(unsigned long id, void* data) const
156{
157 return CHECK_ERRNO(::ioctl(get(), id, data),
William A. Kennington III6417c632023-07-17 02:56:52 -0700158 std::format("ioctl {:#x}", id));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700159}
160
161void FdImpl::fcntlSetfd(FdFlags flags)
162{
163 CHECK_ERRNO(::fcntl(get(), F_SETFD, static_cast<int>(flags)),
164 "fcntl setfd");
165}
166
167FdFlags FdImpl::fcntlGetfd() const
168{
169 return FdFlags(CHECK_ERRNO(::fcntl(get(), F_GETFD), "fcntl getfd"));
170}
171
172void FdImpl::fcntlSetfl(FileFlags flags)
173{
174 CHECK_ERRNO(::fcntl(get(), F_SETFL, static_cast<int>(flags)),
175 "fcntl setfl");
176}
177
178FileFlags FdImpl::fcntlGetfl() const
179{
180 return FileFlags(CHECK_ERRNO(::fcntl(get(), F_GETFL), "fcntl getfl"));
181}
182
William A. Kennington III891e6a32022-05-17 16:35:03 -0700183std::span<std::byte> FdImpl::mmap(std::span<std::byte> window, ProtFlags prot,
184 MMapFlags flags, off_t offset)
185{
186 auto ret = ::mmap(window.data(), window.size(), static_cast<int>(prot),
187 static_cast<int>(flags), get(), offset);
188 if (ret == MAP_FAILED)
189 {
190 util::doError(errno, "mmap");
191 }
192 return {reinterpret_cast<std::byte*>(ret), window.size()};
193}
194
195void FdImpl::munmap(std::span<std::byte> window)
196{
197 CHECK_ERRNO(::munmap(window.data(), window.size()), "munmap");
198}
199
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700200} // namespace fd
201} // namespace stdplus