More fixed-length buffer removal.
Bug: http://b/20666660
Change-Id: I0c738e9fed2defed48a9cf2d0a4f7b99c08dcf3d
(cherry picked from commit 6452a89aa8934231e12ab77e0d90f12c3e892ad1)
diff --git a/adb/adb.h b/adb/adb.h
index cb2cf60..b8c6156 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -243,8 +243,6 @@
void remove_socket(asocket *s);
void close_all_sockets(atransport *t);
-#define LOCAL_CLIENT_PREFIX "emulator-"
-
asocket *create_local_socket(int fd);
asocket *create_local_service_socket(const char *destination);
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 0b2d038..62f79fa 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -32,6 +32,7 @@
#include <vector>
#include <base/stringprintf.h>
+#include <base/strings.h>
#include "adb_io.h"
@@ -41,6 +42,29 @@
static int __adb_server_port = DEFAULT_ADB_PORT;
static const char* __adb_server_name = NULL;
+static std::string perror_str(const char* msg) {
+ return android::base::StringPrintf("%s: %s", msg, strerror(errno));
+}
+
+static bool ReadProtocolString(int 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)");
+ return false;
+ }
+ buf[4] = 0;
+
+ unsigned long len = strtoul(buf, 0, 16);
+ s->resize(len + 1, '\0'); // Ensure NUL-termination.
+ if (!ReadFdExactly(fd, &(*s)[0], len)) {
+ *error = perror_str("protocol fault (couldn't read status message)");
+ return false;
+ }
+
+ return true;
+}
+
void adb_set_transport(transport_type type, const char* serial)
{
__adb_transport = type;
@@ -57,58 +81,36 @@
__adb_server_name = hostname;
}
-int adb_get_emulator_console_port(void)
-{
- const char* serial = __adb_serial;
- int port;
+int adb_get_emulator_console_port() {
+ if (__adb_serial) {
+ // The user specified a serial number; is it an emulator?
+ int port;
+ return (sscanf(__adb_serial, "emulator-%d", &port) == 1) ? port : -1;
+ }
- if (serial == NULL) {
- /* if no specific device was specified, we need to look at */
- /* the list of connected devices, and extract an emulator */
- /* name from it. two emulators is an error */
- std::string error;
- char* tmp = adb_query("host:devices", &error);
- char* p = tmp;
- if (!tmp) {
- printf("no emulator connected: %s\n", error.c_str());
- return -1;
- }
- while (*p) {
- char* q = strchr(p, '\n');
- if (q != NULL)
- *q++ = 0;
- else
- q = p + strlen(p);
+ // No specific device was given, so get the list of connected
+ // devices and search for emulators. If there's one, we'll
+ // take it. If there are more than one, that's an error.
+ std::string devices;
+ std::string error;
+ if (!adb_query("host:devices", &devices, &error)) {
+ printf("no emulator connected: %s\n", error.c_str());
+ return -1;
+ }
- if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
- if (serial != NULL) { /* more than one emulator listed */
- free(tmp);
- return -2;
- }
- serial = p;
+ int port;
+ size_t emulator_count = 0;
+ for (auto& device : android::base::Split(devices, "\n")) {
+ if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
+ if (++emulator_count > 1) {
+ return -2;
}
-
- p = q;
}
- free(tmp);
-
- if (serial == NULL)
- return -1; /* no emulator found */
}
- else {
- if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
- return -1; /* not an emulator */
- }
-
- serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
- port = strtol(serial, NULL, 10);
+ if (emulator_count == 0) return -1;
return port;
}
-std::string perror_str(const char* msg) {
- return android::base::StringPrintf("%s: %s", msg, strerror(errno));
-}
-
static int switch_socket_transport(int fd, std::string* error) {
std::string service;
if (__adb_serial) {
@@ -170,47 +172,36 @@
return false;
}
- if (!ReadFdExactly(fd, buf, 4)) {
- *error = perror_str("protocol fault (couldn't read status length)");
- return false;
- }
- buf[4] = 0;
-
- unsigned long len = strtoul(buf, 0, 16);
- error->resize(len + 1, '\0'); // Ensure NUL-termination.
- if (!ReadFdExactly(fd, &(*error)[0], len)) {
- *error = perror_str("protocol fault (couldn't read status message)");
- }
+ ReadProtocolString(fd, error, error);
return false;
}
-int _adb_connect(const char *service, std::string* error) {
- char tmp[5];
- int fd;
-
- D("_adb_connect: %s\n", service);
- size_t len = strlen(service);
- if ((len < 1) || (len > 1024)) {
- *error = android::base::StringPrintf("service name too long (%d)", static_cast<int>(len));
+int _adb_connect(const std::string& service, std::string* error) {
+ D("_adb_connect: %s\n", service.c_str());
+ if (service.empty() || service.size() > 1024) {
+ *error = android::base::StringPrintf("bad service name length (%d)",
+ static_cast<int>(service.size()));
return -1;
}
- snprintf(tmp, sizeof tmp, "%04zx", len);
- if (__adb_server_name)
+ int fd;
+ if (__adb_server_name) {
fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
- else
+ } else {
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
-
- if(fd < 0) {
+ }
+ if (fd < 0) {
*error = perror_str("cannot connect to daemon");
return -2;
}
- if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd, error)) {
+ if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
return -1;
}
- if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
+ char tmp[5];
+ snprintf(tmp, sizeof(tmp), "%04zx", service.size());
+ if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, &service[0], service.size())) {
*error = perror_str("write failure during connection");
adb_close(fd);
return -1;
@@ -225,11 +216,11 @@
return fd;
}
-int adb_connect(const char* service, std::string* error) {
+int adb_connect(const std::string& service, std::string* error) {
// first query the adb server's version
int fd = _adb_connect("host:version", error);
- D("adb_connect: service %s\n", service);
+ D("adb_connect: service %s\n", service.c_str());
if (fd == -2 && __adb_server_name) {
fprintf(stderr,"** Cannot start server on remote host\n");
return fd;
@@ -248,21 +239,20 @@
// fall through to _adb_connect
} else {
// if server was running, check its version to make sure it is not out of date
- char buf[100];
- size_t n;
int version = ADB_SERVER_VERSION - 1;
// if we have a file descriptor, then parse version result
if (fd >= 0) {
- if(!ReadFdExactly(fd, buf, 4)) goto error;
+ std::string version_string;
+ if (!ReadProtocolString(fd, &version_string, error)) {
+ goto error;
+ }
- buf[4] = 0;
- n = strtoul(buf, 0, 16);
- if(n > sizeof(buf)) goto error;
- if(!ReadFdExactly(fd, buf, n)) goto error;
adb_close(fd);
- if (sscanf(buf, "%04x", &version) != 1) goto error;
+ if (sscanf(&version_string[0], "%04x", &version) != 1) {
+ goto error;
+ }
} else {
// if fd is -1, then check for "unknown host service",
// which would indicate a version of adb that does not support the version command
@@ -271,7 +261,7 @@
}
}
- if(version != ADB_SERVER_VERSION) {
+ if (version != ADB_SERVER_VERSION) {
printf("adb server is out of date. killing...\n");
fd = _adb_connect("host:kill", error);
adb_close(fd);
@@ -283,7 +273,7 @@
}
// if the command is start-server, we are done.
- if (!strcmp(service, "host:start-server")) {
+ if (service == "host:start-server") {
return 0;
}
@@ -302,7 +292,7 @@
}
-int adb_command(const char* service, std::string* error) {
+int adb_command(const std::string& service, std::string* error) {
int fd = adb_connect(service, error);
if (fd < 0) {
fprintf(stderr, "error: %s\n", error->c_str());
@@ -317,39 +307,18 @@
return 0;
}
-char* adb_query(const char* service, std::string* error) {
- char buf[5];
- unsigned long n;
- char* tmp;
-
- D("adb_query: %s\n", service);
+bool adb_query(const std::string& service, std::string* result, std::string* error) {
+ D("adb_query: %s\n", service.c_str());
int fd = adb_connect(service, error);
if (fd < 0) {
fprintf(stderr,"error: %s\n", error->c_str());
return 0;
}
- if (!ReadFdExactly(fd, buf, 4)) goto oops;
-
- buf[4] = 0;
- n = strtoul(buf, 0, 16);
- // TODO: given that we just read a 4-byte hex length 0x????, why the test?
- if (n >= 0xffff) {
- *error = "reply is too long (>= 64KiB)";
- goto oops;
- }
-
- tmp = reinterpret_cast<char*>(malloc(n + 1));
- if(tmp == 0) goto oops;
-
- if(!ReadFdExactly(fd, tmp, n) == 0) {
- tmp[n] = 0;
+ result->clear();
+ if (!ReadProtocolString(fd, result, error)) {
adb_close(fd);
- return tmp;
+ return false;
}
- free(tmp);
-
-oops:
- adb_close(fd);
- return 0;
+ return true;
}
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 5ce7080..96416f5 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -9,19 +9,17 @@
** a valid fd for interacting with that service upon success
** or a negative number on failure
*/
-int adb_connect(const char* service, std::string* error);
-int _adb_connect(const char* service, std::string* error);
+int adb_connect(const std::string& service, std::string* error);
+int _adb_connect(const std::string& service, std::string* error);
/* connect to adb, connect to the named service, return 0 if
** the connection succeeded AND the service returned OKAY
*/
-int adb_command(const char* service, std::string* error);
+int adb_command(const std::string& service, std::string* error);
-/* connect to adb, connect to the named service, return
-** a malloc'd string of its response upon success or NULL
-** on failure.
-*/
-char* adb_query(const char* service, std::string* error);
+// Connects to the named adb service and fills 'result' with the response.
+// Returns true on success; returns false and fills 'error' on failure.
+bool adb_query(const std::string& service, std::string* result, std::string* error);
/* Set the preferred transport to connect to.
*/
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index b5015ea..4941689 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -201,7 +201,6 @@
" adb get-state - prints: offline | bootloader | device\n"
" adb get-serialno - prints: <serial-number>\n"
" adb get-devpath - prints: <device-path>\n"
- " adb status-window - continuously print device status for a specified device\n"
" adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
" adb reboot [bootloader|recovery]\n"
" - reboots the device, optionally into the bootloader or recovery program.\n"
@@ -437,31 +436,25 @@
}
-static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
-{
+static std::string format_host_command(const char* command, transport_type type, const char* serial) {
if (serial) {
- snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
- } else {
- const char* prefix = "host";
- if (ttype == kTransportUsb)
- prefix = "host-usb";
- else if (ttype == kTransportLocal)
- prefix = "host-local";
-
- snprintf(buffer, buflen, "%s:%s", prefix, command);
+ return android::base::StringPrintf("host-serial:%s:%s", serial, command);
}
+
+ const char* prefix = "host";
+ if (type == kTransportUsb) {
+ prefix = "host-usb";
+ } else if (type == kTransportLocal) {
+ prefix = "host-local";
+ }
+ return android::base::StringPrintf("%s:%s", prefix, command);
}
-static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
+static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
bool show_progress)
{
- char buf[4096];
- unsigned total;
-
- sprintf(buf,"%s:%d", service, sz);
-
std::string error;
- int fd = adb_connect(buf, &error);
+ int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
if (fd < 0) {
fprintf(stderr,"error: %s\n", error.c_str());
return -1;
@@ -470,7 +463,7 @@
int opt = CHUNK_SIZE;
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
- total = sz;
+ unsigned total = sz;
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
if (show_progress) {
@@ -478,7 +471,7 @@
if(x) service = x + 1;
}
- while(sz > 0) {
+ while (sz > 0) {
unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
if (!WriteFdExactly(fd, ptr, xfer)) {
std::string error;
@@ -497,6 +490,8 @@
printf("\n");
}
+ // TODO: should this be adb_status?
+ char buf[5];
if(!ReadFdExactly(fd, buf, 4)){
fprintf(stderr,"* error reading response *\n");
adb_close(fd);
@@ -550,10 +545,10 @@
return -1;
}
- char buf[100];
- sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
+ std::string service =
+ android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
std::string error;
- int fd = adb_connect(buf, &error);
+ int fd = adb_connect(service, &error);
if (fd < 0) {
// Try falling back to the older sideload method. Maybe this
// is an older device that doesn't support sideload-host.
@@ -565,18 +560,19 @@
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
while (true) {
+ char buf[9];
if (!ReadFdExactly(fd, buf, 8)) {
fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
status = -1;
goto done;
}
+ buf[8] = '\0';
- if (strncmp("DONEDONE", buf, 8) == 0) {
+ if (strcmp("DONEDONE", buf) == 0) {
status = 0;
break;
}
- buf[8] = '\0';
int block = strtol(buf, NULL, 10);
size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
@@ -622,51 +618,6 @@
return status;
}
-static void status_window(transport_type ttype, const char* serial)
-{
- char command[4096];
- char *state = 0;
- char *laststate = 0;
-
- /* silence stderr */
-#ifdef _WIN32
- /* XXX: TODO */
-#else
- int fd;
- fd = unix_open("/dev/null", O_WRONLY);
- dup2(fd, 2);
- adb_close(fd);
-#endif
-
- format_host_command(command, sizeof command, "get-state", ttype, serial);
-
- while (true) {
- adb_sleep_ms(250);
-
- if (state) {
- free(state);
- state = 0;
- }
-
- std::string error;
- state = adb_query(command, &error);
-
- if (state) {
- if (laststate && !strcmp(state,laststate)){
- continue;
- } else {
- if (laststate) free(laststate);
- laststate = strdup(state);
- }
- }
-
- printf("%c[2J%c[2H", 27, 27);
- printf("Android Debug Bridge\n");
- printf("State: %s\n", state ? state : "offline");
- fflush(stdout);
- }
-}
-
/**
* Run ppp in "notty" mode against a resource listed as the first parameter
* eg:
@@ -741,7 +692,7 @@
int fd;
while (true) {
std::string error;
- fd = adb_connect(command.c_str(), &error);
+ fd = adb_connect(command, &error);
if (fd >= 0) {
break;
}
@@ -835,7 +786,7 @@
D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
std::string error;
- int fd = adb_connect(cmd.c_str(), &error);
+ int fd = adb_connect(cmd, &error);
if (fd < 0) {
fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
adb_close(outFd);
@@ -964,7 +915,7 @@
}
}
-static int adb_connect_command(const char* command) {
+static int adb_connect_command(const std::string& command) {
std::string error;
int fd = adb_connect(command, &error);
if (fd != -1) {
@@ -976,6 +927,17 @@
return 1;
}
+static int adb_query_command(const std::string& command) {
+ std::string result;
+ std::string error;
+ if (!adb_query(command, &result, &error)) {
+ fprintf(stderr, "error: %s\n", error.c_str());
+ return 1;
+ }
+ printf("%s\n", result.c_str());
+ return 0;
+}
+
int adb_commandline(int argc, const char **argv)
{
char buf[4096];
@@ -1129,10 +1091,9 @@
}
}
- format_host_command(buf, sizeof buf, service, ttype, serial);
-
+ std::string cmd = format_host_command(service, ttype, serial);
std::string error;
- if (adb_command(buf, &error)) {
+ if (adb_command(cmd, &error)) {
D("failure: %s *\n", error.c_str());
fprintf(stderr,"error: %s\n", error.c_str());
return 1;
@@ -1152,62 +1113,38 @@
/* adb_connect() commands */
if (!strcmp(argv[0], "devices")) {
- char *tmp;
const char *listopt;
- if (argc < 2)
+ if (argc < 2) {
listopt = "";
- else if (argc == 2 && !strcmp(argv[1], "-l"))
+ } else if (argc == 2 && !strcmp(argv[1], "-l")) {
listopt = argv[1];
- else {
+ } else {
fprintf(stderr, "Usage: adb devices [-l]\n");
return 1;
}
- snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
- std::string error;
- tmp = adb_query(buf, &error);
- if (tmp) {
- printf("List of devices attached \n");
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+
+ std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
+ printf("List of devices attached\n");
+ return adb_query_command(query);
}
else if (!strcmp(argv[0], "connect")) {
- char *tmp;
if (argc != 2) {
fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
return 1;
}
- snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
- std::string error;
- tmp = adb_query(buf, &error);
- if (tmp) {
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+
+ std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
+ return adb_query_command(query);
}
else if (!strcmp(argv[0], "disconnect")) {
- char *tmp;
if (argc > 2) {
fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
return 1;
}
- if (argc == 2) {
- snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
- } else {
- snprintf(buf, sizeof buf, "host:disconnect:");
- }
- std::string error;
- tmp = adb_query(buf, &error);
- if (tmp) {
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+
+ std::string query = android::base::StringPrintf("host:disconnect:%s",
+ (argc == 2) ? argv[1] : "");
+ return adb_query_command(query);
}
else if (!strcmp(argv[0], "emu")) {
return adb_send_emulator_command(argc, argv);
@@ -1241,7 +1178,7 @@
while (true) {
D("interactive shell loop. cmd=%s\n", cmd.c_str());
std::string error;
- int fd = adb_connect(cmd.c_str(), &error);
+ int fd = adb_connect(cmd, &error);
int r;
if (fd >= 0) {
D("about to read_and_dump(fd=%d)\n", fd);
@@ -1280,7 +1217,7 @@
}
std::string error;
- int fd = adb_connect(cmd.c_str(), &error);
+ int fd = adb_connect(cmd, &error);
if (fd < 0) {
fprintf(stderr, "error: %s\n", error.c_str());
return -1;
@@ -1385,18 +1322,12 @@
// Implement forward --list
if (list) {
- if (argc != 1)
+ if (argc != 1) {
return usage();
- snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
- std::string error;
- char* forwards = adb_query(buf, &error);
- if (forwards == NULL) {
- fprintf(stderr, "error: %s\n", error.c_str());
- return 1;
}
- printf("%s", forwards);
- free(forwards);
- return 0;
+
+ std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
+ return adb_query_command(query);
}
// Implement forward --remove-all
@@ -1523,21 +1454,9 @@
!strcmp(argv[0],"get-serialno") ||
!strcmp(argv[0],"get-devpath"))
{
- format_host_command(buf, sizeof buf, argv[0], ttype, serial);
- std::string error;
- char* tmp = adb_query(buf, &error);
- if (tmp) {
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
+ return adb_query_command(format_host_command(argv[0], ttype, serial));
}
/* other commands */
- else if (!strcmp(argv[0],"status-window")) {
- status_window(ttype, serial);
- return 0;
- }
else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
return logcat(ttype, serial, argc, argv);
}
@@ -1755,7 +1674,7 @@
// Create install session
std::string error;
- int fd = adb_connect(cmd.c_str(), &error);
+ int fd = adb_connect(cmd, &error);
if (fd < 0) {
fprintf(stderr, "Connect error for create: %s\n", error.c_str());
return -1;
@@ -1807,7 +1726,7 @@
}
std::string error;
- int remoteFd = adb_connect(cmd.c_str(), &error);
+ int remoteFd = adb_connect(cmd, &error);
if (remoteFd < 0) {
fprintf(stderr, "Connect error for write: %s\n", error.c_str());
adb_close(localFd);
@@ -1831,13 +1750,10 @@
finalize_session:
// Commit session if we streamed everything okay; otherwise abandon
- if (success) {
- snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
- } else {
- snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
- }
-
- fd = adb_connect(buf, &error);
+ std::string service =
+ android::base::StringPrintf("exec:pm install-%s %d",
+ success ? "commit" : "abandon", session_id);
+ fd = adb_connect(service, &error);
if (fd < 0) {
fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
return -1;
diff --git a/adb/transport.cpp b/adb/transport.cpp
index d395a80..45740a8 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -847,7 +847,7 @@
result = t;
} else if (ttype == kTransportAny) {
if (result) {
- if (error_out) *error_out = "more than one device and emulator";
+ if (error_out) *error_out = "more than one device/emulator";
ambiguous = 1;
result = NULL;
break;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 30e6bf5..4d93bb5 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -105,7 +105,7 @@
D("client: connected on remote on fd %d\n", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
- snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
+ snprintf(buf, sizeof buf, "emulator-%d", console_port);
register_socket_transport(fd, buf, adb_port, 1);
return 0;
}