Merge "Clean up the locking in usb_linux.cpp."
diff --git a/adb/adb.h b/adb/adb.h
index 357be51..309b0e9 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -22,6 +22,8 @@
 
 #include <base/macros.h>
 
+#include <string>
+
 #include "adb_trace.h"
 #include "fdevent.h"
 
@@ -357,8 +359,8 @@
 
 
 void local_init(int port);
-int  local_connect(int  port);
-int  local_connect_arbitrary_ports(int console_port, int adb_port);
+void local_connect(int port);
+int  local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
 
 /* usb host/client interface */
 void usb_init();
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 75e888d..418662c 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -33,8 +33,10 @@
 
 #include <base/stringprintf.h>
 #include <base/strings.h>
+#include <cutils/sockets.h>
 
 #include "adb_io.h"
+#include "adb_utils.h"
 
 static TransportType __adb_transport = kTransportAny;
 static const char* __adb_serial = NULL;
@@ -152,13 +154,20 @@
 
     int fd;
     if (__adb_server_name) {
-        fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
+        std::string reason;
+        fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
+        if (fd == -1) {
+            *error = android::base::StringPrintf("can't connect to %s:%d: %s",
+                                                 __adb_server_name, __adb_server_port,
+                                                 reason.c_str());
+            return -2;
+        }
     } else {
         fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
-    }
-    if (fd < 0) {
-        *error = perror_str("cannot connect to daemon");
-        return -2;
+        if (fd == -1) {
+            *error = perror_str("cannot connect to daemon");
+            return -2;
+        }
     }
 
     if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index a15c513..bb45022 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #include <base/stringprintf.h>
+#include <cutils/sockets.h>
 
 #include "sysdeps.h"
 #include "transport.h"
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index e2af045..cd3c7bc 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -28,10 +28,17 @@
 #include <base/logging.h>
 #include <base/stringprintf.h>
 #include <base/strings.h>
+#include <cutils/sockets.h>
 
 #include "adb_trace.h"
 #include "sysdeps.h"
 
+#if defined(_WIN32)
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#endif
+
 bool getcwd(std::string* s) {
   char* cwd = getcwd(nullptr, 0);
   if (cwd != nullptr) *s = cwd;
@@ -158,3 +165,18 @@
                << " (" << *canonical_address << ")";
     return true;
 }
+
+int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
+    int getaddrinfo_error = 0;
+    int fd = socket_network_client_timeout(host.c_str(), port, type, timeout, &getaddrinfo_error);
+    if (fd != -1) {
+        return fd;
+    }
+    if (getaddrinfo_error != 0) {
+        // TODO: gai_strerror is not thread safe on Win32.
+        *error = gai_strerror(getaddrinfo_error);
+    } else {
+        *error = strerror(errno);
+    }
+    return -1;
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index e0aa1ba..d1a3f5f 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -39,4 +39,6 @@
                          std::string* host, int* port,
                          std::string* error);
 
+int network_connect(const std::string& host, int port, int type, int timeout, std::string* error);
+
 #endif
diff --git a/adb/console.cpp b/adb/console.cpp
index 0707960..b7f5345 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -18,9 +18,10 @@
 
 #include <stdio.h>
 
-#include "base/file.h"
-#include "base/logging.h"
-#include "base/strings.h"
+#include <base/file.h>
+#include <base/logging.h>
+#include <base/strings.h>
+#include <cutils/sockets.h>
 
 #include "adb.h"
 #include "adb_client.h"
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index a2e0f88..06e7780 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -22,6 +22,7 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
diff --git a/adb/services.cpp b/adb/services.cpp
index 2e3ad98..82efb1c 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -39,6 +39,7 @@
 #include <base/file.h>
 #include <base/stringprintf.h>
 #include <base/strings.h>
+#include <cutils/sockets.h>
 
 #if !ADB_HOST
 #include "cutils/android_reboot.h"
@@ -436,7 +437,8 @@
                 disable_tcp_nagle(ret);
         } else {
 #if ADB_HOST
-            ret = socket_network_client(name + 1, port, SOCK_STREAM);
+            std::string error;
+            ret = network_connect(name + 1, port, SOCK_STREAM, 0, &error);
 #else
             return -1;
 #endif
@@ -555,10 +557,11 @@
         return;
     }
 
-    int fd = socket_network_client_timeout(host.c_str(), port, SOCK_STREAM, 10);
+    std::string error;
+    int fd = network_connect(host.c_str(), port, SOCK_STREAM, 10, &error);
     if (fd == -1) {
         *response = android::base::StringPrintf("unable to connect to %s: %s",
-                                                serial.c_str(), strerror(errno));
+                                                serial.c_str(), error.c_str());
         return;
     }
 
@@ -612,12 +615,13 @@
     }
 
     // Preconditions met, try to connect to the emulator.
-    if (!local_connect_arbitrary_ports(console_port, adb_port)) {
+    std::string error;
+    if (!local_connect_arbitrary_ports(console_port, adb_port, &error)) {
         *response = android::base::StringPrintf("Connected to emulator on ports %d,%d",
                                                 console_port, adb_port);
     } else {
-        *response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d",
-                                                console_port, adb_port);
+        *response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d: %s",
+                                                console_port, adb_port, error.c_str());
     }
 }
 
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 5efdab5..6160923 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -24,6 +24,8 @@
 #  undef _WIN32
 #endif
 
+#include <errno.h>
+
 /*
  * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
  * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
@@ -185,14 +187,6 @@
 /* normally provided by <cutils/misc.h> */
 extern void*  load_file(const char*  pathname, unsigned*  psize);
 
-/* normally provided by <cutils/sockets.h> */
-extern int socket_loopback_client(int port, int type);
-extern int socket_network_client(const char *host, int port, int type);
-extern int socket_network_client_timeout(const char *host, int port, int type,
-                                         int timeout);
-extern int socket_loopback_server(int port, int type);
-extern int socket_inaddr_any_server(int port, int type);
-
 /* normally provided by "fdevent.h" */
 
 #define FDE_READ              0x0001
@@ -274,7 +268,6 @@
 #else /* !_WIN32 a.k.a. Unix */
 
 #include "fdevent.h"
-#include <cutils/sockets.h>
 #include <cutils/misc.h>
 #include <cutils/threads.h>
 #include <signal.h>
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index bdc6027..a274892 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -25,6 +25,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <cutils/sockets.h>
+
 #include "adb.h"
 
 extern void fatal(const char *fmt, ...);
@@ -668,55 +670,45 @@
 }
 
 
-int socket_network_client(const char *host, int port, int type)
-{
+int socket_network_client_timeout(const char *host, int port, int type, int timeout,
+                                  int* getaddrinfo_error) {
     FH  f = _fh_alloc( &_fh_socket_class );
-    struct hostent *hp;
-    struct sockaddr_in addr;
-    SOCKET s;
+    if (!f) return -1;
 
-    if (!f)
-        return -1;
+    if (!_winsock_init) _init_winsock();
 
-    if (!_winsock_init)
-        _init_winsock();
-
-    hp = gethostbyname(host);
+    hostent* hp = gethostbyname(host);
     if(hp == 0) {
         _fh_close(f);
         return -1;
     }
 
+    sockaddr_in addr;
     memset(&addr, 0, sizeof(addr));
     addr.sin_family = hp->h_addrtype;
     addr.sin_port = htons(port);
     memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
 
-    s = socket(hp->h_addrtype, type, 0);
+    SOCKET s = socket(hp->h_addrtype, type, 0);
     if(s == INVALID_SOCKET) {
         _fh_close(f);
         return -1;
     }
     f->fh_socket = s;
 
+    // TODO: implement timeouts for Windows.
+
     if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
         _fh_close(f);
         return -1;
     }
 
     snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
-    D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
+    D( "socket_network_client_timeout: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
     return _fh_to_int(f);
 }
 
 
-int socket_network_client_timeout(const char *host, int port, int type, int timeout)
-{
-    // TODO: implement timeouts for Windows.
-    return socket_network_client(host, port, type);
-}
-
-
 int socket_inaddr_any_server(int port, int type)
 {
     FH  f = _fh_alloc( &_fh_socket_class );
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 1adc69e..0dc9581 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 
 #include <base/stringprintf.h>
+#include <cutils/sockets.h>
 
 #if !ADB_HOST
 #include "cutils/properties.h"
@@ -33,6 +34,7 @@
 
 #include "adb.h"
 #include "adb_io.h"
+#include "adb_utils.h"
 
 #if ADB_HOST
 /* we keep a list of opened transports. The atransport struct knows to which
@@ -83,19 +85,18 @@
     return 0;
 }
 
-
-int local_connect(int port) {
-    return local_connect_arbitrary_ports(port-1, port);
+void local_connect(int port) {
+    std::string dummy;
+    local_connect_arbitrary_ports(port-1, port, &dummy);
 }
 
-int local_connect_arbitrary_ports(int console_port, int adb_port)
-{
-    int  fd = -1;
+int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error) {
+    int fd = -1;
 
 #if ADB_HOST
     const char *host = getenv("ADBHOST");
     if (host) {
-        fd = socket_network_client(host, adb_port, SOCK_STREAM);
+        fd = network_connect(host, adb_port, SOCK_STREAM, 0, error);
     }
 #endif
     if (fd < 0) {
@@ -126,7 +127,7 @@
     /* this is only done when ADB starts up. later, each new emulator */
     /* will send a message to ADB to indicate that is is starting up  */
     for ( ; count > 0; count--, port += 2 ) {
-        (void) local_connect(port);
+        local_connect(port);
     }
 #endif
     return 0;
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index f8076ca..07d1351 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -77,7 +77,7 @@
 extern int socket_loopback_client(int port, int type);
 extern int socket_network_client(const char *host, int port, int type);
 extern int socket_network_client_timeout(const char *host, int port, int type,
-                                         int timeout);
+                                         int timeout, int* getaddrinfo_error);
 extern int socket_loopback_server(int port, int type);
 extern int socket_local_server(const char *name, int namespaceId, int type);
 extern int socket_local_server_bind(int s, const char *name, int namespaceId);
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index 81b20fa..e5b153a 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -77,8 +77,8 @@
         return;
     }
 
-    char fingerprint[PROP_VALUE_MAX];
-    if (property_get("ro.build.fingerprint", fingerprint) == -1) {
+    std::string fingerprint = property_get("ro.build.fingerprint");
+    if (fingerprint.empty()) {
         return;
     }
 
@@ -92,7 +92,7 @@
     fprintf(out, "version = Android init 0.8 " __TIME__  "\n");
     fprintf(out, "title = Boot chart for Android (%s)\n", date);
     fprintf(out, "system.uname = %s %s %s %s\n", uts.sysname, uts.release, uts.version, uts.machine);
-    fprintf(out, "system.release = %s\n", fingerprint);
+    fprintf(out, "system.release = %s\n", fingerprint.c_str());
     // TODO: use /proc/cpuinfo "model name" line for x86, "Processor" line for arm.
     fprintf(out, "system.cpu = %s\n", uts.machine);
     fprintf(out, "system.kernel.options = %s\n", kernel_cmdline.c_str());
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 8d47da4..e2c033a 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -920,9 +920,8 @@
         return -1;
     }
 
-    char prop_value[PROP_VALUE_MAX] = {0};
-    property_get("ro.crypto.type", prop_value);
-    if (strcmp(prop_value, "file")) {
+    std::string prop_value = property_get("ro.crypto.type");
+    if (prop_value != "file") {
         return 0;
     }
 
diff --git a/init/init.cpp b/init/init.cpp
index 4d62c87..cd19647 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -76,7 +76,7 @@
 static struct command *cur_command = NULL;
 
 static int have_console;
-static char console_name[PROP_VALUE_MAX] = "/dev/console";
+static std::string console_name = "/dev/console";
 static time_t process_needs_restart;
 
 static const char *ENV[32];
@@ -160,7 +160,7 @@
 static void open_console()
 {
     int fd;
-    if ((fd = open(console_name, O_RDWR)) < 0) {
+    if ((fd = open(console_name.c_str(), O_RDWR)) < 0) {
         fd = open("/dev/null", O_RDWR);
     }
     ioctl(fd, TIOCSCTTY, 0);
@@ -727,12 +727,12 @@
 
 static int console_init_action(int nargs, char **args)
 {
-    char console[PROP_VALUE_MAX];
-    if (property_get("ro.boot.console", console) > 0) {
-        snprintf(console_name, sizeof(console_name), "/dev/%s", console);
+    std::string console = property_get("ro.boot.console");
+    if (!console.empty()) {
+        console_name = "/dev/" + console;
     }
 
-    int fd = open(console_name, O_RDWR | O_CLOEXEC);
+    int fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);
     if (fd >= 0)
         have_console = 1;
     close(fd);
@@ -793,9 +793,8 @@
         { "ro.boot.revision",   "ro.revision",   "0", },
     };
     for (size_t i = 0; i < ARRAY_SIZE(prop_map); i++) {
-        char value[PROP_VALUE_MAX];
-        int rc = property_get(prop_map[i].src_prop, value);
-        property_set(prop_map[i].dst_prop, (rc > 0) ? value : prop_map[i].default_value);
+        std::string value = property_get(prop_map[i].src_prop);
+        property_set(prop_map[i].dst_prop, (!value.empty()) ? value.c_str() : prop_map[i].default_value);
     }
 }
 
@@ -1054,8 +1053,8 @@
     queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
 
     // Don't mount filesystems or start core system services in charger mode.
-    char bootmode[PROP_VALUE_MAX];
-    if (property_get("ro.bootmode", bootmode) > 0 && strcmp(bootmode, "charger") == 0) {
+    std::string bootmode = property_get("ro.bootmode");
+    if (bootmode == "charger") {
         action_for_each_trigger("charger", action_add_queue_tail);
     } else {
         action_for_each_trigger("late-init", action_add_queue_tail);
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 956ed25..41b89f1 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -247,9 +247,7 @@
     while (*src_ptr && left > 0) {
         char *c;
         char prop[PROP_NAME_MAX + 1];
-        char prop_val[PROP_VALUE_MAX];
         int prop_len = 0;
-        int prop_val_len;
 
         c = strchr(src_ptr, '$');
         if (!c) {
@@ -307,14 +305,14 @@
             goto err;
         }
 
-        prop_val_len = property_get(prop, prop_val);
-        if (!prop_val_len) {
+        std::string prop_val = property_get(prop);
+        if (prop_val.empty()) {
             ERROR("property '%s' doesn't exist while expanding '%s'\n",
                   prop, src);
             goto err;
         }
 
-        ret = push_chars(&dst_ptr, &left, prop_val, prop_val_len);
+        ret = push_chars(&dst_ptr, &left, prop_val.c_str(), prop_val.size());
         if (ret < 0)
             goto err_nospace;
         src_ptr = c;
@@ -586,17 +584,13 @@
                 } else {
                      const char* equals = strchr(test, '=');
                      if (equals) {
-                         char prop_name[PROP_NAME_MAX + 1];
-                         char value[PROP_VALUE_MAX];
                          int length = equals - test;
                          if (length <= PROP_NAME_MAX) {
-                             int ret;
-                             memcpy(prop_name, test, length);
-                             prop_name[length] = 0;
+                             std::string prop_name(test, length);
+                             std::string value = property_get(prop_name.c_str());
 
                              /* does the property exist, and match the trigger value? */
-                             ret = property_get(prop_name, value);
-                             if (ret > 0 && (!strcmp(equals + 1, value) ||
+                             if (!value.empty() && (!strcmp(equals + 1, value.c_str()) ||
                                 !strcmp(equals + 1, "*"))) {
                                  continue;
                              }
diff --git a/init/keychords.cpp b/init/keychords.cpp
index 10d9573..c4ebdf9 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -64,19 +64,18 @@
 
 static void handle_keychord() {
     struct service *svc;
-    char adb_enabled[PROP_VALUE_MAX];
     int ret;
     __u16 id;
 
-    // Only handle keychords if adb is enabled.
-    property_get("init.svc.adbd", adb_enabled);
     ret = read(keychord_fd, &id, sizeof(id));
     if (ret != sizeof(id)) {
         ERROR("could not read keychord id\n");
         return;
     }
 
-    if (!strcmp(adb_enabled, "running")) {
+    // Only handle keychords if adb is enabled.
+    std::string adb_enabled = property_get("init.svc.adbd");
+    if (adb_enabled == "running") {
         svc = service_find_by_keychord(id);
         if (svc) {
             INFO("Starting service %s from keychord\n", svc->name);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 5b7a1cb..aa939a5 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -141,9 +141,10 @@
     return check_mac_perms(name, sctx);
 }
 
-int __property_get(const char *name, char *value)
-{
-    return __system_property_get(name, value);
+std::string property_get(const char* name) {
+    char value[PROP_VALUE_MAX] = {0};
+    __system_property_get(name, value);
+    return value;
 }
 
 static void write_persistent_property(const char *name, const char *value)
@@ -491,9 +492,8 @@
 
 static void load_override_properties() {
     if (ALLOW_LOCAL_PROP_OVERRIDE) {
-        char debuggable[PROP_VALUE_MAX];
-        int ret = property_get("ro.debuggable", debuggable);
-        if (ret && (strcmp(debuggable, "1") == 0)) {
+        std::string debuggable = property_get("ro.debuggable");
+        if (debuggable == "1") {
             load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE, NULL);
         }
     }
@@ -511,19 +511,17 @@
 }
 
 void load_recovery_id_prop() {
-    char fstab_filename[PROP_VALUE_MAX + sizeof(FSTAB_PREFIX)];
-    char propbuf[PROP_VALUE_MAX];
-    int ret = property_get("ro.hardware", propbuf);
-    if (!ret) {
+    std::string ro_hardware = property_get("ro.hardware");
+    if (ro_hardware.empty()) {
         ERROR("ro.hardware not set - unable to load recovery id\n");
         return;
     }
-    snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX "%s", propbuf);
+    std::string fstab_filename = FSTAB_PREFIX + ro_hardware;
 
-    std::unique_ptr<fstab, void(*)(fstab*)> tab(fs_mgr_read_fstab(fstab_filename),
+    std::unique_ptr<fstab, void(*)(fstab*)> tab(fs_mgr_read_fstab(fstab_filename.c_str()),
             fs_mgr_free_fstab);
     if (!tab) {
-        ERROR("unable to read fstab %s: %s\n", fstab_filename, strerror(errno));
+        ERROR("unable to read fstab %s: %s\n", fstab_filename.c_str(), strerror(errno));
         return;
     }
 
diff --git a/init/property_service.h b/init/property_service.h
index a27053d..51d7404 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -19,6 +19,7 @@
 
 #include <stddef.h>
 #include <sys/system_properties.h>
+#include <string>
 
 extern void property_init(void);
 extern void property_load_boot_defaults(void);
@@ -26,30 +27,9 @@
 extern void load_all_props(void);
 extern void start_property_service(void);
 void get_property_workspace(int *fd, int *sz);
-extern int __property_get(const char *name, char *value);
+std::string property_get(const char* name);
 extern int property_set(const char *name, const char *value);
 extern bool properties_initialized();
 
-#ifndef __clang__
-extern void __property_get_size_error()
-    __attribute__((__error__("property_get called with too small buffer")));
-#else
-extern void __property_get_size_error();
-#endif
-
-static inline
-__attribute__ ((always_inline))
-__attribute__ ((gnu_inline))
-#ifndef __clang__
-__attribute__ ((artificial))
-#endif
-int property_get(const char *name, char *value)
-{
-    size_t value_len = __builtin_object_size(value, 0);
-    if (value_len != PROP_VALUE_MAX)
-        __property_get_size_error();
-
-    return __property_get(name, value);
-}
 
 #endif	/* _INIT_PROPERTY_H */
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index c63fdaa..75924cb 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -59,11 +59,10 @@
     cb.func_log = selinux_klog_callback;
     selinux_set_callback(SELINUX_CB_LOG, cb);
 
-    char hardware[PROP_VALUE_MAX];
-    property_get("ro.hardware", hardware);
+    std::string hardware = property_get("ro.hardware");
 
     ueventd_parse_config_file("/ueventd.rc");
-    ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware).c_str());
+    ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware.c_str()).c_str());
 
     device_init();
 
diff --git a/libcutils/socket_network_client.c b/libcutils/socket_network_client.c
index 2610254..3610f1b 100644
--- a/libcutils/socket_network_client.c
+++ b/libcutils/socket_network_client.c
@@ -41,7 +41,10 @@
 // Connect to the given host and port.
 // 'timeout' is in seconds (0 for no timeout).
 // Returns a file descriptor or -1 on error.
-int socket_network_client_timeout(const char* host, int port, int type, int timeout) {
+// On error, check *getaddrinfo_error (for use with gai_strerror) first;
+// if that's 0, use errno instead.
+int socket_network_client_timeout(const char* host, int port, int type, int timeout,
+                                  int* getaddrinfo_error) {
     struct addrinfo hints;
     memset(&hints, 0, sizeof(hints));
     hints.ai_family = AF_UNSPEC;
@@ -51,7 +54,8 @@
     snprintf(port_str, sizeof(port_str), "%d", port);
 
     struct addrinfo* addrs;
-    if (getaddrinfo(host, port_str, &hints, &addrs) != 0) {
+    *getaddrinfo_error = getaddrinfo(host, port_str, &hints, &addrs);
+    if (getaddrinfo_error != 0) {
         return -1;
     }
 
@@ -116,5 +120,6 @@
 }
 
 int socket_network_client(const char* host, int port, int type) {
-    return socket_network_client_timeout(host, port, type, 0);
+    int getaddrinfo_error;
+    return socket_network_client_timeout(host, port, type, 0, &getaddrinfo_error);
 }