diff --git a/adb/Android.bp b/adb/Android.bp index 87e4adc82..114eb2ab0 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -26,6 +26,7 @@ cc_defaults { "-Wvla", "-DADB_HOST=1", // overridden by adbd_defaults "-DALLOW_ADBD_ROOT=0", // overridden by adbd_defaults + "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION=1", ], cpp_std: "experimental", diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp index f5cdcb558..bdb8efa5c 100644 --- a/adb/adb_io.cpp +++ b/adb/adb_io.cpp @@ -34,7 +34,7 @@ #include "adb_utils.h" #include "sysdeps.h" -bool SendProtocolString(int fd, std::string_view s) { +bool SendProtocolString(borrowed_fd fd, std::string_view s) { unsigned int length = s.size(); if (length > MAX_PAYLOAD - 4) { errno = EMSGSIZE; @@ -47,7 +47,7 @@ bool SendProtocolString(int fd, std::string_view s) { return WriteFdExactly(fd, str); } -bool ReadProtocolString(int fd, std::string* s, std::string* error) { +bool ReadProtocolString(borrowed_fd fd, std::string* s, std::string* error) { char buf[5]; if (!ReadFdExactly(fd, buf, 4)) { *error = perror_str("protocol fault (couldn't read status length)"); @@ -65,57 +65,57 @@ bool ReadProtocolString(int fd, std::string* s, std::string* error) { return true; } -bool SendOkay(int fd) { +bool SendOkay(borrowed_fd fd) { return WriteFdExactly(fd, "OKAY", 4); } -bool SendFail(int fd, std::string_view reason) { +bool SendFail(borrowed_fd fd, std::string_view reason) { return WriteFdExactly(fd, "FAIL", 4) && SendProtocolString(fd, reason); } -bool ReadFdExactly(int fd, void* buf, size_t len) { +bool ReadFdExactly(borrowed_fd fd, void* buf, size_t len) { char* p = reinterpret_cast(buf); size_t len0 = len; - D("readx: fd=%d wanted=%zu", fd, len); + D("readx: fd=%d wanted=%zu", fd.get(), len); while (len > 0) { int r = adb_read(fd, p, len); if (r > 0) { len -= r; p += r; } else if (r == -1) { - D("readx: fd=%d error %d: %s", fd, errno, strerror(errno)); + D("readx: fd=%d error %d: %s", fd.get(), errno, strerror(errno)); return false; } else { - D("readx: fd=%d disconnected", fd); + D("readx: fd=%d disconnected", fd.get()); errno = 0; return false; } } - VLOG(RWX) << "readx: fd=" << fd << " wanted=" << len0 << " got=" << (len0 - len) - << " " << dump_hex(reinterpret_cast(buf), len0); + VLOG(RWX) << "readx: fd=" << fd.get() << " wanted=" << len0 << " got=" << (len0 - len) << " " + << dump_hex(reinterpret_cast(buf), len0); return true; } -bool WriteFdExactly(int fd, const void* buf, size_t len) { +bool WriteFdExactly(borrowed_fd fd, const void* buf, size_t len) { const char* p = reinterpret_cast(buf); int r; - VLOG(RWX) << "writex: fd=" << fd << " len=" << len - << " " << dump_hex(reinterpret_cast(buf), len); + VLOG(RWX) << "writex: fd=" << fd.get() << " len=" << len << " " + << dump_hex(reinterpret_cast(buf), len); while (len > 0) { r = adb_write(fd, p, len); if (r == -1) { - D("writex: fd=%d error %d: %s", fd, errno, strerror(errno)); + D("writex: fd=%d error %d: %s", fd.get(), errno, strerror(errno)); if (errno == EAGAIN) { std::this_thread::yield(); continue; } else if (errno == EPIPE) { - D("writex: fd=%d disconnected", fd); + D("writex: fd=%d disconnected", fd.get()); errno = 0; return false; } else { @@ -129,15 +129,15 @@ bool WriteFdExactly(int fd, const void* buf, size_t len) { return true; } -bool WriteFdExactly(int fd, const char* str) { +bool WriteFdExactly(borrowed_fd fd, const char* str) { return WriteFdExactly(fd, str, strlen(str)); } -bool WriteFdExactly(int fd, const std::string& str) { +bool WriteFdExactly(borrowed_fd fd, const std::string& str) { return WriteFdExactly(fd, str.c_str(), str.size()); } -bool WriteFdFmt(int fd, const char* fmt, ...) { +bool WriteFdFmt(borrowed_fd fd, const char* fmt, ...) { std::string str; va_list ap; @@ -148,7 +148,7 @@ bool WriteFdFmt(int fd, const char* fmt, ...) { return WriteFdExactly(fd, str); } -bool ReadOrderlyShutdown(int fd) { +bool ReadOrderlyShutdown(borrowed_fd fd) { char buf[16]; // Only call this function if you're sure that the peer does @@ -178,7 +178,7 @@ bool ReadOrderlyShutdown(int fd) { // data. We don't repeatedly call adb_read() until we get zero because // we don't know how long that would take, but we do know that the // caller wants to close the socket soon. - VLOG(RWX) << "ReadOrderlyShutdown(" << fd << ") unexpectedly read " + VLOG(RWX) << "ReadOrderlyShutdown(" << fd.get() << ") unexpectedly read " << dump_hex(buf, result); // Shutdown the socket to prevent the caller from reading or writing to // it which doesn't make sense if we just read and discarded some data. diff --git a/adb/adb_io.h b/adb/adb_io.h index d6e65d8de..962894610 100644 --- a/adb/adb_io.h +++ b/adb/adb_io.h @@ -25,16 +25,16 @@ #include "adb_unique_fd.h" // Sends the protocol "OKAY" message. -bool SendOkay(int fd); +bool SendOkay(borrowed_fd fd); // Sends the protocol "FAIL" message, with the given failure reason. -bool SendFail(int fd, std::string_view reason); +bool SendFail(borrowed_fd fd, std::string_view reason); // Writes a protocol-format string; a four hex digit length followed by the string data. -bool SendProtocolString(int fd, std::string_view s); +bool SendProtocolString(borrowed_fd fd, std::string_view s); // Reads a protocol-format string; a four hex digit length followed by the string data. -bool ReadProtocolString(int fd, std::string* s, std::string* error); +bool ReadProtocolString(borrowed_fd fd, std::string* s, std::string* error); // Reads exactly len bytes from fd into buf. // @@ -42,7 +42,7 @@ bool ReadProtocolString(int fd, std::string* s, std::string* error); // were read. If EOF was found, errno will be set to 0. // // If this function fails, the contents of buf are undefined. -bool ReadFdExactly(int fd, void* buf, size_t len); +bool ReadFdExactly(borrowed_fd fd, void* buf, size_t len); // Given a client socket, wait for orderly/graceful shutdown. Call this: // @@ -60,19 +60,19 @@ bool ReadFdExactly(int fd, void* buf, size_t len); // connect()s from the client to fail with WSAEADDRINUSE on Windows. // Returns true if it is sure that orderly/graceful shutdown has occurred with // no additional data read from the server. -bool ReadOrderlyShutdown(int fd); +bool ReadOrderlyShutdown(borrowed_fd fd); // Writes exactly len bytes from buf to fd. // // Returns false if there is an error or if the fd was closed before the write // completed. If the other end of the fd (such as in a socket, pipe, or fifo), // is closed, errno will be set to 0. -bool WriteFdExactly(int fd, const void* buf, size_t len); +bool WriteFdExactly(borrowed_fd fd, const void* buf, size_t len); // Same as above, but for strings. -bool WriteFdExactly(int fd, const char* s); -bool WriteFdExactly(int fd, const std::string& s); +bool WriteFdExactly(borrowed_fd fd, const char* s); +bool WriteFdExactly(borrowed_fd fd, const std::string& s); // Same as above, but formats the string to send. -bool WriteFdFmt(int fd, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))); +bool WriteFdFmt(borrowed_fd fd, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))); #endif /* ADB_IO_H */ diff --git a/adb/adb_unique_fd.h b/adb/adb_unique_fd.h index d47213d75..b6c910a94 100644 --- a/adb/adb_unique_fd.h +++ b/adb/adb_unique_fd.h @@ -32,6 +32,8 @@ using unique_fd = android::base::unique_fd_impl; using unique_fd = android::base::unique_fd; #endif +using android::base::borrowed_fd; + template int adb_close(const android::base::unique_fd_impl&) __attribute__((__unavailable__("adb_close called on unique_fd"))); diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp index 9791769a4..cf5fbc88d 100644 --- a/adb/adb_utils.cpp +++ b/adb/adb_utils.cpp @@ -234,15 +234,15 @@ std::string perror_str(const char* msg) { #if !defined(_WIN32) // Windows version provided in sysdeps_win32.cpp -bool set_file_block_mode(int fd, bool block) { - int flags = fcntl(fd, F_GETFL, 0); +bool set_file_block_mode(borrowed_fd fd, bool block) { + int flags = fcntl(fd.get(), F_GETFL, 0); if (flags == -1) { - PLOG(ERROR) << "failed to fcntl(F_GETFL) for fd " << fd; + PLOG(ERROR) << "failed to fcntl(F_GETFL) for fd " << fd.get(); return false; } flags = block ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); - if (fcntl(fd, F_SETFL, flags) != 0) { - PLOG(ERROR) << "failed to fcntl(F_SETFL) for fd " << fd << ", flags " << flags; + if (fcntl(fd.get(), F_SETFL, flags) != 0) { + PLOG(ERROR) << "failed to fcntl(F_SETFL) for fd " << fd.get() << ", flags " << flags; return false; } return true; diff --git a/adb/adb_utils.h b/adb/adb_utils.h index 8b0dcee83..faad03d07 100644 --- a/adb/adb_utils.h +++ b/adb/adb_utils.h @@ -26,6 +26,7 @@ #include #include "adb.h" +#include "adb_unique_fd.h" void close_stdin(); @@ -51,7 +52,7 @@ std::string perror_str(const char* msg); [[noreturn]] void error_exit(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2))); [[noreturn]] void perror_exit(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2))); -bool set_file_block_mode(int fd, bool block); +bool set_file_block_mode(borrowed_fd fd, bool block); // Given forward/reverse targets, returns true if they look sane. If an error is found, fills // |error| and returns false. diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp index bd676c2de..cdca3aa32 100644 --- a/adb/adb_utils_test.cpp +++ b/adb/adb_utils_test.cpp @@ -149,13 +149,13 @@ TEST(adb_utils, mkdirs) { TEST(adb_utils, set_file_block_mode) { unique_fd fd(adb_open("/dev/null", O_RDWR | O_APPEND)); ASSERT_GE(fd, 0); - int flags = fcntl(fd, F_GETFL, 0); + int flags = fcntl(fd.get(), F_GETFL, 0); ASSERT_EQ(O_RDWR | O_APPEND, (flags & (O_RDWR | O_APPEND))); ASSERT_TRUE(set_file_block_mode(fd, false)); - int new_flags = fcntl(fd, F_GETFL, 0); + int new_flags = fcntl(fd.get(), F_GETFL, 0); ASSERT_EQ(flags | O_NONBLOCK, new_flags); ASSERT_TRUE(set_file_block_mode(fd, true)); - new_flags = fcntl(fd, F_GETFL, 0); + new_flags = fcntl(fd.get(), F_GETFL, 0); ASSERT_EQ(flags, new_flags); } #endif diff --git a/adb/client/adb_client.cpp b/adb/client/adb_client.cpp index 5a7bc8d66..7e408a87a 100644 --- a/adb/client/adb_client.cpp +++ b/adb/client/adb_client.cpp @@ -128,7 +128,7 @@ static std::optional switch_socket_transport(int fd, std::string* e return result; } -bool adb_status(int fd, std::string* error) { +bool adb_status(borrowed_fd fd, std::string* error) { char buf[5]; if (!ReadFdExactly(fd, buf, 4)) { *error = perror_str("protocol fault (couldn't read status)"); diff --git a/adb/client/adb_client.h b/adb/client/adb_client.h index 8d32c93b4..fe1e584a5 100644 --- a/adb/client/adb_client.h +++ b/adb/client/adb_client.h @@ -16,13 +16,14 @@ #pragma once -#include "adb.h" -#include "sysdeps.h" -#include "transport.h" - #include #include +#include "adb.h" +#include "adb_unique_fd.h" +#include "sysdeps.h" +#include "transport.h" + // Explicitly check the adb server version. // All of the commands below do this implicitly. // Only the first invocation of this function will check the server version. @@ -64,7 +65,7 @@ int adb_send_emulator_command(int argc, const char* _Nonnull* _Nonnull argv, // Reads a standard adb status response (OKAY|FAIL) and returns true in the // event of OKAY, false in the event of FAIL or protocol error. -bool adb_status(int fd, std::string* _Nonnull error); +bool adb_status(borrowed_fd fd, std::string* _Nonnull error); // Create a host command corresponding to selected transport type/serial. std::string format_host_command(const char* _Nonnull command); diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp index f39aa5880..0e0a76bb2 100644 --- a/adb/client/commandline.cpp +++ b/adb/client/commandline.cpp @@ -262,7 +262,7 @@ static void stdin_raw_restore() { // stdout/stderr are routed independently and the remote exit code will be // returned. // if |callback| is non-null, stdout/stderr output will be handled by it. -int read_and_dump(int fd, bool use_shell_protocol = false, +int read_and_dump(borrowed_fd fd, bool use_shell_protocol = false, StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK) { int exit_code = 0; if (fd < 0) return exit_code; @@ -305,9 +305,9 @@ int read_and_dump(int fd, bool use_shell_protocol = false, } length = protocol->data_length(); } else { - D("read_and_dump(): pre adb_read(fd=%d)", fd); + D("read_and_dump(): pre adb_read(fd=%d)", fd.get()); length = adb_read(fd, raw_buffer, sizeof(raw_buffer)); - D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length); + D("read_and_dump(): post adb_read(fd=%d): length=%d", fd.get(), length); if (length <= 0) { break; } @@ -887,7 +887,7 @@ static int adb_sideload_install(const char* filename, bool rescue_mode) { return -1; } fprintf(stderr, "adb: trying pre-KitKat sideload method...\n"); - return adb_sideload_legacy(filename, package_fd, static_cast(sb.st_size)); + return adb_sideload_legacy(filename, package_fd.get(), static_cast(sb.st_size)); } int opt = SIDELOAD_HOST_BLOCK_SIZE; @@ -1207,14 +1207,14 @@ static int logcat(int argc, const char** argv) { return send_shell_command(cmd); } -static void write_zeros(int bytes, int fd) { +static void write_zeros(int bytes, borrowed_fd fd) { int old_stdin_mode = -1; int old_stdout_mode = -1; std::vector buf(bytes); - D("write_zeros(%d) -> %d", bytes, fd); + D("write_zeros(%d) -> %d", bytes, fd.get()); - stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode); + stdinout_raw_prologue(-1, fd.get(), old_stdin_mode, old_stdout_mode); if (fd == STDOUT_FILENO) { fwrite(buf.data(), 1, bytes, stdout); @@ -1223,7 +1223,7 @@ static void write_zeros(int bytes, int fd) { adb_write(fd, buf.data(), bytes); } - stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode); + stdinout_raw_prologue(-1, fd.get(), old_stdin_mode, old_stdout_mode); D("write_zeros() finished"); } diff --git a/adb/daemon/abb.cpp b/adb/daemon/abb.cpp index aa75bb193..425438eb2 100644 --- a/adb/daemon/abb.cpp +++ b/adb/daemon/abb.cpp @@ -29,11 +29,11 @@ namespace { class AdbFdTextOutput : public android::TextOutput { public: - explicit AdbFdTextOutput(int fd) : mFD(fd) {} + explicit AdbFdTextOutput(borrowed_fd fd) : fd_(fd) {} private: android::status_t print(const char* txt, size_t len) override { - return WriteFdExactly(mFD, txt, len) ? android::OK : -errno; + return WriteFdExactly(fd_, txt, len) ? android::OK : -errno; } void moveIndent(int delta) override { /*not implemented*/ } @@ -44,7 +44,7 @@ class AdbFdTextOutput : public android::TextOutput { } private: - int mFD; + borrowed_fd fd_; }; std::vector parseCmdArgs(std::string_view args) { @@ -68,10 +68,11 @@ std::vector parseCmdArgs(std::string_view args) { } // namespace -static int execCmd(std::string_view args, int in, int out, int err) { +static int execCmd(std::string_view args, borrowed_fd in, borrowed_fd out, borrowed_fd err) { AdbFdTextOutput oin(out); AdbFdTextOutput oerr(err); - return cmdMain(parseCmdArgs(args), oin, oerr, in, out, err, RunMode::kLibrary); + return cmdMain(parseCmdArgs(args), oin, oerr, in.get(), out.get(), err.get(), + RunMode::kLibrary); } int main(int argc, char* const argv[]) { diff --git a/adb/daemon/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp index 66bfc0d81..cd9b669f6 100644 --- a/adb/daemon/jdwp_service.cpp +++ b/adb/daemon/jdwp_service.cpp @@ -325,12 +325,12 @@ static int jdwp_control_init(JdwpControl* control, const char* sockname, int soc addrlen = pathlen + sizeof(addr.sun_family); - if (bind(s, reinterpret_cast(&addr), addrlen) < 0) { + if (bind(s.get(), reinterpret_cast(&addr), addrlen) < 0) { D("could not bind vm debug control socket: %d: %s", errno, strerror(errno)); return -1; } - if (listen(s, 4) < 0) { + if (listen(s.get(), 4) < 0) { D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno)); return -1; } diff --git a/adb/daemon/reboot_service.cpp b/adb/daemon/reboot_service.cpp index a5a11b866..13398af46 100644 --- a/adb/daemon/reboot_service.cpp +++ b/adb/daemon/reboot_service.cpp @@ -58,7 +58,7 @@ void reboot_service(unique_fd fd, const std::string& arg) { sockaddr_un addr = {.sun_family = AF_UNIX}; strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1); - if (connect(sock, reinterpret_cast(&addr), sizeof(addr)) == -1) { + if (connect(sock.get(), reinterpret_cast(&addr), sizeof(addr)) == -1) { WriteFdFmt(fd, "reboot (%s) connect\n", strerror(errno)); PLOG(ERROR) << "Couldn't connect to recovery socket"; return; diff --git a/adb/daemon/set_verity_enable_state_service.cpp b/adb/daemon/set_verity_enable_state_service.cpp index 49dce660b..4fbccdbd5 100644 --- a/adb/daemon/set_verity_enable_state_service.cpp +++ b/adb/daemon/set_verity_enable_state_service.cpp @@ -58,7 +58,7 @@ static bool make_block_device_writable(const std::string& dev) { } int OFF = 0; - bool result = (ioctl(fd, BLKROSET, &OFF) != -1); + bool result = (ioctl(fd.get(), BLKROSET, &OFF) != -1); return result; } @@ -197,7 +197,7 @@ void set_verity_enabled_state_service(unique_fd fd, bool enable) { } if (!android::base::GetBoolProperty("ro.secure", false)) { - overlayfs_setup(fd, enable); + overlayfs_setup(fd.get(), enable); WriteFdExactly(fd.get(), "verity not enabled - ENG build\n"); return; } @@ -242,7 +242,7 @@ void set_verity_enabled_state_service(unique_fd fd, bool enable) { } } } - if (!any_changed) any_changed = overlayfs_setup(fd, enable); + if (!any_changed) any_changed = overlayfs_setup(fd.get(), enable); if (any_changed) { WriteFdExactly(fd.get(), "Now reboot your device for settings to take effect\n"); diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp index 3c8f3939f..de97068cb 100644 --- a/adb/daemon/shell_service.cpp +++ b/adb/daemon/shell_service.cpp @@ -114,7 +114,7 @@ namespace { // Reads from |fd| until close or failure. -std::string ReadAll(int fd) { +std::string ReadAll(borrowed_fd fd) { char buffer[512]; std::string received; @@ -317,9 +317,10 @@ bool Subprocess::ForkAndExec(std::string* error) { child_stdinout_sfd.reset(OpenPtyChildFd(pts_name, &child_error_sfd)); } - dup2(child_stdinout_sfd, STDIN_FILENO); - dup2(child_stdinout_sfd, STDOUT_FILENO); - dup2(child_stderr_sfd != -1 ? child_stderr_sfd : child_stdinout_sfd, STDERR_FILENO); + dup2(child_stdinout_sfd.get(), STDIN_FILENO); + dup2(child_stdinout_sfd.get(), STDOUT_FILENO); + dup2(child_stderr_sfd != -1 ? child_stderr_sfd.get() : child_stdinout_sfd.get(), + STDERR_FILENO); // exec doesn't trigger destructors, close the FDs manually. stdinout_sfd_.reset(-1); @@ -415,7 +416,7 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) { } } else { // Raw protocol doesn't support multiple output streams, so combine stdout and stderr. - child_stderr_sfd.reset(dup(child_stdinout_sfd)); + child_stderr_sfd.reset(dup(child_stdinout_sfd.get())); } D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(), @@ -537,7 +538,7 @@ void Subprocess::PassDataStreams() { FD_ZERO(&master_write_set); for (unique_fd* sfd : {&protocol_sfd_, &stdinout_sfd_, &stderr_sfd_}) { if (*sfd != -1) { - FD_SET(*sfd, &master_read_set); + FD_SET(sfd->get(), &master_read_set); } } @@ -547,8 +548,8 @@ void Subprocess::PassDataStreams() { unique_fd* dead_sfd = SelectLoop(&master_read_set, &master_write_set); if (dead_sfd) { D("closing FD %d", dead_sfd->get()); - FD_CLR(*dead_sfd, &master_read_set); - FD_CLR(*dead_sfd, &master_write_set); + FD_CLR(dead_sfd->get(), &master_read_set); + FD_CLR(dead_sfd->get(), &master_write_set); if (dead_sfd == &protocol_sfd_) { // Using SIGHUP is a decent general way to indicate that the // controlling process is going away. If specific signals are @@ -573,7 +574,7 @@ void Subprocess::PassDataStreams() { namespace { inline bool ValidAndInSet(const unique_fd& sfd, fd_set* set) { - return sfd != -1 && FD_ISSET(sfd, set); + return sfd != -1 && FD_ISSET(sfd.get(), set); } } // namespace @@ -581,7 +582,8 @@ inline bool ValidAndInSet(const unique_fd& sfd, fd_set* set) { unique_fd* Subprocess::SelectLoop(fd_set* master_read_set_ptr, fd_set* master_write_set_ptr) { fd_set read_set, write_set; - int select_n = std::max(std::max(protocol_sfd_, stdinout_sfd_), stderr_sfd_) + 1; + int select_n = + std::max(std::max(protocol_sfd_.get(), stdinout_sfd_.get()), stderr_sfd_.get()) + 1; unique_fd* dead_sfd = nullptr; // Keep calling select() and passing data until an FD closes/errors. @@ -614,8 +616,8 @@ unique_fd* Subprocess::SelectLoop(fd_set* master_read_set_ptr, dead_sfd = PassInput(); // If we didn't finish writing, block on stdin write. if (input_bytes_left_) { - FD_CLR(protocol_sfd_, master_read_set_ptr); - FD_SET(stdinout_sfd_, master_write_set_ptr); + FD_CLR(protocol_sfd_.get(), master_read_set_ptr); + FD_SET(stdinout_sfd_.get(), master_write_set_ptr); } } @@ -624,8 +626,8 @@ unique_fd* Subprocess::SelectLoop(fd_set* master_read_set_ptr, dead_sfd = PassInput(); // If we finished writing, go back to blocking on protocol read. if (!input_bytes_left_) { - FD_SET(protocol_sfd_, master_read_set_ptr); - FD_CLR(stdinout_sfd_, master_write_set_ptr); + FD_SET(protocol_sfd_.get(), master_read_set_ptr); + FD_CLR(stdinout_sfd_.get(), master_write_set_ptr); } } } // while (!dead_sfd) @@ -639,7 +641,7 @@ unique_fd* Subprocess::PassInput() { if (!input_->Read()) { // Read() uses ReadFdExactly() which sets errno to 0 on EOF. if (errno != 0) { - PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_; + PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_.get(); } return &protocol_sfd_; } @@ -655,7 +657,7 @@ unique_fd* Subprocess::PassInput() { ws.ws_col = cols; ws.ws_xpixel = x_pixels; ws.ws_ypixel = y_pixels; - ioctl(stdinout_sfd_, TIOCSWINSZ, &ws); + ioctl(stdinout_sfd_.get(), TIOCSWINSZ, &ws); } break; case ShellProtocol::kIdStdin: @@ -666,8 +668,7 @@ unique_fd* Subprocess::PassInput() { if (adb_shutdown(stdinout_sfd_, SHUT_WR) == 0) { return nullptr; } - PLOG(ERROR) << "failed to shutdown writes to FD " - << stdinout_sfd_; + PLOG(ERROR) << "failed to shutdown writes to FD " << stdinout_sfd_.get(); return &stdinout_sfd_; } else { // PTYs can't close just input, so rather than close the @@ -688,7 +689,7 @@ unique_fd* Subprocess::PassInput() { int bytes = adb_write(stdinout_sfd_, input_->data() + index, input_bytes_left_); if (bytes == 0 || (bytes < 0 && errno != EAGAIN)) { if (bytes < 0) { - PLOG(ERROR) << "error reading stdin FD " << stdinout_sfd_; + PLOG(ERROR) << "error reading stdin FD " << stdinout_sfd_.get(); } // stdin is done, mark this packet as finished and we'll just start // dumping any further data received from the protocol FD. @@ -708,14 +709,14 @@ unique_fd* Subprocess::PassOutput(unique_fd* sfd, ShellProtocol::Id id) { // read() returns EIO if a PTY closes; don't report this as an error, // it just means the subprocess completed. if (bytes < 0 && !(type_ == SubprocessType::kPty && errno == EIO)) { - PLOG(ERROR) << "error reading output FD " << *sfd; + PLOG(ERROR) << "error reading output FD " << sfd->get(); } return sfd; } if (bytes > 0 && !output_->Write(id, bytes)) { if (errno != 0) { - PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_; + PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_.get(); } return &protocol_sfd_; } diff --git a/adb/daemon/shell_service.h b/adb/daemon/shell_service.h index 3abd95807..030228c7f 100644 --- a/adb/daemon/shell_service.h +++ b/adb/daemon/shell_service.h @@ -48,7 +48,7 @@ unique_fd StartSubprocess(std::string name, const char* terminal_type, Subproces // Sets up in/out and error streams to emulate shell-like behavior. // // Returns an open FD connected to the thread or -1 on failure. -using Command = int(std::string_view args, int in, int out, int err); +using Command = int(std::string_view args, borrowed_fd in, borrowed_fd out, borrowed_fd err); unique_fd StartCommandInProcess(std::string name, Command command, SubprocessProtocol protocol); // Create a pipe containing the error. diff --git a/adb/daemon/shell_service_test.cpp b/adb/daemon/shell_service_test.cpp index dc79d1213..cdd8dbede 100644 --- a/adb/daemon/shell_service_test.cpp +++ b/adb/daemon/shell_service_test.cpp @@ -77,7 +77,7 @@ void ShellServiceTest::StartTestCommandInProcess(std::string name, Command comma namespace { // Reads raw data from |fd| until it closes or errors. -std::string ReadRaw(int fd) { +std::string ReadRaw(borrowed_fd fd) { char buffer[1024]; char *cur_ptr = buffer, *end_ptr = buffer + sizeof(buffer); @@ -93,12 +93,12 @@ std::string ReadRaw(int fd) { // Reads shell protocol data from |fd| until it closes or errors. Fills // |stdout| and |stderr| with their respective data, and returns the exit code // read from the protocol or -1 if an exit code packet was not received. -int ReadShellProtocol(int fd, std::string* stdout, std::string* stderr) { +int ReadShellProtocol(borrowed_fd fd, std::string* stdout, std::string* stderr) { int exit_code = -1; stdout->clear(); stderr->clear(); - auto protocol = std::make_unique(fd); + auto protocol = std::make_unique(fd.get()); while (protocol->Read()) { switch (protocol->id()) { case ShellProtocol::kIdStdout: diff --git a/adb/shell_protocol.h b/adb/shell_protocol.h index 2c8268901..4aab8131c 100644 --- a/adb/shell_protocol.h +++ b/adb/shell_protocol.h @@ -21,6 +21,7 @@ #include #include "adb.h" +#include "adb_unique_fd.h" // Class to send and receive shell protocol packets. // @@ -60,7 +61,7 @@ class ShellProtocol { // should be dynamically allocated on the heap instead. // // |fd| is an open file descriptor to be used to send or receive packets. - explicit ShellProtocol(int fd); + explicit ShellProtocol(borrowed_fd fd); virtual ~ShellProtocol(); // Returns a pointer to the data buffer. @@ -103,7 +104,7 @@ class ShellProtocol { kHeaderSize = sizeof(Id) + sizeof(length_t) }; - int fd_; + borrowed_fd fd_; char buffer_[kBufferSize]; size_t data_length_ = 0, bytes_left_ = 0; diff --git a/adb/shell_service_protocol.cpp b/adb/shell_service_protocol.cpp index 13b66ec31..95afaffe7 100644 --- a/adb/shell_service_protocol.cpp +++ b/adb/shell_service_protocol.cpp @@ -22,7 +22,7 @@ #include "adb_io.h" -ShellProtocol::ShellProtocol(int fd) : fd_(fd) { +ShellProtocol::ShellProtocol(borrowed_fd fd) : fd_(fd) { buffer_[0] = kIdInvalid; } diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp index de4fff98d..1333724fc 100644 --- a/adb/socket_spec.cpp +++ b/adb/socket_spec.cpp @@ -314,14 +314,14 @@ int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_ addr.svm_port = port == 0 ? VMADDR_PORT_ANY : port; addr.svm_cid = VMADDR_CID_ANY; socklen_t addr_len = sizeof(addr); - if (bind(serverfd, reinterpret_cast(&addr), addr_len)) { + if (bind(serverfd.get(), reinterpret_cast(&addr), addr_len)) { return -1; } - if (listen(serverfd, 4)) { + if (listen(serverfd.get(), 4)) { return -1; } if (serverfd >= 0 && resolved_port) { - if (getsockname(serverfd, reinterpret_cast(&addr), &addr_len) == 0) { + if (getsockname(serverfd.get(), reinterpret_cast(&addr), &addr_len) == 0) { *resolved_port = addr.svm_port; } else { return -1; diff --git a/adb/sysdeps.h b/adb/sysdeps.h index 15247e722..78abba54a 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -36,6 +36,7 @@ #include #include +#include "adb_unique_fd.h" #include "sysdeps/errno.h" #include "sysdeps/network.h" #include "sysdeps/stat.h" @@ -76,42 +77,40 @@ static __inline__ bool adb_is_separator(char c) { extern int adb_thread_setname(const std::string& name); -static __inline__ void close_on_exec(int fd) -{ +static __inline__ void close_on_exec(borrowed_fd fd) { /* nothing really */ } -extern int adb_unlink(const char* path); -#undef unlink -#define unlink ___xxx_unlink +extern int adb_unlink(const char* path); +#undef unlink +#define unlink ___xxx_unlink extern int adb_mkdir(const std::string& path, int mode); -#undef mkdir -#define mkdir ___xxx_mkdir +#undef mkdir +#define mkdir ___xxx_mkdir // See the comments for the !defined(_WIN32) versions of adb_*(). extern int adb_open(const char* path, int options); extern int adb_creat(const char* path, int mode); -extern int adb_read(int fd, void* buf, int len); -extern int adb_write(int fd, const void* buf, int len); -extern int64_t adb_lseek(int fd, int64_t pos, int where); -extern int adb_shutdown(int fd, int direction = SHUT_RDWR); +extern int adb_read(borrowed_fd fd, void* buf, int len); +extern int adb_write(borrowed_fd fd, const void* buf, int len); +extern int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where); +extern int adb_shutdown(borrowed_fd fd, int direction = SHUT_RDWR); extern int adb_close(int fd); extern int adb_register_socket(SOCKET s); // See the comments for the !defined(_WIN32) version of unix_close(). -static __inline__ int unix_close(int fd) -{ +static __inline__ int unix_close(int fd) { return close(fd); } -#undef close -#define close ____xxx_close +#undef close +#define close ____xxx_close // Like unix_read(), but may return EINTR. -extern int unix_read_interruptible(int fd, void* buf, size_t len); +extern int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len); // See the comments for the !defined(_WIN32) version of unix_read(). -static __inline__ int unix_read(int fd, void* buf, size_t len) { +static __inline__ int unix_read(borrowed_fd fd, void* buf, size_t len) { return TEMP_FAILURE_RETRY(unix_read_interruptible(fd, buf, len)); } @@ -119,23 +118,21 @@ static __inline__ int unix_read(int fd, void* buf, size_t len) { #define read ___xxx_read // See the comments for the !defined(_WIN32) version of unix_write(). -static __inline__ int unix_write(int fd, const void* buf, size_t len) -{ - return write(fd, buf, len); +static __inline__ int unix_write(borrowed_fd fd, const void* buf, size_t len) { + return write(fd.get(), buf, len); } #undef write #define write ___xxx_write // See the comments for the !defined(_WIN32) version of unix_lseek(). -static __inline__ int unix_lseek(int fd, int pos, int where) { - return lseek(fd, pos, where); +static __inline__ int unix_lseek(borrowed_fd fd, int pos, int where) { + return lseek(fd.get(), pos, where); } #undef lseek #define lseek ___xxx_lseek // See the comments for the !defined(_WIN32) version of adb_open_mode(). -static __inline__ int adb_open_mode(const char* path, int options, int mode) -{ +static __inline__ int adb_open_mode(const char* path, int options, int mode) { return adb_open(path, options); } @@ -152,7 +149,7 @@ extern int unix_open(std::string_view path, int options, ...); // with |fd| must have GENERIC_READ access (which console FDs have by default). // Returns 1 if |fd| is a console FD, 0 otherwise. The value of errno after // calling this function is unreliable and should not be used. -int unix_isatty(int fd); +int unix_isatty(borrowed_fd fd); #define isatty ___xxx_isatty int network_inaddr_any_server(int port, int type, std::string* error); @@ -168,20 +165,21 @@ inline int network_local_server(const char* name, int namespace_id, int type, st int network_connect(const std::string& host, int port, int type, int timeout, std::string* error); -extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen); +extern int adb_socket_accept(borrowed_fd serverfd, struct sockaddr* addr, socklen_t* addrlen); #undef accept #define accept ___xxx_accept // Returns the local port number of a bound socket, or -1 on failure. -int adb_socket_get_local_port(int fd); +int adb_socket_get_local_port(borrowed_fd fd); -extern int adb_setsockopt(int fd, int level, int optname, const void* optval, socklen_t optlen); +extern int adb_setsockopt(borrowed_fd fd, int level, int optname, const void* optval, + socklen_t optlen); #undef setsockopt #define setsockopt ___xxx_setsockopt -extern int adb_socketpair( int sv[2] ); +extern int adb_socketpair(int sv[2]); struct adb_pollfd { int fd; @@ -214,8 +212,7 @@ extern int adb_fputs(const char* buf, FILE* stream); extern int adb_fputc(int ch, FILE* stream); extern int adb_putchar(int ch); extern int adb_puts(const char* buf); -extern size_t adb_fwrite(const void* ptr, size_t size, size_t nmemb, - FILE* stream); +extern size_t adb_fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream); extern FILE* adb_fopen(const char* f, const char* m); @@ -344,9 +341,8 @@ static __inline__ bool adb_is_separator(char c) { return c == '/'; } -static __inline__ void close_on_exec(int fd) -{ - fcntl( fd, F_SETFD, FD_CLOEXEC ); +static __inline__ void close_on_exec(borrowed_fd fd) { + fcntl(fd.get(), F_SETFD, FD_CLOEXEC); } // Open a file and return a file descriptor that may be used with unix_read(), @@ -374,12 +370,10 @@ static __inline__ int unix_open(std::string_view path, int options, ...) { // Similar to the two-argument adb_open(), but takes a mode parameter for file // creation. See adb_open() for more info. -static __inline__ int adb_open_mode( const char* pathname, int options, int mode ) -{ - return TEMP_FAILURE_RETRY( open( pathname, options, mode ) ); +static __inline__ int adb_open_mode(const char* pathname, int options, int mode) { + return TEMP_FAILURE_RETRY(open(pathname, options, mode)); } - // Open a file and return a file descriptor that may be used with adb_read(), // adb_write(), adb_close(), but not unix_read(), unix_write(), unix_close(). // @@ -387,23 +381,21 @@ static __inline__ int adb_open_mode( const char* pathname, int options, int // sysdeps_win32.cpp) uses Windows native file I/O and bypasses the C Runtime // and its CR/LF translation. The returned file descriptor should be used with // adb_read(), adb_write(), adb_close(), etc. -static __inline__ int adb_open( const char* pathname, int options ) -{ - int fd = TEMP_FAILURE_RETRY( open( pathname, options ) ); - if (fd < 0) - return -1; - close_on_exec( fd ); +static __inline__ int adb_open(const char* pathname, int options) { + int fd = TEMP_FAILURE_RETRY(open(pathname, options)); + if (fd < 0) return -1; + close_on_exec(fd); return fd; } -#undef open -#define open ___xxx_open +#undef open +#define open ___xxx_open -static __inline__ int adb_shutdown(int fd, int direction = SHUT_RDWR) { - return shutdown(fd, direction); +static __inline__ int adb_shutdown(borrowed_fd fd, int direction = SHUT_RDWR) { + return shutdown(fd.get(), direction); } -#undef shutdown -#define shutdown ____xxx_shutdown +#undef shutdown +#define shutdown ____xxx_shutdown // Closes a file descriptor that came from adb_open() or adb_open_mode(), but // not designed to take a file descriptor from unix_open(). See the comments @@ -411,81 +403,76 @@ static __inline__ int adb_shutdown(int fd, int direction = SHUT_RDWR) { __inline__ int adb_close(int fd) { return close(fd); } -#undef close -#define close ____xxx_close +#undef close +#define close ____xxx_close // On Windows, ADB has an indirection layer for file descriptors. If we get a // Win32 SOCKET object from an external library, we have to map it in to that // indirection layer, which this does. -__inline__ int adb_register_socket(int s) { +__inline__ int adb_register_socket(int s) { return s; } -static __inline__ int adb_read(int fd, void* buf, size_t len) -{ - return TEMP_FAILURE_RETRY( read( fd, buf, len ) ); +static __inline__ int adb_read(borrowed_fd fd, void* buf, size_t len) { + return TEMP_FAILURE_RETRY(read(fd.get(), buf, len)); } // Like unix_read(), but does not handle EINTR. -static __inline__ int unix_read_interruptible(int fd, void* buf, size_t len) { - return read(fd, buf, len); +static __inline__ int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len) { + return read(fd.get(), buf, len); } -#undef read -#define read ___xxx_read +#undef read +#define read ___xxx_read -static __inline__ int adb_write(int fd, const void* buf, size_t len) -{ - return TEMP_FAILURE_RETRY( write( fd, buf, len ) ); +static __inline__ int adb_write(borrowed_fd fd, const void* buf, size_t len) { + return TEMP_FAILURE_RETRY(write(fd.get(), buf, len)); } #undef write #define write ___xxx_write -static __inline__ int64_t adb_lseek(int fd, int64_t pos, int where) { +static __inline__ int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) { #if defined(__APPLE__) - return lseek(fd, pos, where); + return lseek(fd.get(), pos, where); #else - return lseek64(fd, pos, where); + return lseek64(fd.get(), pos, where); #endif } #undef lseek #define lseek ___xxx_lseek -static __inline__ int adb_unlink(const char* path) -{ - return unlink(path); +static __inline__ int adb_unlink(const char* path) { + return unlink(path); } -#undef unlink -#define unlink ___xxx_unlink +#undef unlink +#define unlink ___xxx_unlink -static __inline__ int adb_creat(const char* path, int mode) -{ - int fd = TEMP_FAILURE_RETRY( creat( path, mode ) ); +static __inline__ int adb_creat(const char* path, int mode) { + int fd = TEMP_FAILURE_RETRY(creat(path, mode)); - if ( fd < 0 ) - return -1; + if (fd < 0) return -1; close_on_exec(fd); return fd; } -#undef creat -#define creat ___xxx_creat +#undef creat +#define creat ___xxx_creat -static __inline__ int unix_isatty(int fd) { - return isatty(fd); +static __inline__ int unix_isatty(borrowed_fd fd) { + return isatty(fd.get()); } -#define isatty ___xxx_isatty +#define isatty ___xxx_isatty // Helper for network_* functions. inline int _fd_set_error_str(int fd, std::string* error) { - if (fd == -1) { - *error = strerror(errno); - } - return fd; + if (fd == -1) { + *error = strerror(errno); + } + return fd; } inline int network_inaddr_any_server(int port, int type, std::string* error) { - return _fd_set_error_str(socket_inaddr_any_server(port, type), error); + return _fd_set_error_str(socket_inaddr_any_server(port, type), error); } inline int network_local_client(const char* name, int namespace_id, int type, std::string* error) { @@ -498,22 +485,21 @@ inline int network_local_server(const char* name, int namespace_id, int type, st int network_connect(const std::string& host, int port, int type, int timeout, std::string* error); -static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen) -{ +static __inline__ int adb_socket_accept(borrowed_fd serverfd, struct sockaddr* addr, + socklen_t* addrlen) { int fd; - fd = TEMP_FAILURE_RETRY( accept( serverfd, addr, addrlen ) ); - if (fd >= 0) - close_on_exec(fd); + fd = TEMP_FAILURE_RETRY(accept(serverfd.get(), addr, addrlen)); + if (fd >= 0) close_on_exec(fd); return fd; } -#undef accept -#define accept ___xxx_accept +#undef accept +#define accept ___xxx_accept -inline int adb_socket_get_local_port(int fd) { - return socket_get_local_port(fd); +inline int adb_socket_get_local_port(borrowed_fd fd) { + return socket_get_local_port(fd.get()); } // Operate on a file descriptor returned from unix_open() or a well-known file @@ -524,10 +510,10 @@ inline int adb_socket_get_local_port(int fd) { // Windows implementations (in the ifdef above and in sysdeps_win32.cpp) call // into the C Runtime and its configurable CR/LF translation (which is settable // via _setmode()). -#define unix_read adb_read -#define unix_write adb_write +#define unix_read adb_read +#define unix_write adb_write #define unix_lseek adb_lseek -#define unix_close adb_close +#define unix_close adb_close static __inline__ int adb_thread_setname(const std::string& name) { #ifdef __APPLE__ @@ -542,34 +528,31 @@ static __inline__ int adb_thread_setname(const std::string& name) { #endif } -static __inline__ int adb_setsockopt( int fd, int level, int optname, const void* optval, socklen_t optlen ) -{ - return setsockopt( fd, level, optname, optval, optlen ); +static __inline__ int adb_setsockopt(borrowed_fd fd, int level, int optname, const void* optval, + socklen_t optlen) { + return setsockopt(fd.get(), level, optname, optval, optlen); } -#undef setsockopt -#define setsockopt ___xxx_setsockopt +#undef setsockopt +#define setsockopt ___xxx_setsockopt -static __inline__ int unix_socketpair( int d, int type, int protocol, int sv[2] ) -{ - return socketpair( d, type, protocol, sv ); +static __inline__ int unix_socketpair(int d, int type, int protocol, int sv[2]) { + return socketpair(d, type, protocol, sv); } -static __inline__ int adb_socketpair( int sv[2] ) -{ - int rc; +static __inline__ int adb_socketpair(int sv[2]) { + int rc; - rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv ); - if (rc < 0) - return -1; + rc = unix_socketpair(AF_UNIX, SOCK_STREAM, 0, sv); + if (rc < 0) return -1; - close_on_exec( sv[0] ); - close_on_exec( sv[1] ); + close_on_exec(sv[0]); + close_on_exec(sv[1]); return 0; } -#undef socketpair -#define socketpair ___xxx_socketpair +#undef socketpair +#define socketpair ___xxx_socketpair typedef struct pollfd adb_pollfd; static __inline__ int adb_poll(adb_pollfd* fds, size_t nfds, int timeout) { @@ -578,13 +561,12 @@ static __inline__ int adb_poll(adb_pollfd* fds, size_t nfds, int timeout) { #define poll ___xxx_poll -static __inline__ int adb_mkdir(const std::string& path, int mode) -{ +static __inline__ int adb_mkdir(const std::string& path, int mode) { return mkdir(path.c_str(), mode); } -#undef mkdir -#define mkdir ___xxx_mkdir +#undef mkdir +#define mkdir ___xxx_mkdir static __inline__ int adb_is_absolute_host_path(const char* path) { return path[0] == '/'; @@ -592,15 +574,15 @@ static __inline__ int adb_is_absolute_host_path(const char* path) { #endif /* !_WIN32 */ -static inline void disable_tcp_nagle(int fd) { +static inline void disable_tcp_nagle(borrowed_fd fd) { int off = 1; - adb_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off)); + adb_setsockopt(fd.get(), IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off)); } // Sets TCP socket |fd| to send a keepalive TCP message every |interval_sec| seconds. Set // |interval_sec| to 0 to disable keepalives. If keepalives are enabled, the connection will be // configured to drop after 10 missed keepalives. Returns true on success. -bool set_tcp_keepalive(int fd, int interval_sec); +bool set_tcp_keepalive(borrowed_fd fd, int interval_sec); #if defined(_WIN32) // Win32 defines ERROR, which we don't need, but which conflicts with google3 logging. diff --git a/adb/sysdeps/posix/network.cpp b/adb/sysdeps/posix/network.cpp index 4de240e5f..c5c227568 100644 --- a/adb/sysdeps/posix/network.cpp +++ b/adb/sysdeps/posix/network.cpp @@ -104,13 +104,13 @@ static int _network_loopback_server(bool ipv6, int port, int type, std::string* socklen_t addrlen = sizeof(addr_storage); sockaddr* addr = (ipv6 ? loopback_addr6 : loopback_addr4)(&addr_storage, &addrlen, port); - if (bind(s, addr, addrlen) != 0) { + if (bind(s.get(), addr, addrlen) != 0) { set_error(error); return -1; } if (type == SOCK_STREAM || type == SOCK_SEQPACKET) { - if (listen(s, SOMAXCONN) != 0) { + if (listen(s.get(), SOMAXCONN) != 0) { set_error(error); return -1; } diff --git a/adb/sysdeps/uio.h b/adb/sysdeps/uio.h index d06ef8958..ced884ba5 100644 --- a/adb/sysdeps/uio.h +++ b/adb/sysdeps/uio.h @@ -18,6 +18,8 @@ #include +#include "adb_unique_fd.h" + #if defined(_WIN32) // Layout of this struct must match struct WSABUF (verified via static assert in sysdeps_win32.cpp) @@ -26,13 +28,15 @@ struct adb_iovec { void* iov_base; }; -ssize_t adb_writev(int fd, const adb_iovec* iov, int iovcnt); +ssize_t adb_writev(borrowed_fd fd, const adb_iovec* iov, int iovcnt); #else #include using adb_iovec = struct iovec; -#define adb_writev writev +inline ssize_t adb_writev(borrowed_fd fd, const adb_iovec* iov, int iovcnt) { + return writev(fd.get(), iov, iovcnt); +} #endif diff --git a/adb/sysdeps_unix.cpp b/adb/sysdeps_unix.cpp index 4445a4420..3fdc917dd 100644 --- a/adb/sysdeps_unix.cpp +++ b/adb/sysdeps_unix.cpp @@ -16,7 +16,7 @@ #include "sysdeps.h" -bool set_tcp_keepalive(int fd, int interval_sec) { +bool set_tcp_keepalive(borrowed_fd fd, int interval_sec) { int enable = (interval_sec > 0); if (adb_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable))) { return false; diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp index 4c5d8cb64..886ded464 100644 --- a/adb/sysdeps_win32.cpp +++ b/adb/sysdeps_win32.cpp @@ -145,16 +145,14 @@ static std::mutex& _win32_lock = *new std::mutex(); static FHRec _win32_fhs[ WIN32_MAX_FHS ]; static int _win32_fh_next; // where to start search for free FHRec -static FH -_fh_from_int( int fd, const char* func ) -{ - FH f; +static FH _fh_from_int(borrowed_fd bfd, const char* func) { + FH f; + int fd = bfd.get(); fd -= WIN32_FH_BASE; if (fd < 0 || fd >= WIN32_MAX_FHS) { - D( "_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE, - func ); + D("_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE, func); errno = EBADF; return nullptr; } @@ -162,8 +160,7 @@ _fh_from_int( int fd, const char* func ) f = &_win32_fhs[fd]; if (f->used == 0) { - D( "_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE, - func ); + D("_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE, func); errno = EBADF; return nullptr; } @@ -171,20 +168,15 @@ _fh_from_int( int fd, const char* func ) return f; } - -static int -_fh_to_int( FH f ) -{ +static int _fh_to_int(FH f) { if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS) return (int)(f - _win32_fhs) + WIN32_FH_BASE; return -1; } -static FH -_fh_alloc( FHClass clazz ) -{ - FH f = nullptr; +static FH _fh_alloc(FHClass clazz) { + FH f = nullptr; std::lock_guard lock(_win32_lock); @@ -206,10 +198,7 @@ _fh_alloc( FHClass clazz ) return nullptr; } - -static int -_fh_close( FH f ) -{ +static int _fh_close(FH f) { // Use lock so that closing only happens once and so that _fh_alloc can't // allocate a FH that we're in the middle of closing. std::lock_guard lock(_win32_lock); @@ -456,7 +445,7 @@ int adb_creat(const char* path, int mode) { return _fh_to_int(f); } -int adb_read(int fd, void* buf, int len) { +int adb_read(borrowed_fd fd, void* buf, int len) { FH f = _fh_from_int(fd, __func__); if (f == nullptr) { @@ -467,7 +456,7 @@ int adb_read(int fd, void* buf, int len) { return f->clazz->_fh_read(f, buf, len); } -int adb_write(int fd, const void* buf, int len) { +int adb_write(borrowed_fd fd, const void* buf, int len) { FH f = _fh_from_int(fd, __func__); if (f == nullptr) { @@ -478,7 +467,7 @@ int adb_write(int fd, const void* buf, int len) { return f->clazz->_fh_write(f, buf, len); } -ssize_t adb_writev(int fd, const adb_iovec* iov, int iovcnt) { +ssize_t adb_writev(borrowed_fd fd, const adb_iovec* iov, int iovcnt) { FH f = _fh_from_int(fd, __func__); if (f == nullptr) { @@ -489,7 +478,7 @@ ssize_t adb_writev(int fd, const adb_iovec* iov, int iovcnt) { return f->clazz->_fh_writev(f, iov, iovcnt); } -int64_t adb_lseek(int fd, int64_t pos, int where) { +int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) { FH f = _fh_from_int(fd, __func__); if (!f) { errno = EBADF; @@ -973,11 +962,11 @@ int adb_register_socket(SOCKET s) { } #undef accept -int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t* addrlen) { +int adb_socket_accept(borrowed_fd serverfd, struct sockaddr* addr, socklen_t* addrlen) { FH serverfh = _fh_from_int(serverfd, __func__); if (!serverfh || serverfh->clazz != &_fh_socket_class) { - D("adb_socket_accept: invalid fd %d", serverfd); + D("adb_socket_accept: invalid fd %d", serverfd.get()); errno = EBADF; return -1; } @@ -992,7 +981,7 @@ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t* addrlen) { fh->fh_socket = accept(serverfh->fh_socket, addr, addrlen); if (fh->fh_socket == INVALID_SOCKET) { const DWORD err = WSAGetLastError(); - LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd + LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd.get() << " failed: " + android::base::SystemErrorCodeToString(err); _socket_set_errno(err); return -1; @@ -1000,16 +989,16 @@ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t* addrlen) { const int fd = _fh_to_int(fh.get()); snprintf(fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name); - D("adb_socket_accept on fd %d returns fd %d", serverfd, fd); + D("adb_socket_accept on fd %d returns fd %d", serverfd.get(), fd); fh.release(); return fd; } -int adb_setsockopt(int fd, int level, int optname, const void* optval, socklen_t optlen) { +int adb_setsockopt(borrowed_fd fd, int level, int optname, const void* optval, socklen_t optlen) { FH fh = _fh_from_int(fd, __func__); if (!fh || fh->clazz != &_fh_socket_class) { - D("adb_setsockopt: invalid fd %d", fd); + D("adb_setsockopt: invalid fd %d", fd.get()); errno = EBADF; return -1; } @@ -1022,7 +1011,7 @@ int adb_setsockopt(int fd, int level, int optname, const void* optval, socklen_t setsockopt(fh->fh_socket, level, optname, reinterpret_cast(optval), optlen); if (result == SOCKET_ERROR) { const DWORD err = WSAGetLastError(); - D("adb_setsockopt: setsockopt on fd %d level %d optname %d failed: %s\n", fd, level, + D("adb_setsockopt: setsockopt on fd %d level %d optname %d failed: %s\n", fd.get(), level, optname, android::base::SystemErrorCodeToString(err).c_str()); _socket_set_errno(err); result = -1; @@ -1030,11 +1019,11 @@ int adb_setsockopt(int fd, int level, int optname, const void* optval, socklen_t return result; } -int adb_getsockname(int fd, struct sockaddr* sockaddr, socklen_t* optlen) { +static int adb_getsockname(borrowed_fd fd, struct sockaddr* sockaddr, socklen_t* optlen) { FH fh = _fh_from_int(fd, __func__); if (!fh || fh->clazz != &_fh_socket_class) { - D("adb_getsockname: invalid fd %d", fd); + D("adb_getsockname: invalid fd %d", fd.get()); errno = EBADF; return -1; } @@ -1042,7 +1031,7 @@ int adb_getsockname(int fd, struct sockaddr* sockaddr, socklen_t* optlen) { int result = getsockname(fh->fh_socket, sockaddr, optlen); if (result == SOCKET_ERROR) { const DWORD err = WSAGetLastError(); - D("adb_getsockname: setsockopt on fd %d failed: %s\n", fd, + D("adb_getsockname: setsockopt on fd %d failed: %s\n", fd.get(), android::base::SystemErrorCodeToString(err).c_str()); _socket_set_errno(err); result = -1; @@ -1050,7 +1039,7 @@ int adb_getsockname(int fd, struct sockaddr* sockaddr, socklen_t* optlen) { return result; } -int adb_socket_get_local_port(int fd) { +int adb_socket_get_local_port(borrowed_fd fd) { sockaddr_storage addr_storage; socklen_t addr_len = sizeof(addr_storage); @@ -1068,11 +1057,11 @@ int adb_socket_get_local_port(int fd) { return ntohs(reinterpret_cast(&addr_storage)->sin_port); } -int adb_shutdown(int fd, int direction) { +int adb_shutdown(borrowed_fd fd, int direction) { FH f = _fh_from_int(fd, __func__); if (!f || f->clazz != &_fh_socket_class) { - D("adb_shutdown: invalid fd %d", fd); + D("adb_shutdown: invalid fd %d", fd.get()); errno = EBADF; return -1; } @@ -1080,7 +1069,7 @@ int adb_shutdown(int fd, int direction) { D("adb_shutdown: %s", f->name); if (shutdown(f->fh_socket, direction) == SOCKET_ERROR) { const DWORD err = WSAGetLastError(); - D("socket shutdown fd %d failed: %s", fd, + D("socket shutdown fd %d failed: %s", fd.get(), android::base::SystemErrorCodeToString(err).c_str()); _socket_set_errno(err); return -1; @@ -1138,12 +1127,12 @@ fail: return -1; } -bool set_file_block_mode(int fd, bool block) { +bool set_file_block_mode(borrowed_fd fd, bool block) { FH fh = _fh_from_int(fd, __func__); if (!fh || !fh->used) { errno = EBADF; - D("Setting nonblocking on bad file descriptor %d", fd); + D("Setting nonblocking on bad file descriptor %d", fd.get()); return false; } @@ -1152,22 +1141,22 @@ bool set_file_block_mode(int fd, bool block) { if (ioctlsocket(fh->u.socket, FIONBIO, &x) != 0) { int error = WSAGetLastError(); _socket_set_errno(error); - D("Setting %d nonblocking failed (%d)", fd, error); + D("Setting %d nonblocking failed (%d)", fd.get(), error); return false; } return true; } else { errno = ENOTSOCK; - D("Setting nonblocking on non-socket %d", fd); + D("Setting nonblocking on non-socket %d", fd.get()); return false; } } -bool set_tcp_keepalive(int fd, int interval_sec) { +bool set_tcp_keepalive(borrowed_fd fd, int interval_sec) { FH fh = _fh_from_int(fd, __func__); if (!fh || fh->clazz != &_fh_socket_class) { - D("set_tcp_keepalive(%d) failed: invalid fd", fd); + D("set_tcp_keepalive(%d) failed: invalid fd", fd.get()); errno = EBADF; return false; } @@ -1181,7 +1170,7 @@ bool set_tcp_keepalive(int fd, int interval_sec) { if (WSAIoctl(fh->fh_socket, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), nullptr, 0, &bytes_returned, nullptr, nullptr) != 0) { const DWORD err = WSAGetLastError(); - D("set_tcp_keepalive(%d) failed: %s", fd, + D("set_tcp_keepalive(%d) failed: %s", fd.get(), android::base::SystemErrorCodeToString(err).c_str()); _socket_set_errno(err); return false; @@ -1228,12 +1217,12 @@ bool set_tcp_keepalive(int fd, int interval_sec) { // Returns a console HANDLE if |fd| is a console, otherwise returns nullptr. // If a valid HANDLE is returned and |mode| is not null, |mode| is also filled // with the console mode. Requires GENERIC_READ access to the underlying HANDLE. -static HANDLE _get_console_handle(int fd, DWORD* mode=nullptr) { +static HANDLE _get_console_handle(borrowed_fd fd, DWORD* mode = nullptr) { // First check isatty(); this is very fast and eliminates most non-console // FDs, but returns 1 for both consoles and character devices like NUL. #pragma push_macro("isatty") #undef isatty - if (!isatty(fd)) { + if (!isatty(fd.get())) { return nullptr; } #pragma pop_macro("isatty") @@ -1241,7 +1230,7 @@ static HANDLE _get_console_handle(int fd, DWORD* mode=nullptr) { // To differentiate between character devices and consoles we need to get // the underlying HANDLE and use GetConsoleMode(), which is what requires // GENERIC_READ permissions. - const intptr_t intptr_handle = _get_osfhandle(fd); + const intptr_t intptr_handle = _get_osfhandle(fd.get()); if (intptr_handle == -1) { return nullptr; } @@ -1265,7 +1254,7 @@ static HANDLE _get_console_handle(FILE* const stream) { return _get_console_handle(fd); } -int unix_isatty(int fd) { +int unix_isatty(borrowed_fd fd) { return _get_console_handle(fd) ? 1 : 0; } @@ -1645,7 +1634,7 @@ static char _get_decimal_char() { // Prefix the len bytes in buf with the escape character, and then return the // new buffer length. -size_t _escape_prefix(char* const buf, const size_t len) { +static size_t _escape_prefix(char* const buf, const size_t len) { // If nothing to prefix, don't do anything. We might be called with // len == 0, if alt was held down with a dead key which produced nothing. if (len == 0) { @@ -2073,7 +2062,7 @@ void stdin_raw_restore() { } // Called by 'adb shell' and 'adb exec-in' (via unix_read()) to read from stdin. -int unix_read_interruptible(int fd, void* buf, size_t len) { +int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len) { if ((fd == STDIN_FILENO) && (_console_handle != nullptr)) { // If it is a request to read from stdin, and stdin_raw_init() has been // called, and it successfully configured the console, then read from @@ -2093,7 +2082,7 @@ int unix_read_interruptible(int fd, void* buf, size_t len) { // plain read() in favor of unix_read() or adb_read(). #pragma push_macro("read") #undef read - return read(fd, buf, len); + return read(fd.get(), buf, len); #pragma pop_macro("read") } } diff --git a/base/Android.bp b/base/Android.bp index d4268cac0..340f81435 100644 --- a/base/Android.bp +++ b/base/Android.bp @@ -46,6 +46,7 @@ cc_defaults { name: "libbase_defaults", defaults: ["libbase_cflags_defaults"], srcs: [ + "abi_compatibility.cpp", "chrono_utils.cpp", "cmsg.cpp", "file.cpp", diff --git a/base/abi_compatibility.cpp b/base/abi_compatibility.cpp new file mode 100644 index 000000000..06a780171 --- /dev/null +++ b/base/abi_compatibility.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019 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 + +#include "android-base/cmsg.h" +#include "android-base/file.h" +#include "android-base/mapped_file.h" +#include "android-base/unique_fd.h" + +namespace android { +namespace base { + +// These ABI-compatibility shims are in a separate file for two reasons: +// 1. If they were in the file with the actual functions, it prevents calls to +// those functions by other functions in the file, due to ambiguity. +// 2. We will hopefully be able to delete these quickly. + +#if !defined(_WIN32) +ssize_t SendFileDescriptorVector(int sockfd, const void* data, size_t len, + const std::vector& fds) { + return SendFileDescriptorVector(borrowed_fd(sockfd), data, len, fds); +} + +ssize_t ReceiveFileDescriptorVector(int sockfd, void* data, size_t len, size_t max_fds, + std::vector* fds) { + return ReceiveFileDescriptorVector(borrowed_fd(sockfd), data, len, max_fds, fds); +} +#endif + +bool ReadFdToString(int fd, std::string* content) { + return ReadFdToString(borrowed_fd(fd), content); +} + +bool WriteStringToFd(const std::string& content, int fd) { + return WriteStringToFd(content, borrowed_fd(fd)); +} + +bool ReadFully(int fd, void* data, size_t byte_count) { + return ReadFully(borrowed_fd(fd), data, byte_count); +} + +bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset) { + return ReadFullyAtOffset(borrowed_fd(fd), data, byte_count, offset); +} + +bool WriteFully(int fd, const void* data, size_t byte_count) { + return WriteFully(borrowed_fd(fd), data, byte_count); +} + +#if defined(__LP64__) +#define MAPPEDFILE_FROMFD _ZN10MappedFile6FromFdEilmi +#else +#define MAPPEDFILE_FROMFD _ZN10MappedFile6FromFdEixmi +#endif + +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +extern "C" std::unique_ptr MAPPEDFILE_FROMFD(int fd, off64_t offset, size_t length, + int prot) { + return MappedFile::FromFd(fd, offset, length, prot); +} + +} // namespace base +} // namespace android diff --git a/base/cmsg.cpp b/base/cmsg.cpp index 42866f8f2..1fa873c82 100644 --- a/base/cmsg.cpp +++ b/base/cmsg.cpp @@ -29,7 +29,7 @@ namespace android { namespace base { -ssize_t SendFileDescriptorVector(int sockfd, const void* data, size_t len, +ssize_t SendFileDescriptorVector(borrowed_fd sockfd, const void* data, size_t len, const std::vector& fds) { size_t cmsg_space = CMSG_SPACE(sizeof(int) * fds.size()); size_t cmsg_len = CMSG_LEN(sizeof(int) * fds.size()); @@ -67,10 +67,10 @@ ssize_t SendFileDescriptorVector(int sockfd, const void* data, size_t len, int flags = 0; #endif - return TEMP_FAILURE_RETRY(sendmsg(sockfd, &msg, flags)); + return TEMP_FAILURE_RETRY(sendmsg(sockfd.get(), &msg, flags)); } -ssize_t ReceiveFileDescriptorVector(int sockfd, void* data, size_t len, size_t max_fds, +ssize_t ReceiveFileDescriptorVector(borrowed_fd sockfd, void* data, size_t len, size_t max_fds, std::vector* fds) { fds->clear(); @@ -98,7 +98,7 @@ ssize_t ReceiveFileDescriptorVector(int sockfd, void* data, size_t len, size_t m flags |= MSG_CMSG_CLOEXEC | MSG_NOSIGNAL; #endif - ssize_t rc = TEMP_FAILURE_RETRY(recvmsg(sockfd, &msg, flags)); + ssize_t rc = TEMP_FAILURE_RETRY(recvmsg(sockfd.get(), &msg, flags)); if (rc == -1) { return -1; diff --git a/base/file.cpp b/base/file.cpp index adc898489..3dfcfbb7e 100644 --- a/base/file.cpp +++ b/base/file.cpp @@ -176,20 +176,20 @@ namespace base { // Versions of standard library APIs that support UTF-8 strings. using namespace android::base::utf8; -bool ReadFdToString(int fd, std::string* content) { +bool ReadFdToString(borrowed_fd fd, std::string* content) { content->clear(); // Although original we had small files in mind, this code gets used for // very large files too, where the std::string growth heuristics might not // be suitable. https://code.google.com/p/android/issues/detail?id=258500. struct stat sb; - if (fstat(fd, &sb) != -1 && sb.st_size > 0) { + if (fstat(fd.get(), &sb) != -1 && sb.st_size > 0) { content->reserve(sb.st_size); } char buf[BUFSIZ]; ssize_t n; - while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) { + while ((n = TEMP_FAILURE_RETRY(read(fd.get(), &buf[0], sizeof(buf)))) > 0) { content->append(buf, n); } return (n == 0) ? true : false; @@ -206,11 +206,11 @@ bool ReadFileToString(const std::string& path, std::string* content, bool follow return ReadFdToString(fd, content); } -bool WriteStringToFd(const std::string& content, int fd) { +bool WriteStringToFd(const std::string& content, borrowed_fd fd) { const char* p = content.data(); size_t left = content.size(); while (left > 0) { - ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, left)); + ssize_t n = TEMP_FAILURE_RETRY(write(fd.get(), p, left)); if (n == -1) { return false; } @@ -269,11 +269,11 @@ bool WriteStringToFile(const std::string& content, const std::string& path, return WriteStringToFd(content, fd) || CleanUpAfterFailedWrite(path); } -bool ReadFully(int fd, void* data, size_t byte_count) { +bool ReadFully(borrowed_fd fd, void* data, size_t byte_count) { uint8_t* p = reinterpret_cast(data); size_t remaining = byte_count; while (remaining > 0) { - ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining)); + ssize_t n = TEMP_FAILURE_RETRY(read(fd.get(), p, remaining)); if (n <= 0) return false; p += n; remaining -= n; @@ -284,14 +284,14 @@ bool ReadFully(int fd, void* data, size_t byte_count) { #if defined(_WIN32) // Windows implementation of pread. Note that this DOES move the file descriptors read position, // but it does so atomically. -static ssize_t pread(int fd, void* data, size_t byte_count, off64_t offset) { +static ssize_t pread(borrowed_fd fd, void* data, size_t byte_count, off64_t offset) { DWORD bytes_read; OVERLAPPED overlapped; memset(&overlapped, 0, sizeof(OVERLAPPED)); overlapped.Offset = static_cast(offset); overlapped.OffsetHigh = static_cast(offset >> 32); - if (!ReadFile(reinterpret_cast(_get_osfhandle(fd)), data, static_cast(byte_count), - &bytes_read, &overlapped)) { + if (!ReadFile(reinterpret_cast(_get_osfhandle(fd.get())), data, + static_cast(byte_count), &bytes_read, &overlapped)) { // In case someone tries to read errno (since this is masquerading as a POSIX call) errno = EIO; return -1; @@ -300,10 +300,10 @@ static ssize_t pread(int fd, void* data, size_t byte_count, off64_t offset) { } #endif -bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset) { +bool ReadFullyAtOffset(borrowed_fd fd, void* data, size_t byte_count, off64_t offset) { uint8_t* p = reinterpret_cast(data); while (byte_count > 0) { - ssize_t n = TEMP_FAILURE_RETRY(pread(fd, p, byte_count, offset)); + ssize_t n = TEMP_FAILURE_RETRY(pread(fd.get(), p, byte_count, offset)); if (n <= 0) return false; p += n; byte_count -= n; @@ -312,11 +312,11 @@ bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset) { return true; } -bool WriteFully(int fd, const void* data, size_t byte_count) { +bool WriteFully(borrowed_fd fd, const void* data, size_t byte_count) { const uint8_t* p = reinterpret_cast(data); size_t remaining = byte_count; while (remaining > 0) { - ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining)); + ssize_t n = TEMP_FAILURE_RETRY(write(fd.get(), p, remaining)); if (n == -1) return false; p += n; remaining -= n; diff --git a/base/include/android-base/cmsg.h b/base/include/android-base/cmsg.h index 7f93ddc3b..e4197b109 100644 --- a/base/include/android-base/cmsg.h +++ b/base/include/android-base/cmsg.h @@ -51,20 +51,20 @@ namespace base { // Note that the write can return short if the socket type is SOCK_STREAM. When // this happens, file descriptors are still sent to the other end, but with // truncated data. For this reason, using SOCK_SEQPACKET or SOCK_DGRAM is recommended. -ssize_t SendFileDescriptorVector(int sock, const void* data, size_t len, +ssize_t SendFileDescriptorVector(borrowed_fd sock, const void* data, size_t len, const std::vector& fds); // Receive file descriptors from a Unix domain socket. // // If more FDs (or bytes, for datagram sockets) are received than expected, // -1 is returned with errno set to EMSGSIZE, and all received FDs are thrown away. -ssize_t ReceiveFileDescriptorVector(int sock, void* data, size_t len, size_t max_fds, +ssize_t ReceiveFileDescriptorVector(borrowed_fd sock, void* data, size_t len, size_t max_fds, std::vector* fds); // Helper for SendFileDescriptorVector that constructs a std::vector for you, e.g.: // SendFileDescriptors(sock, "foo", 3, std::move(fd1), std::move(fd2)) template -ssize_t SendFileDescriptors(int sock, const void* data, size_t len, Args&&... sent_fds) { +ssize_t SendFileDescriptors(borrowed_fd sock, const void* data, size_t len, Args&&... sent_fds) { // Do not allow implicit conversion to int: people might try to do something along the lines of: // SendFileDescriptors(..., std::move(a_unique_fd)) // and be surprised when the unique_fd isn't closed afterwards. @@ -79,7 +79,7 @@ ssize_t SendFileDescriptors(int sock, const void* data, size_t len, Args&&... se // If fewer file descriptors are received than requested, -1 is returned with errno set to ENOMSG. // In both cases, all arguments are cleared and any received FDs are thrown away. template -ssize_t ReceiveFileDescriptors(int sock, void* data, size_t len, Args&&... received_fds) { +ssize_t ReceiveFileDescriptors(borrowed_fd sock, void* data, size_t len, Args&&... received_fds) { std::vector fds; Append(fds, std::forward(received_fds)...); diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h index f8748b5d4..c62256277 100644 --- a/base/include/android-base/file.h +++ b/base/include/android-base/file.h @@ -21,8 +21,9 @@ #include -#include +#include "android-base/macros.h" #include "android-base/off64_t.h" +#include "android-base/unique_fd.h" #if !defined(_WIN32) && !defined(O_BINARY) /** Windows needs O_BINARY, but Unix never mangles line endings. */ @@ -77,13 +78,13 @@ class TemporaryDir { namespace android { namespace base { -bool ReadFdToString(int fd, std::string* content); +bool ReadFdToString(borrowed_fd fd, std::string* content); bool ReadFileToString(const std::string& path, std::string* content, bool follow_symlinks = false); bool WriteStringToFile(const std::string& content, const std::string& path, bool follow_symlinks = false); -bool WriteStringToFd(const std::string& content, int fd); +bool WriteStringToFd(const std::string& content, borrowed_fd fd); #if !defined(_WIN32) bool WriteStringToFile(const std::string& content, const std::string& path, @@ -91,7 +92,7 @@ bool WriteStringToFile(const std::string& content, const std::string& path, bool follow_symlinks = false); #endif -bool ReadFully(int fd, void* data, size_t byte_count); +bool ReadFully(borrowed_fd fd, void* data, size_t byte_count); // Reads `byte_count` bytes from the file descriptor at the specified offset. // Returns false if there was an IO error or EOF was reached before reading `byte_count` bytes. @@ -101,9 +102,9 @@ bool ReadFully(int fd, void* data, size_t byte_count); // get modified. This means that ReadFullyAtOffset can be used concurrently with other calls to the // same function, but concurrently seeking or reading incrementally can lead to unexpected // behavior. -bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset); +bool ReadFullyAtOffset(borrowed_fd fd, void* data, size_t byte_count, off64_t offset); -bool WriteFully(int fd, const void* data, size_t byte_count); +bool WriteFully(borrowed_fd fd, const void* data, size_t byte_count); bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr); diff --git a/base/include/android-base/mapped_file.h b/base/include/android-base/mapped_file.h index 80513b1fa..b71964655 100644 --- a/base/include/android-base/mapped_file.h +++ b/base/include/android-base/mapped_file.h @@ -16,13 +16,14 @@ #pragma once -#include "android-base/macros.h" -#include "android-base/off64_t.h" - #include #include +#include "android-base/macros.h" +#include "android-base/off64_t.h" +#include "android-base/unique_fd.h" + #if defined(_WIN32) #include #define PROT_READ 1 @@ -44,7 +45,8 @@ class MappedFile { * `offset` does not need to be page-aligned. If `PROT_WRITE` is set in `prot`, the mapping * will be writable, otherwise it will be read-only. Mappings are always `MAP_SHARED`. */ - static std::unique_ptr FromFd(int fd, off64_t offset, size_t length, int prot); + static std::unique_ptr FromFd(borrowed_fd fd, off64_t offset, size_t length, + int prot); /** * Removes the mapping. diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h index 3fa3bea2e..3a02cffba 100644 --- a/base/include/android-base/unique_fd.h +++ b/base/include/android-base/unique_fd.h @@ -103,7 +103,17 @@ class unique_fd_impl final { void reset(int new_value = -1) { reset(new_value, nullptr); } int get() const { return fd_; } + +#if !defined(ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION) + // unique_fd's operator int is dangerous, but we have way too much code that + // depends on it, so make this opt-in at first. operator int() const { return get(); } // NOLINT +#endif + + bool operator>=(int rhs) const { return get() >= rhs; } + bool operator<(int rhs) const { return get() < rhs; } + bool operator==(int rhs) const { return get() == rhs; } + bool operator!=(int rhs) const { return get() != rhs; } // Catch bogus error checks (i.e.: "!fd" instead of "fd != -1"). bool operator!() const = delete; @@ -246,6 +256,22 @@ inline DIR* Fdopendir(unique_fd&& ufd) { #endif // !defined(_WIN32) +// A wrapper type that can be implicitly constructed from either int or unique_fd. +struct borrowed_fd { + /* implicit */ borrowed_fd(int fd) : fd_(fd) {} + template + /* implicit */ borrowed_fd(const unique_fd_impl& ufd) : fd_(ufd.get()) {} + + int get() const { return fd_; } + + bool operator>=(int rhs) const { return get() >= rhs; } + bool operator<(int rhs) const { return get() < rhs; } + bool operator==(int rhs) const { return get() == rhs; } + bool operator!=(int rhs) const { return get() != rhs; } + + private: + int fd_ = -1; +}; } // namespace base } // namespace android diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp index 7c65dc3c5..f689bfad7 100644 --- a/base/mapped_file.cpp +++ b/base/mapped_file.cpp @@ -18,6 +18,8 @@ #include +#include "android-base/unique_fd.h" + namespace android { namespace base { @@ -31,7 +33,8 @@ static off64_t InitPageSize() { #endif } -std::unique_ptr MappedFile::FromFd(int fd, off64_t offset, size_t length, int prot) { +std::unique_ptr MappedFile::FromFd(borrowed_fd fd, off64_t offset, size_t length, + int prot) { static off64_t page_size = InitPageSize(); size_t slop = offset % page_size; off64_t file_offset = offset - slop; @@ -39,7 +42,7 @@ std::unique_ptr MappedFile::FromFd(int fd, off64_t offset, size_t le #if defined(_WIN32) HANDLE handle = - CreateFileMapping(reinterpret_cast(_get_osfhandle(fd)), nullptr, + CreateFileMapping(reinterpret_cast(_get_osfhandle(fd.get())), nullptr, (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr); if (handle == nullptr) { // http://b/119818070 "app crashes when reading asset of zero length". @@ -58,7 +61,7 @@ std::unique_ptr MappedFile::FromFd(int fd, off64_t offset, size_t le return std::unique_ptr( new MappedFile{static_cast(base), length, slop, handle}); #else - void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd, file_offset); + void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd.get(), file_offset); if (base == MAP_FAILED) { // http://b/119818070 "app crashes when reading asset of zero length". // mmap fails with EINVAL for a zero length region.