Stream.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "Stream.h"
  8. #include <LibCore/System.h>
  9. #include <fcntl.h>
  10. #include <netdb.h>
  11. #include <poll.h>
  12. #include <sys/ioctl.h>
  13. #include <sys/socket.h>
  14. #include <sys/types.h>
  15. #include <unistd.h>
  16. #ifdef AK_OS_SERENITY
  17. # include <serenity.h>
  18. #endif
  19. #ifdef AK_OS_FREEBSD
  20. # include <sys/ucred.h>
  21. #endif
  22. namespace Core::Stream {
  23. bool Stream::read_or_error(Bytes buffer)
  24. {
  25. VERIFY(buffer.size());
  26. size_t nread = 0;
  27. do {
  28. if (is_eof())
  29. return false;
  30. auto result = read(buffer.slice(nread));
  31. if (result.is_error()) {
  32. if (result.error().is_errno() && result.error().code() == EINTR) {
  33. continue;
  34. }
  35. return false;
  36. }
  37. nread += result.value().size();
  38. } while (nread < buffer.size());
  39. return true;
  40. }
  41. ErrorOr<ByteBuffer> Stream::read_all(size_t block_size)
  42. {
  43. return read_all_impl(block_size);
  44. }
  45. ErrorOr<ByteBuffer> Stream::read_all_impl(size_t block_size, size_t expected_file_size)
  46. {
  47. ByteBuffer data;
  48. data.ensure_capacity(expected_file_size);
  49. size_t total_read = 0;
  50. Bytes buffer;
  51. while (!is_eof()) {
  52. if (buffer.is_empty()) {
  53. buffer = TRY(data.get_bytes_for_writing(block_size));
  54. }
  55. auto nread = TRY(read(buffer)).size();
  56. total_read += nread;
  57. buffer = buffer.slice(nread);
  58. }
  59. data.resize(total_read);
  60. return data;
  61. }
  62. bool Stream::write_or_error(ReadonlyBytes buffer)
  63. {
  64. VERIFY(buffer.size());
  65. size_t nwritten = 0;
  66. do {
  67. auto result = write(buffer.slice(nwritten));
  68. if (result.is_error()) {
  69. if (result.error().is_errno() && result.error().code() == EINTR) {
  70. continue;
  71. }
  72. return false;
  73. }
  74. nwritten += result.value();
  75. } while (nwritten < buffer.size());
  76. return true;
  77. }
  78. ErrorOr<off_t> SeekableStream::tell() const
  79. {
  80. // Seek with 0 and SEEK_CUR does not modify anything despite the const_cast,
  81. // so it's safe to do this.
  82. return const_cast<SeekableStream*>(this)->seek(0, SeekMode::FromCurrentPosition);
  83. }
  84. ErrorOr<off_t> SeekableStream::size()
  85. {
  86. auto original_position = TRY(tell());
  87. auto seek_result = seek(0, SeekMode::FromEndPosition);
  88. if (seek_result.is_error()) {
  89. // Let's try to restore the original position, just in case.
  90. auto restore_result = seek(original_position, SeekMode::SetPosition);
  91. if (restore_result.is_error()) {
  92. dbgln("Core::SeekableStream::size: Couldn't restore initial position, stream might have incorrect position now!");
  93. }
  94. return seek_result.release_error();
  95. }
  96. TRY(seek(original_position, SeekMode::SetPosition));
  97. return seek_result.value();
  98. }
  99. ErrorOr<NonnullOwnPtr<File>> File::open(StringView filename, OpenMode mode, mode_t permissions)
  100. {
  101. auto file = TRY(adopt_nonnull_own_or_enomem(new (nothrow) File(mode)));
  102. TRY(file->open_path(filename, permissions));
  103. return file;
  104. }
  105. ErrorOr<NonnullOwnPtr<File>> File::adopt_fd(int fd, OpenMode mode, ShouldCloseFileDescriptor should_close_file_descriptor)
  106. {
  107. if (fd < 0) {
  108. return Error::from_errno(EBADF);
  109. }
  110. if (!has_any_flag(mode, OpenMode::ReadWrite)) {
  111. dbgln("Core::File::adopt_fd: Attempting to adopt a file with neither Read nor Write specified in mode");
  112. return Error::from_errno(EINVAL);
  113. }
  114. auto file = TRY(adopt_nonnull_own_or_enomem(new (nothrow) File(mode, should_close_file_descriptor)));
  115. file->m_fd = fd;
  116. return file;
  117. }
  118. bool File::exists(StringView filename)
  119. {
  120. return !Core::System::stat(filename).is_error();
  121. }
  122. ErrorOr<NonnullOwnPtr<File>> File::standard_input()
  123. {
  124. return File::adopt_fd(STDIN_FILENO, OpenMode::Read, ShouldCloseFileDescriptor::No);
  125. }
  126. ErrorOr<NonnullOwnPtr<File>> File::standard_output()
  127. {
  128. return File::adopt_fd(STDOUT_FILENO, OpenMode::Write, ShouldCloseFileDescriptor::No);
  129. }
  130. ErrorOr<NonnullOwnPtr<File>> File::standard_error()
  131. {
  132. return File::adopt_fd(STDERR_FILENO, OpenMode::Write, ShouldCloseFileDescriptor::No);
  133. }
  134. ErrorOr<NonnullOwnPtr<File>> File::open_file_or_standard_stream(StringView filename, OpenMode mode)
  135. {
  136. if (!filename.is_empty() && filename != "-"sv)
  137. return File::open(filename, mode);
  138. switch (mode) {
  139. case OpenMode::Read:
  140. return standard_input();
  141. case OpenMode::Write:
  142. return standard_output();
  143. default:
  144. VERIFY_NOT_REACHED();
  145. }
  146. }
  147. int File::open_mode_to_options(OpenMode mode)
  148. {
  149. int flags = 0;
  150. if (has_flag(mode, OpenMode::ReadWrite)) {
  151. flags |= O_RDWR | O_CREAT;
  152. } else if (has_flag(mode, OpenMode::Read)) {
  153. flags |= O_RDONLY;
  154. } else if (has_flag(mode, OpenMode::Write)) {
  155. flags |= O_WRONLY | O_CREAT;
  156. bool should_truncate = !has_any_flag(mode, OpenMode::Append | OpenMode::MustBeNew);
  157. if (should_truncate)
  158. flags |= O_TRUNC;
  159. }
  160. if (has_flag(mode, OpenMode::Append))
  161. flags |= O_APPEND;
  162. if (has_flag(mode, OpenMode::Truncate))
  163. flags |= O_TRUNC;
  164. if (has_flag(mode, OpenMode::MustBeNew))
  165. flags |= O_EXCL;
  166. if (!has_flag(mode, OpenMode::KeepOnExec))
  167. flags |= O_CLOEXEC;
  168. if (!has_flag(mode, OpenMode::Nonblocking))
  169. flags |= O_NONBLOCK;
  170. return flags;
  171. }
  172. ErrorOr<void> File::open_path(StringView filename, mode_t permissions)
  173. {
  174. VERIFY(m_fd == -1);
  175. auto flags = open_mode_to_options(m_mode);
  176. m_fd = TRY(System::open(filename, flags, permissions));
  177. return {};
  178. }
  179. bool File::is_readable() const { return has_flag(m_mode, OpenMode::Read); }
  180. bool File::is_writable() const { return has_flag(m_mode, OpenMode::Write); }
  181. ErrorOr<Bytes> File::read(Bytes buffer)
  182. {
  183. if (!has_flag(m_mode, OpenMode::Read)) {
  184. // NOTE: POSIX says that if the fd is not open for reading, the call
  185. // will return EBADF. Since we already know whether we can or
  186. // can't read the file, let's avoid a syscall.
  187. return Error::from_errno(EBADF);
  188. }
  189. ssize_t nread = TRY(System::read(m_fd, buffer));
  190. m_last_read_was_eof = nread == 0;
  191. return buffer.trim(nread);
  192. }
  193. ErrorOr<ByteBuffer> File::read_all(size_t block_size)
  194. {
  195. // Note: This is used as a heuristic, it's not valid for devices or virtual files.
  196. auto const potential_file_size = TRY(System::fstat(m_fd)).st_size;
  197. return read_all_impl(block_size, potential_file_size);
  198. }
  199. ErrorOr<size_t> File::write(ReadonlyBytes buffer)
  200. {
  201. if (!has_flag(m_mode, OpenMode::Write)) {
  202. // NOTE: Same deal as Read.
  203. return Error::from_errno(EBADF);
  204. }
  205. return TRY(System::write(m_fd, buffer));
  206. }
  207. bool File::is_eof() const { return m_last_read_was_eof; }
  208. bool File::is_open() const { return m_fd >= 0; }
  209. void File::close()
  210. {
  211. if (!is_open()) {
  212. return;
  213. }
  214. // NOTE: The closing of the file can be interrupted by a signal, in which
  215. // case EINTR will be returned by the close syscall. So let's try closing
  216. // the file until we aren't interrupted by rude signals. :^)
  217. ErrorOr<void> result;
  218. do {
  219. result = System::close(m_fd);
  220. } while (result.is_error() && result.error().code() == EINTR);
  221. VERIFY(!result.is_error());
  222. m_fd = -1;
  223. }
  224. ErrorOr<off_t> File::seek(i64 offset, SeekMode mode)
  225. {
  226. int syscall_mode;
  227. switch (mode) {
  228. case SeekMode::SetPosition:
  229. syscall_mode = SEEK_SET;
  230. break;
  231. case SeekMode::FromCurrentPosition:
  232. syscall_mode = SEEK_CUR;
  233. break;
  234. case SeekMode::FromEndPosition:
  235. syscall_mode = SEEK_END;
  236. break;
  237. default:
  238. VERIFY_NOT_REACHED();
  239. }
  240. off_t seek_result = TRY(System::lseek(m_fd, offset, syscall_mode));
  241. m_last_read_was_eof = false;
  242. return seek_result;
  243. }
  244. ErrorOr<void> File::truncate(off_t length)
  245. {
  246. return System::ftruncate(m_fd, length);
  247. }
  248. ErrorOr<int> Socket::create_fd(SocketDomain domain, SocketType type)
  249. {
  250. int socket_domain;
  251. switch (domain) {
  252. case SocketDomain::Inet:
  253. socket_domain = AF_INET;
  254. break;
  255. case SocketDomain::Local:
  256. socket_domain = AF_LOCAL;
  257. break;
  258. default:
  259. VERIFY_NOT_REACHED();
  260. }
  261. int socket_type;
  262. switch (type) {
  263. case SocketType::Stream:
  264. socket_type = SOCK_STREAM;
  265. break;
  266. case SocketType::Datagram:
  267. socket_type = SOCK_DGRAM;
  268. break;
  269. default:
  270. VERIFY_NOT_REACHED();
  271. }
  272. // Let's have a safe default of CLOEXEC. :^)
  273. #ifdef SOCK_CLOEXEC
  274. return System::socket(socket_domain, socket_type | SOCK_CLOEXEC, 0);
  275. #else
  276. auto fd = TRY(System::socket(socket_domain, socket_type, 0));
  277. TRY(System::fcntl(fd, F_SETFD, FD_CLOEXEC));
  278. return fd;
  279. #endif
  280. }
  281. ErrorOr<IPv4Address> Socket::resolve_host(String const& host, SocketType type)
  282. {
  283. int socket_type;
  284. switch (type) {
  285. case SocketType::Stream:
  286. socket_type = SOCK_STREAM;
  287. break;
  288. case SocketType::Datagram:
  289. socket_type = SOCK_DGRAM;
  290. break;
  291. default:
  292. VERIFY_NOT_REACHED();
  293. }
  294. struct addrinfo hints = {};
  295. hints.ai_family = AF_UNSPEC;
  296. hints.ai_socktype = socket_type;
  297. hints.ai_flags = 0;
  298. hints.ai_protocol = 0;
  299. // FIXME: Convert this to Core::System
  300. struct addrinfo* results = nullptr;
  301. int rc = getaddrinfo(host.characters(), nullptr, &hints, &results);
  302. if (rc != 0) {
  303. if (rc == EAI_SYSTEM) {
  304. return Error::from_syscall("getaddrinfo"sv, -errno);
  305. }
  306. auto const* error_string = gai_strerror(rc);
  307. return Error::from_string_view({ error_string, strlen(error_string) });
  308. }
  309. ScopeGuard free_results = [results] { freeaddrinfo(results); };
  310. for (auto* result = results; result != nullptr; result = result->ai_next) {
  311. if (result->ai_family == AF_INET) {
  312. auto* socket_address = bit_cast<struct sockaddr_in*>(result->ai_addr);
  313. NetworkOrdered<u32> network_ordered_address { socket_address->sin_addr.s_addr };
  314. return IPv4Address { network_ordered_address };
  315. }
  316. }
  317. return Error::from_string_literal("Could not resolve to IPv4 address");
  318. }
  319. ErrorOr<void> Socket::connect_local(int fd, String const& path)
  320. {
  321. auto address = SocketAddress::local(path);
  322. auto maybe_sockaddr = address.to_sockaddr_un();
  323. if (!maybe_sockaddr.has_value()) {
  324. dbgln("Core::Stream::Socket::connect_local: Could not obtain a sockaddr_un");
  325. return Error::from_errno(EINVAL);
  326. }
  327. auto addr = maybe_sockaddr.release_value();
  328. return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr));
  329. }
  330. ErrorOr<void> Socket::connect_inet(int fd, SocketAddress const& address)
  331. {
  332. auto addr = address.to_sockaddr_in();
  333. return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr));
  334. }
  335. ErrorOr<Bytes> PosixSocketHelper::read(Bytes buffer, int flags)
  336. {
  337. if (!is_open()) {
  338. return Error::from_errno(ENOTCONN);
  339. }
  340. ssize_t nread = TRY(System::recv(m_fd, buffer.data(), buffer.size(), flags));
  341. m_last_read_was_eof = nread == 0;
  342. // If a socket read is EOF, then no more data can be read from it because
  343. // the protocol has disconnected. In this case, we can just disable the
  344. // notifier if we have one.
  345. if (m_last_read_was_eof && m_notifier)
  346. m_notifier->set_enabled(false);
  347. return buffer.trim(nread);
  348. }
  349. ErrorOr<size_t> PosixSocketHelper::write(ReadonlyBytes buffer)
  350. {
  351. if (!is_open()) {
  352. return Error::from_errno(ENOTCONN);
  353. }
  354. return TRY(System::send(m_fd, buffer.data(), buffer.size(), 0));
  355. }
  356. void PosixSocketHelper::close()
  357. {
  358. if (!is_open()) {
  359. return;
  360. }
  361. if (m_notifier)
  362. m_notifier->set_enabled(false);
  363. ErrorOr<void> result;
  364. do {
  365. result = System::close(m_fd);
  366. } while (result.is_error() && result.error().code() == EINTR);
  367. VERIFY(!result.is_error());
  368. m_fd = -1;
  369. }
  370. ErrorOr<bool> PosixSocketHelper::can_read_without_blocking(int timeout) const
  371. {
  372. struct pollfd the_fd = { .fd = m_fd, .events = POLLIN, .revents = 0 };
  373. // FIXME: Convert this to Core::System
  374. int rc;
  375. do {
  376. rc = ::poll(&the_fd, 1, timeout);
  377. } while (rc < 0 && errno == EINTR);
  378. if (rc < 0) {
  379. return Error::from_syscall("poll"sv, -errno);
  380. }
  381. return (the_fd.revents & POLLIN) > 0;
  382. }
  383. ErrorOr<void> PosixSocketHelper::set_blocking(bool enabled)
  384. {
  385. int value = enabled ? 0 : 1;
  386. return System::ioctl(m_fd, FIONBIO, &value);
  387. }
  388. ErrorOr<void> PosixSocketHelper::set_close_on_exec(bool enabled)
  389. {
  390. int flags = TRY(System::fcntl(m_fd, F_GETFD));
  391. if (enabled)
  392. flags |= FD_CLOEXEC;
  393. else
  394. flags &= ~FD_CLOEXEC;
  395. TRY(System::fcntl(m_fd, F_SETFD, flags));
  396. return {};
  397. }
  398. ErrorOr<void> PosixSocketHelper::set_receive_timeout(Time timeout)
  399. {
  400. auto timeout_spec = timeout.to_timespec();
  401. return System::setsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_spec, sizeof(timeout_spec));
  402. }
  403. void PosixSocketHelper::setup_notifier()
  404. {
  405. if (!m_notifier)
  406. m_notifier = Core::Notifier::construct(m_fd, Core::Notifier::Read);
  407. }
  408. ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(String const& host, u16 port)
  409. {
  410. auto ip_address = TRY(resolve_host(host, SocketType::Stream));
  411. return connect(SocketAddress { ip_address, port });
  412. }
  413. ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(SocketAddress const& address)
  414. {
  415. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket()));
  416. auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Stream));
  417. socket->m_helper.set_fd(fd);
  418. TRY(connect_inet(fd, address));
  419. socket->setup_notifier();
  420. return socket;
  421. }
  422. ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::adopt_fd(int fd)
  423. {
  424. if (fd < 0) {
  425. return Error::from_errno(EBADF);
  426. }
  427. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket()));
  428. socket->m_helper.set_fd(fd);
  429. socket->setup_notifier();
  430. return socket;
  431. }
  432. ErrorOr<size_t> PosixSocketHelper::pending_bytes() const
  433. {
  434. if (!is_open()) {
  435. return Error::from_errno(ENOTCONN);
  436. }
  437. int value;
  438. TRY(System::ioctl(m_fd, FIONREAD, &value));
  439. return static_cast<size_t>(value);
  440. }
  441. ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(String const& host, u16 port, Optional<Time> timeout)
  442. {
  443. auto ip_address = TRY(resolve_host(host, SocketType::Datagram));
  444. return connect(SocketAddress { ip_address, port }, timeout);
  445. }
  446. ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(SocketAddress const& address, Optional<Time> timeout)
  447. {
  448. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) UDPSocket()));
  449. auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Datagram));
  450. socket->m_helper.set_fd(fd);
  451. if (timeout.has_value()) {
  452. TRY(socket->m_helper.set_receive_timeout(timeout.value()));
  453. }
  454. TRY(connect_inet(fd, address));
  455. socket->setup_notifier();
  456. return socket;
  457. }
  458. ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::connect(String const& path)
  459. {
  460. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket()));
  461. auto fd = TRY(create_fd(SocketDomain::Local, SocketType::Stream));
  462. socket->m_helper.set_fd(fd);
  463. TRY(connect_local(fd, path));
  464. socket->setup_notifier();
  465. return socket;
  466. }
  467. ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::adopt_fd(int fd)
  468. {
  469. if (fd < 0) {
  470. return Error::from_errno(EBADF);
  471. }
  472. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket()));
  473. socket->m_helper.set_fd(fd);
  474. socket->setup_notifier();
  475. return socket;
  476. }
  477. ErrorOr<int> LocalSocket::receive_fd(int flags)
  478. {
  479. #if defined(AK_OS_SERENITY)
  480. return Core::System::recvfd(m_helper.fd(), flags);
  481. #elif defined(AK_OS_LINUX) || defined(AK_OS_MACOS)
  482. union {
  483. struct cmsghdr cmsghdr;
  484. char control[CMSG_SPACE(sizeof(int))];
  485. } cmsgu {};
  486. char c = 0;
  487. struct iovec iov {
  488. .iov_base = &c,
  489. .iov_len = 1,
  490. };
  491. struct msghdr msg {
  492. .msg_name = NULL,
  493. .msg_namelen = 0,
  494. .msg_iov = &iov,
  495. .msg_iovlen = 1,
  496. .msg_control = cmsgu.control,
  497. .msg_controllen = sizeof(cmsgu.control),
  498. .msg_flags = 0,
  499. };
  500. TRY(Core::System::recvmsg(m_helper.fd(), &msg, 0));
  501. struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
  502. if (!cmsg || cmsg->cmsg_len != CMSG_LEN(sizeof(int)))
  503. return Error::from_string_literal("Malformed message when receiving file descriptor");
  504. VERIFY(cmsg->cmsg_level == SOL_SOCKET);
  505. VERIFY(cmsg->cmsg_type == SCM_RIGHTS);
  506. int fd = *((int*)CMSG_DATA(cmsg));
  507. if (flags & O_CLOEXEC) {
  508. auto fd_flags = TRY(Core::System::fcntl(fd, F_GETFD));
  509. TRY(Core::System::fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC));
  510. }
  511. return fd;
  512. #else
  513. (void)flags;
  514. return Error::from_string_literal("File descriptor passing not supported on this platform");
  515. #endif
  516. }
  517. ErrorOr<void> LocalSocket::send_fd(int fd)
  518. {
  519. #if defined(AK_OS_SERENITY)
  520. return Core::System::sendfd(m_helper.fd(), fd);
  521. #elif defined(AK_OS_LINUX) || defined(AK_OS_MACOS)
  522. char c = 'F';
  523. struct iovec iov {
  524. .iov_base = &c,
  525. .iov_len = sizeof(c)
  526. };
  527. union {
  528. struct cmsghdr cmsghdr;
  529. char control[CMSG_SPACE(sizeof(int))];
  530. } cmsgu {};
  531. struct msghdr msg {
  532. .msg_name = NULL,
  533. .msg_namelen = 0,
  534. .msg_iov = &iov,
  535. .msg_iovlen = 1,
  536. .msg_control = cmsgu.control,
  537. .msg_controllen = sizeof(cmsgu.control),
  538. .msg_flags = 0,
  539. };
  540. struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
  541. cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  542. cmsg->cmsg_level = SOL_SOCKET;
  543. cmsg->cmsg_type = SCM_RIGHTS;
  544. *((int*)CMSG_DATA(cmsg)) = fd;
  545. TRY(Core::System::sendmsg(m_helper.fd(), &msg, 0));
  546. return {};
  547. #else
  548. (void)fd;
  549. return Error::from_string_literal("File descriptor passing not supported on this platform");
  550. #endif
  551. }
  552. ErrorOr<pid_t> LocalSocket::peer_pid() const
  553. {
  554. #ifdef AK_OS_MACOS
  555. pid_t pid;
  556. socklen_t pid_size = sizeof(pid);
  557. #elif defined(AK_OS_FREEBSD)
  558. struct xucred creds = {};
  559. socklen_t creds_size = sizeof(creds);
  560. #elif defined(AK_OS_OPENBSD)
  561. struct sockpeercred creds = {};
  562. socklen_t creds_size = sizeof(creds);
  563. #else
  564. struct ucred creds = {};
  565. socklen_t creds_size = sizeof(creds);
  566. #endif
  567. #ifdef AK_OS_MACOS
  568. TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size));
  569. return pid;
  570. #elif defined(AK_OS_FREEBSD)
  571. TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERCRED, &creds, &creds_size));
  572. return creds.cr_pid;
  573. #else
  574. TRY(System::getsockopt(m_helper.fd(), SOL_SOCKET, SO_PEERCRED, &creds, &creds_size));
  575. return creds.pid;
  576. #endif
  577. }
  578. ErrorOr<Bytes> LocalSocket::read_without_waiting(Bytes buffer)
  579. {
  580. return m_helper.read(buffer, MSG_DONTWAIT);
  581. }
  582. Optional<int> LocalSocket::fd() const
  583. {
  584. if (!is_open())
  585. return {};
  586. return m_helper.fd();
  587. }
  588. ErrorOr<int> LocalSocket::release_fd()
  589. {
  590. if (!is_open()) {
  591. return Error::from_errno(ENOTCONN);
  592. }
  593. auto fd = m_helper.fd();
  594. m_helper.set_fd(-1);
  595. return fd;
  596. }
  597. WrappedAKInputStream::WrappedAKInputStream(NonnullOwnPtr<InputStream> stream)
  598. : m_stream(move(stream))
  599. {
  600. }
  601. ErrorOr<Bytes> WrappedAKInputStream::read(Bytes bytes)
  602. {
  603. auto bytes_read = m_stream->read(bytes);
  604. if (m_stream->has_any_error())
  605. return Error::from_string_literal("Underlying InputStream indicated an error");
  606. return bytes.slice(0, bytes_read);
  607. }
  608. ErrorOr<size_t> WrappedAKInputStream::write(ReadonlyBytes)
  609. {
  610. VERIFY_NOT_REACHED();
  611. }
  612. bool WrappedAKInputStream::is_eof() const
  613. {
  614. return m_stream->unreliable_eof();
  615. }
  616. bool WrappedAKInputStream::is_open() const
  617. {
  618. return true;
  619. }
  620. void WrappedAKInputStream::close()
  621. {
  622. }
  623. WrappedAKOutputStream::WrappedAKOutputStream(NonnullOwnPtr<OutputStream> stream)
  624. : m_stream(move(stream))
  625. {
  626. }
  627. ErrorOr<Bytes> WrappedAKOutputStream::read(Bytes)
  628. {
  629. VERIFY_NOT_REACHED();
  630. }
  631. ErrorOr<size_t> WrappedAKOutputStream::write(ReadonlyBytes bytes)
  632. {
  633. auto bytes_written = m_stream->write(bytes);
  634. if (m_stream->has_any_error())
  635. return Error::from_string_literal("Underlying OutputStream indicated an error");
  636. return bytes_written;
  637. }
  638. bool WrappedAKOutputStream::is_eof() const
  639. {
  640. VERIFY_NOT_REACHED();
  641. }
  642. bool WrappedAKOutputStream::is_open() const
  643. {
  644. return true;
  645. }
  646. void WrappedAKOutputStream::close()
  647. {
  648. }
  649. }