Merge changes I1d899134,If4ea92ae,I92c05721,I298517b6,Iccbeb619, ...
* changes: adb: add stroll equivalent for string_view. adb: finish switching service creation to string_view. adb: switch socket spec to string_view. adb: switch daemon_service_to_fd to string_view. adb: switch usb_linux helper to string_view. adb: switch unix_open to string_view.
This commit is contained in:
commit
d5db4e1b97
18 changed files with 236 additions and 119 deletions
|
|
@ -357,9 +357,9 @@ void handle_packet(apacket *p, atransport *t)
|
|||
|
||||
case A_OPEN: /* OPEN(local-id, 0, "destination") */
|
||||
if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
|
||||
// TODO: Switch to string_view.
|
||||
std::string address(p->payload.begin(), p->payload.end());
|
||||
asocket* s = create_local_service_socket(address.c_str(), t);
|
||||
std::string_view address(p->payload.begin(), p->payload.size());
|
||||
|
||||
asocket* s = create_local_service_socket(address, t);
|
||||
if (s == nullptr) {
|
||||
send_close(0, p->msg.arg0, t);
|
||||
} else {
|
||||
|
|
@ -600,7 +600,7 @@ static void ReportServerStartupFailure(pid_t pid) {
|
|||
fprintf(stderr, "Full server startup log: %s\n", GetLogFilePath().c_str());
|
||||
fprintf(stderr, "Server had pid: %d\n", pid);
|
||||
|
||||
android::base::unique_fd fd(unix_open(GetLogFilePath().c_str(), O_RDONLY));
|
||||
android::base::unique_fd fd(unix_open(GetLogFilePath(), O_RDONLY));
|
||||
if (fd == -1) return;
|
||||
|
||||
// Let's not show more than 128KiB of log...
|
||||
|
|
|
|||
|
|
@ -139,9 +139,9 @@ atransport* find_emulator_transport_by_adb_port(int adb_port);
|
|||
atransport* find_emulator_transport_by_console_port(int console_port);
|
||||
#endif
|
||||
|
||||
int service_to_fd(const char* name, atransport* transport);
|
||||
int service_to_fd(std::string_view name, atransport* transport);
|
||||
#if !ADB_HOST
|
||||
unique_fd daemon_service_to_fd(const char* name, atransport* transport);
|
||||
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport);
|
||||
#endif
|
||||
|
||||
#if ADB_HOST
|
||||
|
|
|
|||
|
|
@ -72,8 +72,7 @@ static std::string get_log_file_name() {
|
|||
}
|
||||
|
||||
void start_device_log(void) {
|
||||
int fd = unix_open(get_log_file_name().c_str(),
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
|
||||
int fd = unix_open(get_log_file_name(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
|
||||
if (fd == -1) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
|
|
@ -94,3 +96,47 @@ class BlockingQueue {
|
|||
};
|
||||
|
||||
std::string GetLogFilePath();
|
||||
|
||||
inline std::string_view StripTrailingNulls(std::string_view str) {
|
||||
size_t n = 0;
|
||||
for (auto it = str.rbegin(); it != str.rend(); ++it) {
|
||||
if (*it != '\0') {
|
||||
break;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
|
||||
str.remove_suffix(n);
|
||||
return str;
|
||||
}
|
||||
|
||||
// Base-10 stroll on a string_view.
|
||||
template <typename T>
|
||||
inline bool ParseUint(T* result, std::string_view str, std::string_view* remaining) {
|
||||
if (str.empty() || !isdigit(str[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
T value = 0;
|
||||
std::string_view::iterator it;
|
||||
constexpr T max = std::numeric_limits<T>::max();
|
||||
for (it = str.begin(); it != str.end() && isdigit(*it); ++it) {
|
||||
if (value > max / 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value *= 10;
|
||||
|
||||
T digit = *it - '0';
|
||||
if (value > max - digit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value += digit;
|
||||
}
|
||||
*result = value;
|
||||
if (remaining) {
|
||||
*remaining = str.substr(it - str.begin());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,3 +181,48 @@ TEST(adb_utils, test_forward_targets_are_valid) {
|
|||
EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:a", &error));
|
||||
EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:22x", &error));
|
||||
}
|
||||
|
||||
void TestParseUint(std::string_view string, bool expected_success, uint32_t expected_value = 0) {
|
||||
// Standalone.
|
||||
{
|
||||
uint32_t value;
|
||||
std::string_view remaining;
|
||||
bool success = ParseUint(&value, string, &remaining);
|
||||
EXPECT_EQ(success, expected_success);
|
||||
if (expected_success) {
|
||||
EXPECT_EQ(value, expected_value);
|
||||
}
|
||||
EXPECT_TRUE(remaining.empty());
|
||||
}
|
||||
|
||||
// With trailing text.
|
||||
{
|
||||
std::string text = std::string(string) + "foo";
|
||||
uint32_t value;
|
||||
std::string_view remaining;
|
||||
bool success = ParseUint(&value, text, &remaining);
|
||||
EXPECT_EQ(success, expected_success);
|
||||
if (expected_success) {
|
||||
EXPECT_EQ(value, expected_value);
|
||||
EXPECT_EQ(remaining, "foo");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(adb_utils, ParseUint) {
|
||||
TestParseUint("", false);
|
||||
TestParseUint("foo", false);
|
||||
TestParseUint("foo123", false);
|
||||
TestParseUint("-1", false);
|
||||
|
||||
TestParseUint("123", true, 123);
|
||||
TestParseUint("9999999999999999999999999", false);
|
||||
TestParseUint(std::to_string(UINT32_MAX), true, UINT32_MAX);
|
||||
TestParseUint("0" + std::to_string(UINT32_MAX), true, UINT32_MAX);
|
||||
TestParseUint(std::to_string(static_cast<uint64_t>(UINT32_MAX) + 1), false);
|
||||
TestParseUint("0" + std::to_string(static_cast<uint64_t>(UINT32_MAX) + 1), false);
|
||||
|
||||
std::string x = std::to_string(UINT32_MAX) + "123";
|
||||
std::string_view substr = std::string_view(x).substr(0, std::to_string(UINT32_MAX).size());
|
||||
TestParseUint(substr, true, UINT32_MAX);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
static void setup_daemon_logging() {
|
||||
const std::string log_file_path(GetLogFilePath());
|
||||
int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
|
||||
int fd = unix_open(log_file_path, O_WRONLY | O_CREAT | O_APPEND, 0640);
|
||||
if (fd == -1) {
|
||||
PLOG(FATAL) << "cannot open " << log_file_path;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include <list>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
#include <android-base/file.h>
|
||||
|
|
@ -90,7 +91,7 @@ struct usb_handle : public ::usb_handle {
|
|||
static auto& g_usb_handles_mutex = *new std::mutex();
|
||||
static auto& g_usb_handles = *new std::list<usb_handle*>();
|
||||
|
||||
static int is_known_device(const char* dev_name) {
|
||||
static int is_known_device(std::string_view dev_name) {
|
||||
std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
|
||||
for (usb_handle* usb : g_usb_handles) {
|
||||
if (usb->path == dev_name) {
|
||||
|
|
@ -152,11 +153,11 @@ static void find_usb_device(const std::string& base,
|
|||
if (contains_non_digit(de->d_name)) continue;
|
||||
|
||||
std::string dev_name = bus_name + "/" + de->d_name;
|
||||
if (is_known_device(dev_name.c_str())) {
|
||||
if (is_known_device(dev_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int fd = unix_open(dev_name.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
int fd = unix_open(dev_name, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -535,10 +536,10 @@ static void register_device(const char* dev_name, const char* dev_path, unsigned
|
|||
// Initialize mark so we don't get garbage collected after the device scan.
|
||||
usb->mark = true;
|
||||
|
||||
usb->fd = unix_open(usb->path.c_str(), O_RDWR | O_CLOEXEC);
|
||||
usb->fd = unix_open(usb->path, O_RDWR | O_CLOEXEC);
|
||||
if (usb->fd == -1) {
|
||||
// Opening RW failed, so see if we have RO access.
|
||||
usb->fd = unix_open(usb->path.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
usb->fd = unix_open(usb->path, O_RDONLY | O_CLOEXEC);
|
||||
if (usb->fd == -1) {
|
||||
D("[ usb open %s failed: %s]", usb->path.c_str(), strerror(errno));
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ bool dev_is_overlayfs(const std::string& dev) {
|
|||
|
||||
bool make_block_device_writable(const std::string& dev) {
|
||||
if (dev_is_overlayfs(dev)) return true;
|
||||
int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
int fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,14 +151,17 @@ void reconnect_service(unique_fd fd, atransport* t) {
|
|||
kick_transport(t);
|
||||
}
|
||||
|
||||
unique_fd reverse_service(const char* command, atransport* transport) {
|
||||
unique_fd reverse_service(std::string_view command, atransport* transport) {
|
||||
// TODO: Switch handle_forward_request to std::string_view.
|
||||
std::string str(command);
|
||||
|
||||
int s[2];
|
||||
if (adb_socketpair(s)) {
|
||||
PLOG(ERROR) << "cannot create service socket pair.";
|
||||
return unique_fd{};
|
||||
}
|
||||
VLOG(SERVICES) << "service socketpair: " << s[0] << ", " << s[1];
|
||||
if (!handle_forward_request(command, transport, s[1])) {
|
||||
if (!handle_forward_request(str.c_str(), transport, s[1])) {
|
||||
SendFail(s[1], "not a reverse forwarding command");
|
||||
}
|
||||
adb_close(s[1]);
|
||||
|
|
@ -167,15 +170,16 @@ unique_fd reverse_service(const char* command, atransport* transport) {
|
|||
|
||||
// Shell service string can look like:
|
||||
// shell[,arg1,arg2,...]:[command]
|
||||
unique_fd ShellService(const std::string& args, const atransport* transport) {
|
||||
unique_fd ShellService(std::string_view args, const atransport* transport) {
|
||||
size_t delimiter_index = args.find(':');
|
||||
if (delimiter_index == std::string::npos) {
|
||||
LOG(ERROR) << "No ':' found in shell service arguments: " << args;
|
||||
return unique_fd{};
|
||||
}
|
||||
|
||||
const std::string service_args = args.substr(0, delimiter_index);
|
||||
const std::string command = args.substr(delimiter_index + 1);
|
||||
// TODO: android::base::Split(const std::string_view&, ...)
|
||||
std::string service_args(args.substr(0, delimiter_index));
|
||||
std::string command(args.substr(delimiter_index + 1));
|
||||
|
||||
// Defaults:
|
||||
// PTY for interactive, raw for non-interactive.
|
||||
|
|
@ -192,15 +196,15 @@ unique_fd ShellService(const std::string& args, const atransport* transport) {
|
|||
type = SubprocessType::kPty;
|
||||
} else if (arg == kShellServiceArgShellProtocol) {
|
||||
protocol = SubprocessProtocol::kShell;
|
||||
} else if (android::base::StartsWith(arg, "TERM=")) {
|
||||
terminal_type = arg.substr(5);
|
||||
} else if (arg.starts_with("TERM=")) {
|
||||
terminal_type = arg.substr(strlen("TERM="));
|
||||
} else if (!arg.empty()) {
|
||||
// This is not an error to allow for future expansion.
|
||||
LOG(WARNING) << "Ignoring unknown shell service argument: " << arg;
|
||||
}
|
||||
}
|
||||
|
||||
return StartSubprocess(command.c_str(), terminal_type.c_str(), type, protocol);
|
||||
return StartSubprocess(command, terminal_type.c_str(), type, protocol);
|
||||
}
|
||||
|
||||
static void spin_service(unique_fd fd) {
|
||||
|
|
@ -323,59 +327,77 @@ asocket* daemon_service_to_socket(std::string_view name) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
unique_fd daemon_service_to_fd(const char* name, atransport* transport) {
|
||||
if (!strncmp("dev:", name, 4)) {
|
||||
return unique_fd{unix_open(name + 4, O_RDWR | O_CLOEXEC)};
|
||||
} else if (!strncmp(name, "framebuffer:", 12)) {
|
||||
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
|
||||
// Historically, we received service names as a char*, and stopped at the first NUL byte.
|
||||
// The client unintentionally sent strings with embedded NULs, which post-string_view, start
|
||||
// being interpreted as part of the string, unless we explicitly strip them.
|
||||
// Notably, shell checks that the part after "shell:" is empty to determine whether the session
|
||||
// is interactive, and {'\0'} is non-empty.
|
||||
name = StripTrailingNulls(name);
|
||||
|
||||
if (name.starts_with("dev:")) {
|
||||
name.remove_prefix(strlen("dev:"));
|
||||
return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
|
||||
} else if (name.starts_with("framebuffer:")) {
|
||||
return create_service_thread("fb", framebuffer_service);
|
||||
} else if (!strncmp(name, "jdwp:", 5)) {
|
||||
return create_jdwp_connection_fd(atoi(name + 5));
|
||||
} else if (!strncmp(name, "shell", 5)) {
|
||||
return ShellService(name + 5, transport);
|
||||
} else if (!strncmp(name, "exec:", 5)) {
|
||||
return StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
|
||||
} else if (!strncmp(name, "sync:", 5)) {
|
||||
} else if (name.starts_with("jdwp:")) {
|
||||
name.remove_prefix(strlen("jdwp:"));
|
||||
std::string str(name);
|
||||
return create_jdwp_connection_fd(atoi(str.c_str()));
|
||||
} else if (name.starts_with("shell")) {
|
||||
name.remove_prefix(strlen("shell"));
|
||||
return ShellService(name, transport);
|
||||
} else if (name.starts_with("exec:")) {
|
||||
name.remove_prefix(strlen("exec:"));
|
||||
return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
|
||||
SubprocessProtocol::kNone);
|
||||
} else if (name.starts_with("sync:")) {
|
||||
return create_service_thread("sync", file_sync_service);
|
||||
} else if (!strncmp(name, "remount:", 8)) {
|
||||
std::string options(name + strlen("remount:"));
|
||||
} else if (name.starts_with("remount:")) {
|
||||
std::string arg(name.begin() + strlen("remount:"), name.end());
|
||||
return create_service_thread("remount",
|
||||
std::bind(remount_service, std::placeholders::_1, options));
|
||||
} else if (!strncmp(name, "reboot:", 7)) {
|
||||
std::string arg(name + strlen("reboot:"));
|
||||
std::bind(remount_service, std::placeholders::_1, arg));
|
||||
} else if (name.starts_with("reboot:")) {
|
||||
std::string arg(name.begin() + strlen("reboot:"), name.end());
|
||||
return create_service_thread("reboot",
|
||||
std::bind(reboot_service, std::placeholders::_1, arg));
|
||||
} else if (!strncmp(name, "root:", 5)) {
|
||||
} else if (name.starts_with("root:")) {
|
||||
return create_service_thread("root", restart_root_service);
|
||||
} else if (!strncmp(name, "unroot:", 7)) {
|
||||
} else if (name.starts_with("unroot:")) {
|
||||
return create_service_thread("unroot", restart_unroot_service);
|
||||
} else if (!strncmp(name, "backup:", 7)) {
|
||||
return StartSubprocess(
|
||||
android::base::StringPrintf("/system/bin/bu backup %s", (name + 7)).c_str(),
|
||||
nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
|
||||
} else if (!strncmp(name, "restore:", 8)) {
|
||||
} else if (name.starts_with("backup:")) {
|
||||
name.remove_prefix(strlen("backup:"));
|
||||
std::string cmd = "/system/bin/bu backup ";
|
||||
cmd += name;
|
||||
return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
|
||||
} else if (name.starts_with("restore:")) {
|
||||
return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
|
||||
SubprocessProtocol::kNone);
|
||||
} else if (!strncmp(name, "tcpip:", 6)) {
|
||||
} else if (name.starts_with("tcpip:")) {
|
||||
name.remove_prefix(strlen("tcpip:"));
|
||||
std::string str(name);
|
||||
|
||||
int port;
|
||||
if (sscanf(name + 6, "%d", &port) != 1) {
|
||||
if (sscanf(str.c_str(), "%d", &port) != 1) {
|
||||
return unique_fd{};
|
||||
}
|
||||
return create_service_thread("tcp",
|
||||
std::bind(restart_tcp_service, std::placeholders::_1, port));
|
||||
} else if (!strncmp(name, "usb:", 4)) {
|
||||
} else if (name.starts_with("usb:")) {
|
||||
return create_service_thread("usb", restart_usb_service);
|
||||
} else if (!strncmp(name, "reverse:", 8)) {
|
||||
return reverse_service(name + 8, transport);
|
||||
} else if (!strncmp(name, "disable-verity:", 15)) {
|
||||
} else if (name.starts_with("reverse:")) {
|
||||
name.remove_prefix(strlen("reverse:"));
|
||||
return reverse_service(name, transport);
|
||||
} else if (name.starts_with("disable-verity:")) {
|
||||
return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service,
|
||||
std::placeholders::_1, false));
|
||||
} else if (!strncmp(name, "enable-verity:", 15)) {
|
||||
} else if (name.starts_with("enable-verity:")) {
|
||||
return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service,
|
||||
std::placeholders::_1, true));
|
||||
} else if (!strcmp(name, "reconnect")) {
|
||||
} else if (name == "reconnect") {
|
||||
return create_service_thread(
|
||||
"reconnect", std::bind(reconnect_service, std::placeholders::_1, transport));
|
||||
} else if (!strcmp(name, "spin")) {
|
||||
} else if (name == "spin") {
|
||||
return create_service_thread("spin", spin_service);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@ bool CreateSocketpair(unique_fd* fd1, unique_fd* fd2) {
|
|||
|
||||
class Subprocess {
|
||||
public:
|
||||
Subprocess(const std::string& command, const char* terminal_type,
|
||||
SubprocessType type, SubprocessProtocol protocol);
|
||||
Subprocess(std::string command, const char* terminal_type, SubprocessType type,
|
||||
SubprocessProtocol protocol);
|
||||
~Subprocess();
|
||||
|
||||
const std::string& command() const { return command_; }
|
||||
|
|
@ -191,9 +191,9 @@ class Subprocess {
|
|||
DISALLOW_COPY_AND_ASSIGN(Subprocess);
|
||||
};
|
||||
|
||||
Subprocess::Subprocess(const std::string& command, const char* terminal_type,
|
||||
SubprocessType type, SubprocessProtocol protocol)
|
||||
: command_(command),
|
||||
Subprocess::Subprocess(std::string command, const char* terminal_type, SubprocessType type,
|
||||
SubprocessProtocol protocol)
|
||||
: command_(std::move(command)),
|
||||
terminal_type_(terminal_type ? terminal_type : ""),
|
||||
type_(type),
|
||||
protocol_(protocol) {
|
||||
|
|
@ -745,14 +745,13 @@ static unique_fd ReportError(SubprocessProtocol protocol, const std::string& mes
|
|||
return read;
|
||||
}
|
||||
|
||||
unique_fd StartSubprocess(const char* name, const char* terminal_type, SubprocessType type,
|
||||
unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
|
||||
SubprocessProtocol protocol) {
|
||||
D("starting %s subprocess (protocol=%s, TERM=%s): '%s'",
|
||||
type == SubprocessType::kRaw ? "raw" : "PTY",
|
||||
protocol == SubprocessProtocol::kNone ? "none" : "shell",
|
||||
terminal_type, name);
|
||||
protocol == SubprocessProtocol::kNone ? "none" : "shell", terminal_type, name.c_str());
|
||||
|
||||
auto subprocess = std::make_unique<Subprocess>(name, terminal_type, type, protocol);
|
||||
auto subprocess = std::make_unique<Subprocess>(std::move(name), terminal_type, type, protocol);
|
||||
if (!subprocess) {
|
||||
LOG(ERROR) << "failed to allocate new subprocess";
|
||||
return ReportError(protocol, "failed to allocate new subprocess");
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "adb_unique_fd.h"
|
||||
|
||||
enum class SubprocessType {
|
||||
|
|
@ -32,5 +34,5 @@ enum class SubprocessProtocol {
|
|||
// shell is started, otherwise |name| is executed non-interactively.
|
||||
//
|
||||
// Returns an open FD connected to the subprocess or -1 on failure.
|
||||
unique_fd StartSubprocess(const char* name, const char* terminal_type, SubprocessType type,
|
||||
unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
|
||||
SubprocessProtocol protocol);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ unique_fd create_service_thread(const char* service_name, std::function<void(uni
|
|||
return unique_fd(s[0]);
|
||||
}
|
||||
|
||||
int service_to_fd(const char* name, atransport* transport) {
|
||||
int service_to_fd(std::string_view name, atransport* transport) {
|
||||
int ret = -1;
|
||||
|
||||
if (is_socket_spec(name)) {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ void remove_socket(asocket *s);
|
|||
void close_all_sockets(atransport *t);
|
||||
|
||||
asocket *create_local_socket(int fd);
|
||||
asocket* create_local_service_socket(const char* destination, atransport* transport);
|
||||
asocket* create_local_service_socket(std::string_view destination, atransport* transport);
|
||||
|
||||
asocket *create_remote_socket(unsigned id, atransport *t);
|
||||
void connect_to_remote(asocket *s, const char *destination);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "socket_spec.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -29,7 +30,8 @@
|
|||
#include "adb.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
using android::base::StartsWith;
|
||||
using namespace std::string_literals;
|
||||
|
||||
using android::base::StringPrintf;
|
||||
|
||||
#if defined(__linux__)
|
||||
|
|
@ -64,10 +66,11 @@ static auto& kLocalSocketTypes = *new std::unordered_map<std::string, LocalSocke
|
|||
{ "localfilesystem", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } },
|
||||
});
|
||||
|
||||
bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int* port,
|
||||
bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
|
||||
std::string* error) {
|
||||
if (!StartsWith(spec, "tcp:")) {
|
||||
*error = StringPrintf("specification is not tcp: '%s'", spec.c_str());
|
||||
if (!spec.starts_with("tcp:")) {
|
||||
*error = "specification is not tcp: ";
|
||||
*error += spec;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +87,7 @@ bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int*
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string addr = spec.substr(4);
|
||||
std::string addr(spec.substr(4));
|
||||
port_value = -1;
|
||||
|
||||
// FIXME: ParseNetAddress rejects port 0. This currently doesn't hurt, because listening
|
||||
|
|
@ -94,7 +97,8 @@ bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int*
|
|||
}
|
||||
|
||||
if (port_value == -1) {
|
||||
*error = StringPrintf("missing port in specification: '%s'", spec.c_str());
|
||||
*error = "missing port in specification: ";
|
||||
*error += spec;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -110,25 +114,25 @@ bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int*
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool tcp_host_is_local(const std::string& hostname) {
|
||||
static bool tcp_host_is_local(std::string_view hostname) {
|
||||
// FIXME
|
||||
return hostname.empty() || hostname == "localhost";
|
||||
}
|
||||
|
||||
bool is_socket_spec(const std::string& spec) {
|
||||
bool is_socket_spec(std::string_view spec) {
|
||||
for (const auto& it : kLocalSocketTypes) {
|
||||
std::string prefix = it.first + ":";
|
||||
if (StartsWith(spec, prefix)) {
|
||||
if (spec.starts_with(prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return StartsWith(spec, "tcp:");
|
||||
return spec.starts_with("tcp:");
|
||||
}
|
||||
|
||||
bool is_local_socket_spec(const std::string& spec) {
|
||||
bool is_local_socket_spec(std::string_view spec) {
|
||||
for (const auto& it : kLocalSocketTypes) {
|
||||
std::string prefix = it.first + ":";
|
||||
if (StartsWith(spec, prefix)) {
|
||||
if (spec.starts_with(prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -141,8 +145,8 @@ bool is_local_socket_spec(const std::string& spec) {
|
|||
return tcp_host_is_local(hostname);
|
||||
}
|
||||
|
||||
int socket_spec_connect(const std::string& spec, std::string* error) {
|
||||
if (StartsWith(spec, "tcp:")) {
|
||||
int socket_spec_connect(std::string_view spec, std::string* error) {
|
||||
if (spec.starts_with("tcp:")) {
|
||||
std::string hostname;
|
||||
int port;
|
||||
if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
|
||||
|
|
@ -170,7 +174,7 @@ int socket_spec_connect(const std::string& spec, std::string* error) {
|
|||
|
||||
for (const auto& it : kLocalSocketTypes) {
|
||||
std::string prefix = it.first + ":";
|
||||
if (StartsWith(spec, prefix)) {
|
||||
if (spec.starts_with(prefix)) {
|
||||
if (!it.second.available) {
|
||||
*error = StringPrintf("socket type %s is unavailable on this platform",
|
||||
it.first.c_str());
|
||||
|
|
@ -182,12 +186,13 @@ int socket_spec_connect(const std::string& spec, std::string* error) {
|
|||
}
|
||||
}
|
||||
|
||||
*error = StringPrintf("unknown socket specification '%s'", spec.c_str());
|
||||
*error = "unknown socket specification: ";
|
||||
*error += spec;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int socket_spec_listen(const std::string& spec, std::string* error, int* resolved_tcp_port) {
|
||||
if (StartsWith(spec, "tcp:")) {
|
||||
int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_tcp_port) {
|
||||
if (spec.starts_with("tcp:")) {
|
||||
std::string hostname;
|
||||
int port;
|
||||
if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
|
||||
|
|
@ -213,10 +218,10 @@ int socket_spec_listen(const std::string& spec, std::string* error, int* resolve
|
|||
|
||||
for (const auto& it : kLocalSocketTypes) {
|
||||
std::string prefix = it.first + ":";
|
||||
if (StartsWith(spec, prefix)) {
|
||||
if (spec.starts_with(prefix)) {
|
||||
if (!it.second.available) {
|
||||
*error = StringPrintf("attempted to listen on unavailable socket type: '%s'",
|
||||
spec.c_str());
|
||||
*error = "attempted to listen on unavailable socket type: ";
|
||||
*error += spec;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -225,6 +230,7 @@ int socket_spec_listen(const std::string& spec, std::string* error, int* resolve
|
|||
}
|
||||
}
|
||||
|
||||
*error = StringPrintf("unknown socket specification '%s'", spec.c_str());
|
||||
*error = "unknown socket specification:";
|
||||
*error += spec;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,12 @@
|
|||
#include <string>
|
||||
|
||||
// Returns true if the argument starts with a plausible socket prefix.
|
||||
bool is_socket_spec(const std::string& spec);
|
||||
bool is_local_socket_spec(const std::string& spec);
|
||||
bool is_socket_spec(std::string_view spec);
|
||||
bool is_local_socket_spec(std::string_view spec);
|
||||
|
||||
int socket_spec_connect(const std::string& spec, std::string* error);
|
||||
int socket_spec_listen(const std::string& spec, std::string* error,
|
||||
int* resolved_tcp_port = nullptr);
|
||||
int socket_spec_connect(std::string_view spec, std::string* error);
|
||||
int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_tcp_port = nullptr);
|
||||
|
||||
// Exposed for testing.
|
||||
bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int* port,
|
||||
bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
|
||||
std::string* error);
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ asocket* create_local_socket(int fd) {
|
|||
return s;
|
||||
}
|
||||
|
||||
asocket* create_local_service_socket(const char* name, atransport* transport) {
|
||||
asocket* create_local_service_socket(std::string_view name, atransport* transport) {
|
||||
#if !ADB_HOST
|
||||
if (asocket* s = daemon_service_to_socket(name); s) {
|
||||
return s;
|
||||
|
|
@ -358,13 +358,12 @@ asocket* create_local_service_socket(const char* name, atransport* transport) {
|
|||
}
|
||||
|
||||
asocket* s = create_local_socket(fd);
|
||||
D("LS(%d): bound to '%s' via %d", s->id, name, fd);
|
||||
LOG(VERBOSE) << "LS(" << s->id << "): bound to '" << name << "' via " << fd;
|
||||
|
||||
#if !ADB_HOST
|
||||
if ((!strncmp(name, "root:", 5) && getuid() != 0 && __android_log_is_debuggable()) ||
|
||||
(!strncmp(name, "unroot:", 7) && getuid() == 0) ||
|
||||
!strncmp(name, "usb:", 4) ||
|
||||
!strncmp(name, "tcpip:", 6)) {
|
||||
if ((name.starts_with("root:") && getuid() != 0 && __android_log_is_debuggable()) ||
|
||||
(name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
|
||||
name.starts_with("tcpip:")) {
|
||||
D("LS(%d): enabling exit_on_close", s->id);
|
||||
s->exit_on_close = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
// Include this before open/close/unlink are defined as macros below.
|
||||
|
|
@ -139,7 +140,7 @@ static __inline__ int adb_open_mode(const char* path, int options, int mode)
|
|||
}
|
||||
|
||||
// See the comments for the !defined(_WIN32) version of unix_open().
|
||||
extern int unix_open(const char* path, int options, ...);
|
||||
extern int unix_open(std::string_view path, int options, ...);
|
||||
#define open ___xxx_unix_open
|
||||
|
||||
// Checks if |fd| corresponds to a console.
|
||||
|
|
@ -357,20 +358,17 @@ static __inline__ void close_on_exec(int fd)
|
|||
// by unix_read(), unix_write(), unix_close()). Also, the C Runtime has
|
||||
// configurable CR/LF translation which defaults to text mode, but is settable
|
||||
// with _setmode().
|
||||
static __inline__ int unix_open(const char* path, int options,...)
|
||||
{
|
||||
if ((options & O_CREAT) == 0)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY( open(path, options) );
|
||||
}
|
||||
else
|
||||
{
|
||||
int mode;
|
||||
va_list args;
|
||||
va_start( args, options );
|
||||
mode = va_arg( args, int );
|
||||
va_end( args );
|
||||
return TEMP_FAILURE_RETRY( open( path, options, mode ) );
|
||||
static __inline__ int unix_open(std::string_view path, int options, ...) {
|
||||
std::string zero_terminated(path.begin(), path.end());
|
||||
if ((options & O_CREAT) == 0) {
|
||||
return TEMP_FAILURE_RETRY(open(zero_terminated.c_str(), options));
|
||||
} else {
|
||||
int mode;
|
||||
va_list args;
|
||||
va_start(args, options);
|
||||
mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
return TEMP_FAILURE_RETRY(open(zero_terminated.c_str(), options, mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -2203,15 +2204,15 @@ NarrowArgs::~NarrowArgs() {
|
|||
}
|
||||
}
|
||||
|
||||
int unix_open(const char* path, int options, ...) {
|
||||
int unix_open(std::string_view path, int options, ...) {
|
||||
std::wstring path_wide;
|
||||
if (!android::base::UTF8ToWide(path, &path_wide)) {
|
||||
if (!android::base::UTF8ToWide(path.data(), path.size(), &path_wide)) {
|
||||
return -1;
|
||||
}
|
||||
if ((options & O_CREAT) == 0) {
|
||||
return _wopen(path_wide.c_str(), options);
|
||||
} else {
|
||||
int mode;
|
||||
int mode;
|
||||
va_list args;
|
||||
va_start(args, options);
|
||||
mode = va_arg(args, int);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue