Move __adb_error to std::string, and improve various errors.

Also remove an sprintf. Also fix various bits of code that were
reporting stale adb_error values when they meant strerror.

Bug: http://b/20666660
Change-Id: Ibeb48b7bc21bb0ec30ba47889d1d671ee480e1b7
diff --git a/adb_client.cpp b/adb_client.cpp
index 0f64998..e07c92c 100644
--- a/adb_client.cpp
+++ b/adb_client.cpp
@@ -29,6 +29,9 @@
 #include <sys/types.h>
 
 #include <string>
+#include <vector>
+
+#include <base/stringprintf.h>
 
 #include "adb_io.h"
 
@@ -63,10 +66,11 @@
         /* 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                 */
-        char*  tmp = adb_query("host:devices");
+        std::string error;
+        char*  tmp = adb_query("host:devices", &error);
         char*  p   = tmp;
-        if(!tmp) {
-            printf("no emulator connected\n");
+        if (!tmp) {
+            printf("no emulator connected: %s\n", error.c_str());
             return -1;
         }
         while (*p) {
@@ -101,15 +105,11 @@
     return port;
 }
 
-static char __adb_error[256] = { 0 };
-
-const char *adb_error(void)
-{
-    return __adb_error;
+std::string perror_str(const char* msg) {
+    return android::base::StringPrintf("%s: %s", msg, strerror(errno));
 }
 
-static int switch_socket_transport(int fd)
-{
+static int switch_socket_transport(int fd, std::string* error) {
     std::string service;
     if (__adb_serial) {
         service += "host:transport:";
@@ -137,70 +137,64 @@
     char tmp[5];
     snprintf(tmp, sizeof(tmp), "%04zx", service.size());
     if (!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service.c_str(), service.size())) {
-        strcpy(__adb_error, "write failure during connection");
+        *error = perror_str("write failure during connection");
         adb_close(fd);
         return -1;
     }
     D("Switch transport in progress\n");
 
-    if (adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
-        D("Switch transport failed\n");
+        D("Switch transport failed: %s\n", error->c_str());
         return -1;
     }
     D("Switch transport success\n");
     return 0;
 }
 
-int adb_status(int fd)
-{
-    unsigned char buf[5];
-    unsigned len;
+bool adb_status(int fd, std::string* error) {
+    char buf[5];
 
-    if(!ReadFdExactly(fd, buf, 4)) {
-        strcpy(__adb_error, "protocol fault (no status)");
-        return -1;
+    if (!ReadFdExactly(fd, buf, 4)) {
+        *error = perror_str("protocol fault (couldn't read status)");
+        return false;
     }
 
-    if(!memcmp(buf, "OKAY", 4)) {
-        return 0;
+    if (!memcmp(buf, "OKAY", 4)) {
+        return true;
     }
 
-    if(memcmp(buf, "FAIL", 4)) {
-        sprintf(__adb_error,
-                "protocol fault (status %02x %02x %02x %02x?!)",
-                buf[0], buf[1], buf[2], buf[3]);
-        return -1;
+    if (memcmp(buf, "FAIL", 4)) {
+        *error = android::base::StringPrintf("protocol fault (status %02x %02x %02x %02x?!)",
+                                             buf[0], buf[1], buf[2], buf[3]);
+        return false;
     }
 
-    if(!ReadFdExactly(fd, buf, 4)) {
-        strcpy(__adb_error, "protocol fault (status len)");
-        return -1;
+    if (!ReadFdExactly(fd, buf, 4)) {
+        *error = perror_str("protocol fault (couldn't read status length)");
+        return false;
     }
     buf[4] = 0;
-    len = strtoul((char*)buf, 0, 16);
-    if(len > 255) len = 255;
-    if(!ReadFdExactly(fd, __adb_error, len)) {
-        strcpy(__adb_error, "protocol fault (status read)");
-        return -1;
+
+    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)");
     }
-    __adb_error[len] = 0;
-    return -1;
+    return false;
 }
 
-int _adb_connect(const char *service)
-{
+int _adb_connect(const char *service, std::string* error) {
     char tmp[5];
-    int len;
     int fd;
 
     D("_adb_connect: %s\n", service);
-    len = strlen(service);
-    if((len < 1) || (len > 1024)) {
-        strcpy(__adb_error, "service name too long");
+    size_t len = strlen(service);
+    if ((len < 1) || (len > 1024)) {
+        *error = android::base::StringPrintf("service name too long (%zd)", len);
         return -1;
     }
-    snprintf(tmp, sizeof tmp, "%04x", len);
+    snprintf(tmp, sizeof tmp, "%04zx", len);
 
     if (__adb_server_name)
         fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
@@ -208,21 +202,21 @@
         fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
 
     if(fd < 0) {
-        strcpy(__adb_error, "cannot connect to daemon");
+        *error = perror_str("cannot connect to daemon");
         return -2;
     }
 
-    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
+    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd, error)) {
         return -1;
     }
 
     if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
-        strcpy(__adb_error, "write failure during connection");
+        *error = perror_str("write failure during connection");
         adb_close(fd);
         return -1;
     }
 
-    if(adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
         return -1;
     }
@@ -231,20 +225,19 @@
     return fd;
 }
 
-int adb_connect(const char *service)
-{
+int adb_connect(const char* service, std::string* error) {
     // first query the adb server's version
-    int fd = _adb_connect("host:version");
+    int fd = _adb_connect("host:version", error);
 
     D("adb_connect: service %s\n", service);
-    if(fd == -2 && __adb_server_name) {
+    if (fd == -2 && __adb_server_name) {
         fprintf(stderr,"** Cannot start server on remote host\n");
         return fd;
-    } else if(fd == -2) {
+    } else if (fd == -2) {
         fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
                 __adb_server_port);
     start_server:
-        if(launch_server(__adb_server_port)) {
+        if (launch_server(__adb_server_port)) {
             fprintf(stderr,"* failed to start daemon *\n");
             return -1;
         } else {
@@ -260,7 +253,7 @@
         int version = ADB_SERVER_VERSION - 1;
 
         // if we have a file descriptor, then parse version result
-        if(fd >= 0) {
+        if (fd >= 0) {
             if(!ReadFdExactly(fd, buf, 4)) goto error;
 
             buf[4] = 0;
@@ -273,13 +266,14 @@
         } 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
-            if (strcmp(__adb_error, "unknown host service") != 0)
+            if (*error == "unknown host service") {
                 return fd;
+            }
         }
 
         if(version != ADB_SERVER_VERSION) {
             printf("adb server is out of date.  killing...\n");
-            fd = _adb_connect("host:kill");
+            fd = _adb_connect("host:kill", error);
             adb_close(fd);
 
             /* XXX can we better detect its death? */
@@ -289,12 +283,13 @@
     }
 
     // if the command is start-server, we are done.
-    if (!strcmp(service, "host:start-server"))
+    if (!strcmp(service, "host:start-server")) {
         return 0;
+    }
 
-    fd = _adb_connect(service);
-    if(fd == -1) {
-        D("_adb_connect error: %s", __adb_error);
+    fd = _adb_connect(service, error);
+    if (fd == -1) {
+        D("_adb_connect error: %s", error->c_str());
     } else if(fd == -2) {
         fprintf(stderr,"** daemon still not running\n");
     }
@@ -307,15 +302,14 @@
 }
 
 
-int adb_command(const char *service)
-{
-    int fd = adb_connect(service);
-    if(fd < 0) {
-        fprintf(stderr, "error: %s\n", adb_error());
+int adb_command(const char* service, std::string* error) {
+    int fd = adb_connect(service, error);
+    if (fd < 0) {
+        fprintf(stderr, "error: %s\n", error->c_str());
         return -1;
     }
 
-    if(adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
         return -1;
     }
@@ -323,25 +317,25 @@
     return 0;
 }
 
-char *adb_query(const char *service)
-{
+char* adb_query(const char* service, std::string* error) {
     char buf[5];
     unsigned long n;
     char* tmp;
 
     D("adb_query: %s\n", service);
-    int fd = adb_connect(service);
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", __adb_error);
+    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;
+    if (!ReadFdExactly(fd, buf, 4)) goto oops;
 
     buf[4] = 0;
     n = strtoul(buf, 0, 16);
-    if(n >= 0xffff) {
-        strcpy(__adb_error, "reply is too long (>= 64kB)");
+    // 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;
     }