blob: 40ce7b32c7b180c3b7037850cc4a4ad4ea10d0db [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
Patrick Williams68975b92022-04-27 16:00:26 -050020std::span<std::byte> FdImpl::read(std::span<std::byte> buf)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070021{
22 ssize_t amt = ::read(get(), buf.data(), buf.size());
23 if (amt == -1)
24 {
25 if (errno == EAGAIN || errno == EWOULDBLOCK)
26 {
27 return {};
28 }
29 throw util::makeSystemError(errno, "read");
30 }
31 else if (amt == 0)
32 {
33 throw exception::Eof("read");
34 }
35 return buf.subspan(0, amt);
36}
37
Patrick Williams68975b92022-04-27 16:00:26 -050038std::span<std::byte> FdImpl::recv(std::span<std::byte> buf, RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070039{
Patrick Williamsd1984dd2023-05-10 16:12:44 -050040 ssize_t amt = ::recv(get(), buf.data(), buf.size(),
41 static_cast<int>(flags));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070042 if (amt == -1)
43 {
44 if (errno == EAGAIN || errno == EWOULDBLOCK)
45 {
46 return {};
47 }
48 throw util::makeSystemError(errno, "recv");
49 }
50 else if (amt == 0)
51 {
52 throw exception::Eof("recv");
53 }
54 return buf.subspan(0, amt);
55}
56
Patrick Williams68975b92022-04-27 16:00:26 -050057std::span<const std::byte> FdImpl::write(std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070058{
59 ssize_t amt = ::write(get(), data.data(), data.size());
60 if (amt == -1)
61 {
62 if (errno == EAGAIN || errno == EWOULDBLOCK)
63 {
64 return {};
65 }
66 throw util::makeSystemError(errno, "write");
67 }
68 return data.subspan(0, amt);
69}
70
Patrick Williams68975b92022-04-27 16:00:26 -050071std::span<const std::byte> FdImpl::send(std::span<const std::byte> data,
72 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070073{
Patrick Williamsd1984dd2023-05-10 16:12:44 -050074 ssize_t amt = ::send(get(), data.data(), data.size(),
75 static_cast<int>(flags));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070076 if (amt == -1)
77 {
78 if (errno == EAGAIN || errno == EWOULDBLOCK)
79 {
80 return {};
81 }
82 throw util::makeSystemError(errno, "send");
83 }
84 return data.subspan(0, amt);
85}
86
87static std::string_view whenceStr(Whence whence)
88{
89 switch (whence)
90 {
91 case Whence::Set:
92 return "set"sv;
93 case Whence::Cur:
94 return "cur"sv;
95 case Whence::End:
96 return "end"sv;
97 default:
98 return "Unknown whence"sv;
99 }
100}
101
102size_t FdImpl::lseek(off_t offset, Whence whence)
103{
104 return CHECK_ERRNO(::lseek(get(), offset, static_cast<int>(whence)),
William A. Kennington III6417c632023-07-17 02:56:52 -0700105 std::format("lseek {}B {}", offset, whenceStr(whence)));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700106}
107
108void FdImpl::truncate(off_t size)
109{
William A. Kennington III6417c632023-07-17 02:56:52 -0700110 CHECK_ERRNO(::ftruncate(get(), size), std::format("ftruncate {}B", size));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700111}
112
Patrick Williams68975b92022-04-27 16:00:26 -0500113void FdImpl::bind(std::span<const std::byte> sockaddr)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700114{
115 CHECK_ERRNO(
116 ::bind(get(), reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
117 sockaddr.size()),
118 "bind");
119}
120
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800121void FdImpl::listen(int backlog)
122{
123 CHECK_ERRNO(::listen(get(), backlog), "listen");
124}
125
Patrick Williams68975b92022-04-27 16:00:26 -0500126std::tuple<std::optional<int>, std::span<std::byte>>
127 FdImpl::accept(std::span<std::byte> sockaddr)
William A. Kennington III1151c6d2022-02-08 15:11:12 -0800128{
129 socklen_t len = sockaddr.size();
130 auto fd = ::accept(
131 get(), reinterpret_cast<struct sockaddr*>(sockaddr.data()), &len);
132 if (fd == -1)
133 {
134 if (errno == EAGAIN || errno == EWOULDBLOCK)
135 {
136 return {};
137 }
138 throw util::makeSystemError(errno, "accept");
139 }
140 return std::make_tuple(fd, sockaddr.subspan(0, len));
141}
142
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700143void FdImpl::setsockopt(SockLevel level, SockOpt optname,
Patrick Williams68975b92022-04-27 16:00:26 -0500144 std::span<const std::byte> opt)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700145{
146 CHECK_ERRNO(::setsockopt(get(), static_cast<int>(level),
147 static_cast<int>(optname), opt.data(), opt.size()),
148 "setsockopt");
149}
150
151int FdImpl::ioctl(unsigned long id, void* data)
152{
153 return constIoctl(id, data);
154}
155
156int FdImpl::constIoctl(unsigned long id, void* data) const
157{
158 return CHECK_ERRNO(::ioctl(get(), id, data),
William A. Kennington III6417c632023-07-17 02:56:52 -0700159 std::format("ioctl {:#x}", id));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700160}
161
162void FdImpl::fcntlSetfd(FdFlags flags)
163{
164 CHECK_ERRNO(::fcntl(get(), F_SETFD, static_cast<int>(flags)),
165 "fcntl setfd");
166}
167
168FdFlags FdImpl::fcntlGetfd() const
169{
170 return FdFlags(CHECK_ERRNO(::fcntl(get(), F_GETFD), "fcntl getfd"));
171}
172
173void FdImpl::fcntlSetfl(FileFlags flags)
174{
175 CHECK_ERRNO(::fcntl(get(), F_SETFL, static_cast<int>(flags)),
176 "fcntl setfl");
177}
178
179FileFlags FdImpl::fcntlGetfl() const
180{
181 return FileFlags(CHECK_ERRNO(::fcntl(get(), F_GETFL), "fcntl getfl"));
182}
183
William A. Kennington III891e6a32022-05-17 16:35:03 -0700184std::span<std::byte> FdImpl::mmap(std::span<std::byte> window, ProtFlags prot,
185 MMapFlags flags, off_t offset)
186{
187 auto ret = ::mmap(window.data(), window.size(), static_cast<int>(prot),
188 static_cast<int>(flags), get(), offset);
189 if (ret == MAP_FAILED)
190 {
191 util::doError(errno, "mmap");
192 }
193 return {reinterpret_cast<std::byte*>(ret), window.size()};
194}
195
196void FdImpl::munmap(std::span<std::byte> window)
197{
198 CHECK_ERRNO(::munmap(window.data(), window.size()), "munmap");
199}
200
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700201} // namespace fd
202} // namespace stdplus