summaryrefslogtreecommitdiff
path: root/common/netd/libnetdutils/Syscalls.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/netd/libnetdutils/Syscalls.cpp')
-rw-r--r--common/netd/libnetdutils/Syscalls.cpp265
1 files changed, 0 insertions, 265 deletions
diff --git a/common/netd/libnetdutils/Syscalls.cpp b/common/netd/libnetdutils/Syscalls.cpp
deleted file mode 100644
index 7e1a2426..00000000
--- a/common/netd/libnetdutils/Syscalls.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "netdutils/Syscalls.h"
-
-#include <atomic>
-#include <type_traits>
-#include <utility>
-
-namespace android {
-namespace netdutils {
-namespace {
-
-// Retry syscall fn as long as it returns -1 with errno == EINTR
-template <typename FnT, typename... Params>
-typename std::invoke_result<FnT, Params...>::type syscallRetry(FnT fn, Params&&... params) {
- auto rv = fn(std::forward<Params>(params)...);
- while ((rv == -1) && (errno == EINTR)) {
- rv = fn(std::forward<Params>(params)...);
- }
- return rv;
-}
-
-} // namespace
-
-// Production implementation of Syscalls that forwards to libc syscalls.
-class RealSyscalls final : public Syscalls {
- public:
- ~RealSyscalls() override = default;
-
- StatusOr<UniqueFd> open(const std::string& pathname, int flags, mode_t mode) const override {
- UniqueFd fd(::open(pathname.c_str(), flags, mode));
- if (!isWellFormed(fd)) {
- return statusFromErrno(errno, "open(\"" + pathname + "\"...) failed");
- }
- return fd;
- }
-
- StatusOr<UniqueFd> socket(int domain, int type, int protocol) const override {
- UniqueFd sock(::socket(domain, type, protocol));
- if (!isWellFormed(sock)) {
- return statusFromErrno(errno, "socket() failed");
- }
- return sock;
- }
-
- Status getsockname(Fd sock, sockaddr* addr, socklen_t* addrlen) const override {
- auto rv = ::getsockname(sock.get(), addr, addrlen);
- if (rv == -1) {
- return statusFromErrno(errno, "getsockname() failed");
- }
- return status::ok;
- }
-
- Status getsockopt(Fd sock, int level, int optname, void* optval,
- socklen_t* optlen) const override {
- auto rv = ::getsockopt(sock.get(), level, optname, optval, optlen);
- if (rv == -1) {
- return statusFromErrno(errno, "getsockopt() failed");
- }
- return status::ok;
- }
-
- Status setsockopt(Fd sock, int level, int optname, const void* optval,
- socklen_t optlen) const override {
- auto rv = ::setsockopt(sock.get(), level, optname, optval, optlen);
- if (rv == -1) {
- return statusFromErrno(errno, "setsockopt() failed");
- }
- return status::ok;
- }
-
- Status bind(Fd sock, const sockaddr* addr, socklen_t addrlen) const override {
- auto rv = ::bind(sock.get(), addr, addrlen);
- if (rv == -1) {
- return statusFromErrno(errno, "bind() failed");
- }
- return status::ok;
- }
-
- Status connect(Fd sock, const sockaddr* addr, socklen_t addrlen) const override {
- auto rv = syscallRetry(::connect, sock.get(), addr, addrlen);
- if (rv == -1) {
- return statusFromErrno(errno, "connect() failed");
- }
- return status::ok;
- }
-
- StatusOr<ifreq> ioctl(Fd sock, unsigned long request, ifreq* ifr) const override {
- auto rv = ::ioctl(sock.get(), request, ifr);
- if (rv == -1) {
- return statusFromErrno(errno, "ioctl() failed");
- }
- return *ifr;
- }
-
- StatusOr<UniqueFd> eventfd(unsigned int initval, int flags) const override {
- UniqueFd fd(::eventfd(initval, flags));
- if (!isWellFormed(fd)) {
- return statusFromErrno(errno, "eventfd() failed");
- }
- return fd;
- }
-
- StatusOr<int> ppoll(pollfd* fds, nfds_t nfds, double timeout) const override {
- timespec ts = {};
- ts.tv_sec = timeout;
- ts.tv_nsec = (timeout - ts.tv_sec) * 1e9;
- auto rv = syscallRetry(::ppoll, fds, nfds, &ts, nullptr);
- if (rv == -1) {
- return statusFromErrno(errno, "ppoll() failed");
- }
- return rv;
- }
-
- StatusOr<size_t> writev(Fd fd, const std::vector<iovec>& iov) const override {
- auto rv = syscallRetry(::writev, fd.get(), iov.data(), iov.size());
- if (rv == -1) {
- return statusFromErrno(errno, "writev() failed");
- }
- return rv;
- }
-
- StatusOr<size_t> write(Fd fd, const Slice buf) const override {
- auto rv = syscallRetry(::write, fd.get(), buf.base(), buf.size());
- if (rv == -1) {
- return statusFromErrno(errno, "write() failed");
- }
- return static_cast<size_t>(rv);
- }
-
- StatusOr<Slice> read(Fd fd, const Slice buf) const override {
- auto rv = syscallRetry(::read, fd.get(), buf.base(), buf.size());
- if (rv == -1) {
- return statusFromErrno(errno, "read() failed");
- }
- return Slice(buf.base(), rv);
- }
-
- StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const sockaddr* dst,
- socklen_t dstlen) const override {
- auto rv = syscallRetry(::sendto, sock.get(), buf.base(), buf.size(), flags, dst, dstlen);
- if (rv == -1) {
- return statusFromErrno(errno, "sendto() failed");
- }
- return static_cast<size_t>(rv);
- }
-
- StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags, sockaddr* src,
- socklen_t* srclen) const override {
- auto rv = syscallRetry(::recvfrom, sock.get(), dst.base(), dst.size(), flags, src, srclen);
- if (rv == -1) {
- return statusFromErrno(errno, "recvfrom() failed");
- }
- if (rv == 0) {
- return status::eof;
- }
- return take(dst, rv);
- }
-
- Status shutdown(Fd fd, int how) const override {
- auto rv = ::shutdown(fd.get(), how);
- if (rv == -1) {
- return statusFromErrno(errno, "shutdown() failed");
- }
- return status::ok;
- }
-
- Status close(Fd fd) const override {
- auto rv = ::close(fd.get());
- if (rv == -1) {
- return statusFromErrno(errno, "close() failed");
- }
- return status::ok;
- }
-
- StatusOr<UniqueFile> fopen(const std::string& path, const std::string& mode) const override {
- UniqueFile file(::fopen(path.c_str(), mode.c_str()));
- if (file == nullptr) {
- return statusFromErrno(errno, "fopen(\"" + path + "\", \"" + mode + "\") failed");
- }
- return file;
- }
-
- StatusOr<pid_t> fork() const override {
- pid_t rv = ::fork();
- if (rv == -1) {
- return statusFromErrno(errno, "fork() failed");
- }
- return rv;
- }
-
- StatusOr<int> vfprintf(FILE* file, const char* format, va_list ap) const override {
- auto rv = ::vfprintf(file, format, ap);
- if (rv == -1) {
- return statusFromErrno(errno, "vfprintf() failed");
- }
- return rv;
- }
-
- StatusOr<int> vfscanf(FILE* file, const char* format, va_list ap) const override {
- auto rv = ::vfscanf(file, format, ap);
- if (rv == -1) {
- return statusFromErrno(errno, "vfscanf() failed");
- }
- return rv;
- }
-
- Status fclose(FILE* file) const override {
- auto rv = ::fclose(file);
- if (rv == -1) {
- return statusFromErrno(errno, "fclose() failed");
- }
- return status::ok;
- }
-};
-
-SyscallsHolder::~SyscallsHolder() {
- delete &get();
-}
-
-Syscalls& SyscallsHolder::get() {
- while (true) {
- // memory_order_relaxed gives the compiler and hardware more
- // freedom. If we get a stale value (this should only happen
- // early in the execution of a program) the exchange code below
- // will loop until we get the most current value.
- auto* syscalls = mSyscalls.load(std::memory_order_relaxed);
- // Common case returns existing syscalls
- if (syscalls) {
- return *syscalls;
- }
-
- // This code will execute on first get()
- std::unique_ptr<Syscalls> tmp(new RealSyscalls());
- Syscalls* expected = nullptr;
- bool success = mSyscalls.compare_exchange_strong(expected, tmp.get());
- if (success) {
- // Ownership was transferred to mSyscalls already, must release()
- return *tmp.release();
- }
- }
-}
-
-Syscalls& SyscallsHolder::swap(Syscalls& syscalls) {
- return *mSyscalls.exchange(&syscalls);
-}
-
-SyscallsHolder sSyscalls;
-
-} // namespace netdutils
-} // namespace android