Merge "statically link adb and fastboot against libc++"
diff --git a/adb/Android.mk b/adb/Android.mk
index 5bba23e..3c48585 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -5,7 +5,11 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-ADB_CLANG :=
+ifeq ($(HOST_OS),windows)
+  adb_host_clang := false  # libc++ for mingw not ready yet.
+else
+  adb_host_clang := true
+endif
 
 # libadb
 # =========================================================
@@ -21,11 +25,17 @@
     adb_auth.cpp \
     adb_io.cpp \
     adb_listeners.cpp \
+    adb_utils.cpp \
     sockets.cpp \
     transport.cpp \
     transport_local.cpp \
     transport_usb.cpp \
 
+LIBADB_TEST_SRCS := \
+    adb_io_test.cpp \
+    adb_utils_test.cpp \
+    transport_test.cpp \
+
 LIBADB_CFLAGS := \
     -Wall -Werror \
     -Wno-unused-parameter \
@@ -34,8 +44,8 @@
 
 LIBADB_darwin_SRC_FILES := \
     fdevent.cpp \
-    get_my_path_darwin.c \
-    usb_osx.c \
+    get_my_path_darwin.cpp \
+    usb_osx.cpp \
 
 LIBADB_linux_SRC_FILES := \
     fdevent.cpp \
@@ -44,11 +54,11 @@
 
 LIBADB_windows_SRC_FILES := \
     get_my_path_windows.cpp \
-    sysdeps_win32.c \
+    sysdeps_win32.cpp \
     usb_windows.cpp \
 
 include $(CLEAR_VARS)
-LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_CLANG := true
 LOCAL_MODULE := libadbd
 LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=0
 LOCAL_SRC_FILES := \
@@ -57,12 +67,12 @@
     fdevent.cpp \
     jdwp_service.cpp \
     qemu_tracing.cpp \
-    usb_linux_client.c \
+    usb_linux_client.cpp \
 
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
-LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_CLANG := $(adb_host_clang)
 LOCAL_MODULE := libadb
 LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=1
 LOCAL_SRC_FILES := \
@@ -80,12 +90,8 @@
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 
-LIBADB_TEST_SRCS := \
-    adb_io_test.cpp \
-    transport_test.cpp \
-
 include $(CLEAR_VARS)
-LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_CLANG := true
 LOCAL_MODULE := adbd_test
 LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS)
 LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS)
@@ -94,7 +100,7 @@
 include $(BUILD_NATIVE_TEST)
 
 include $(CLEAR_VARS)
-LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_CLANG := $(adb_host_clang)
 LOCAL_MODULE := adb_test
 LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
 LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.cpp
@@ -108,6 +114,10 @@
   LOCAL_LDLIBS += -lrt -ldl -lpthread
 endif
 
+ifeq ($(HOST_OS),darwin)
+  LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
+endif
+
 include $(BUILD_HOST_NATIVE_TEST)
 
 # adb host tool
@@ -125,15 +135,11 @@
 endif
 
 ifeq ($(HOST_OS),windows)
+  LOCAL_LDLIBS += -lws2_32 -lgdi32
   EXTRA_STATIC_LIBS := AdbWinApi
-  ifneq ($(strip $(USE_MINGW)),)
-    # MinGW under Linux case
-    LOCAL_LDLIBS += -lws2_32 -lgdi32
-    USE_SYSDEPS_WIN32 := 1
-  endif
 endif
 
-LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_CLANG := $(adb_host_clang)
 
 LOCAL_SRC_FILES := \
     adb_main.cpp \
@@ -154,13 +160,11 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libadb \
+    libbase \
     libcrypto_static \
+    libcutils \
     $(EXTRA_STATIC_LIBS) \
 
-ifeq ($(USE_SYSDEPS_WIN32),)
-    LOCAL_STATIC_LIBRARIES += libcutils
-endif
-
 LOCAL_CXX_STL := libc++_static
 
 # Don't add anything here, we don't want additional shared dependencies
@@ -184,7 +188,7 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_CLANG := $(ADB_CLANG)
+LOCAL_CLANG := true
 
 LOCAL_SRC_FILES := \
     adb_main.cpp \
diff --git a/adb/adb.cpp b/adb/adb.cpp
index ad85184f..b09e853 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -838,10 +838,10 @@
             }
         }
 
-        const char* err;
-        transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
+        std::string error_msg;
+        transport = acquire_one_transport(CS_ANY, ttype, serial, &error_msg);
         if (!transport) {
-            sendfailmsg(reply_fd, err);
+            sendfailmsg(reply_fd, error_msg.c_str());
             return 1;
         }
 
@@ -910,14 +910,14 @@
             serial = service;
         }
 
-        const char* error_string = "unknown failure";
-        transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
+        std::string error_msg = "unknown failure";
+        transport = acquire_one_transport(CS_ANY, type, serial, &error_msg);
 
         if (transport) {
             s->transport = transport;
             adb_write(reply_fd, "OKAY", 4);
         } else {
-            sendfailmsg(reply_fd, error_string);
+            sendfailmsg(reply_fd, error_msg.c_str());
         }
         return 1;
     }
@@ -975,7 +975,7 @@
     if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
         const char *out = "unknown";
         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
-       if (transport && transport->serial) {
+        if (transport && transport->serial) {
             out = transport->serial;
         }
         send_msg_with_okay(reply_fd, out, strlen(out));
@@ -984,7 +984,7 @@
     if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
         const char *out = "unknown";
         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
-       if (transport && transport->devpath) {
+        if (transport && transport->devpath) {
             out = transport->devpath;
         }
         send_msg_with_okay(reply_fd, out, strlen(out));
diff --git a/adb/adb.h b/adb/adb.h
index 749515c..cb2cf60 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -23,10 +23,6 @@
 #include "adb_trace.h"
 #include "fdevent.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define MAX_PAYLOAD 4096
 
 #define A_SYNC 0x434e5953
@@ -47,14 +43,8 @@
 // Increment this when we want to force users to start a new adb server.
 #define ADB_SERVER_VERSION 32
 
-typedef struct amessage amessage;
-typedef struct apacket apacket;
-typedef struct asocket asocket;
-typedef struct alistener alistener;
-typedef struct aservice aservice;
-typedef struct atransport atransport;
-typedef struct adisconnect  adisconnect;
-typedef struct usb_handle usb_handle;
+struct atransport;
+struct usb_handle;
 
 struct amessage {
     unsigned command;       /* command identifier constant      */
@@ -171,12 +161,12 @@
 ** object, it's a special value used to indicate that a client wants to
 ** connect to a service implemented within the ADB server itself.
 */
-typedef enum transport_type {
+enum transport_type {
         kTransportUsb,
         kTransportLocal,
         kTransportAny,
         kTransportHost,
-} transport_type;
+};
 
 #define TOKEN_SIZE 20
 
@@ -363,10 +353,10 @@
 extern int HOST;
 extern int SHELL_EXIT_NOTIFY_FD;
 
-typedef enum {
+enum subproc_mode {
     SUBPROC_PTY = 0,
     SUBPROC_RAW = 1,
-} subproc_mode;
+} ;
 
 #define CHUNK_SIZE (64*1024)
 
@@ -389,8 +379,4 @@
 
 void send_connect(atransport *t);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 635556e..1e1978d 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -19,10 +19,6 @@
 
 #include "adb.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern int auth_enabled;
 
 int adb_auth_keygen(const char* filename);
@@ -68,8 +64,4 @@
 
 #endif // ADB_HOST
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif // __ADB_AUTH_H
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 9af176f..934362a 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -3,10 +3,6 @@
 
 #include "adb.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* connect to adb, connect to the named service, and return
 ** a valid fd for interacting with that service upon success
 ** or a negative number on failure
@@ -58,8 +54,4 @@
 */
 int adb_status(int fd);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/adb/adb_io.h b/adb/adb_io.h
index 7d09e7b..8d237ce 100644
--- a/adb/adb_io.h
+++ b/adb/adb_io.h
@@ -20,10 +20,6 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * Reads exactly len bytes from fd into buf.
  *
@@ -46,8 +42,4 @@
 /* Same as WriteFdExactly, but with an implicit len = strlen(buf). */
 bool WriteStringFully(int fd, const char* str);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* ADB_IO_H */
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 14fdcd6..6421df1 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -19,17 +19,13 @@
 
 #include "adb.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 // error/status codes for install_listener.
-typedef enum {
+enum install_status_t {
   INSTALL_STATUS_OK = 0,
   INSTALL_STATUS_INTERNAL_ERROR = -1,
   INSTALL_STATUS_CANNOT_BIND = -2,
   INSTALL_STATUS_CANNOT_REBIND = -3,
-} install_status_t;
+};
 
 extern alistener listener_list;
 
@@ -47,8 +43,4 @@
 int remove_listener(const char *local_name, atransport* transport);
 void remove_all_listeners(void);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __ADB_LISTENERS_H */
diff --git a/adb/adb_main.cpp b/adb/adb_main.cpp
index fb17e89..5acaf80 100644
--- a/adb/adb_main.cpp
+++ b/adb/adb_main.cpp
@@ -383,7 +383,7 @@
     /* If adbd runs inside the emulator this will enable adb tracing via
      * adb-debug qemud service in the emulator. */
     adb_qemu_trace_init();
-    while (1) {
+    while (true) {
         int c;
         int option_index = 0;
         static struct option opts[] = {
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index ef5dc24..32b6ae4 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -23,10 +23,6 @@
 #include <stdio.h>
 #endif
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
 #define  ADB_TRACE    1
 
@@ -34,7 +30,7 @@
  * forget to update the corresponding 'tags' table in
  * the adb_trace_init() function implemented in adb.c
  */
-typedef enum {
+enum AdbTrace {
     TRACE_ADB = 0,   /* 0x001 */
     TRACE_SOCKETS,
     TRACE_PACKETS,
@@ -47,7 +43,7 @@
     TRACE_SERVICES,
     TRACE_AUTH,
     TRACE_FDEVENT,
-} AdbTrace;
+} ;
 
 #if ADB_TRACE
 
@@ -148,8 +144,4 @@
 #  define  ADB_TRACING     0
 #endif /* ADB_TRACE */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __ADB_TRACE_H */
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
new file mode 100644
index 0000000..710ef3c
--- /dev/null
+++ b/adb/adb_utils.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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 "adb_utils.h"
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sysdeps.h"
+
+bool getcwd(std::string* s) {
+  char* cwd = getcwd(nullptr, 0);
+  if (cwd != nullptr) *s = cwd;
+  free(cwd);
+  return (cwd != nullptr);
+}
+
+bool directory_exists(const std::string& path) {
+  struct stat sb;
+  return lstat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode);
+}
+
+static bool should_escape(const char c) {
+  return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
+}
+
+std::string escape_arg(const std::string& s) {
+  // Preserve empty arguments.
+  if (s.empty()) return "\"\"";
+
+  std::string result(s);
+  for (auto it = result.begin(); it != result.end(); ++it) {
+      if (should_escape(*it)) {
+          it = result.insert(it, '\\') + 1;
+      }
+  }
+  return result;
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
new file mode 100644
index 0000000..4b64afa
--- /dev/null
+++ b/adb/adb_utils.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef _ADB_UTILS_H_
+#define _ADB_UTILS_H_
+
+#include <string>
+
+bool getcwd(std::string* cwd);
+bool directory_exists(const std::string& path);
+
+std::string escape_arg(const std::string& s);
+
+#endif
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
new file mode 100644
index 0000000..95e28a8
--- /dev/null
+++ b/adb/adb_utils_test.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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 "adb_utils.h"
+
+#include <gtest/gtest.h>
+
+TEST(adb_utils, directory_exists) {
+  ASSERT_TRUE(directory_exists("/proc"));
+  ASSERT_FALSE(directory_exists("/proc/self")); // Symbolic link.
+  ASSERT_FALSE(directory_exists("/proc/does-not-exist"));
+}
+
+TEST(adb_utils, escape_arg) {
+  ASSERT_EQ(R"("")", escape_arg(""));
+
+  ASSERT_EQ(R"(abc)", escape_arg("abc"));
+
+  ASSERT_EQ(R"(\ abc)", escape_arg(" abc"));
+  ASSERT_EQ(R"(\'abc)", escape_arg("'abc"));
+  ASSERT_EQ(R"(\"abc)", escape_arg("\"abc"));
+  ASSERT_EQ(R"(\\abc)", escape_arg("\\abc"));
+  ASSERT_EQ(R"(\(abc)", escape_arg("(abc"));
+  ASSERT_EQ(R"(\)abc)", escape_arg(")abc"));
+
+  ASSERT_EQ(R"(abc\ abc)", escape_arg("abc abc"));
+  ASSERT_EQ(R"(abc\'abc)", escape_arg("abc'abc"));
+  ASSERT_EQ(R"(abc\"abc)", escape_arg("abc\"abc"));
+  ASSERT_EQ(R"(abc\\abc)", escape_arg("abc\\abc"));
+  ASSERT_EQ(R"(abc\(abc)", escape_arg("abc(abc"));
+  ASSERT_EQ(R"(abc\)abc)", escape_arg("abc)abc"));
+
+  ASSERT_EQ(R"(abc\ )", escape_arg("abc "));
+  ASSERT_EQ(R"(abc\')", escape_arg("abc'"));
+  ASSERT_EQ(R"(abc\")", escape_arg("abc\""));
+  ASSERT_EQ(R"(abc\\)", escape_arg("abc\\"));
+  ASSERT_EQ(R"(abc\()", escape_arg("abc("));
+  ASSERT_EQ(R"(abc\))", escape_arg("abc)"));
+}
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 34efefe..f193d2f 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -21,6 +21,7 @@
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <stdarg.h>
 #include <stdint.h>
@@ -30,6 +31,10 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <string>
+
+#include <base/stringprintf.h>
+
 #if !defined(_WIN32)
 #include <termios.h>
 #include <unistd.h>
@@ -39,49 +44,38 @@
 #include "adb_auth.h"
 #include "adb_client.h"
 #include "adb_io.h"
+#include "adb_utils.h"
 #include "file_sync_service.h"
 
 static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
 
-int find_sync_dirs(const char *srcarg,
-        char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
-        char **oem_srcdir_out);
-int install_app(transport_type transport, const char* serial, int argc,
-                const char** argv);
-int install_multiple_app(transport_type transport, const char* serial, int argc,
+static int install_app(transport_type transport, const char* serial, int argc,
+                       const char** argv);
+static int install_multiple_app(transport_type transport, const char* serial, int argc,
+                                const char** argv);
+static int uninstall_app(transport_type transport, const char* serial, int argc,
                          const char** argv);
-int uninstall_app(transport_type transport, const char* serial, int argc,
-                  const char** argv);
 
-static const char *gProductOutPath = NULL;
+static std::string gProductOutPath;
 extern int gListenAll;
 
-static char *product_file(const char *extra)
-{
-    if (gProductOutPath == NULL) {
+static std::string product_file(const char *extra) {
+    if (gProductOutPath.empty()) {
         fprintf(stderr, "adb: Product directory not specified; "
                 "use -p or define ANDROID_PRODUCT_OUT\n");
         exit(1);
     }
 
-    int n = strlen(gProductOutPath) + strlen(extra) + 2;
-    char* x = reinterpret_cast<char*>(malloc(n));
-    if (x == 0) {
-        fprintf(stderr, "adb: Out of memory (product_file())\n");
-        exit(1);
-    }
-
-    snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
-    return x;
+    return android::base::StringPrintf("%s%s%s",
+                                       gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
 }
 
-void version(FILE * out) {
+static void version(FILE* out) {
     fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
-         ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
+            ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
 }
 
-void help()
-{
+static void help() {
     version(stderr);
 
     fprintf(stderr,
@@ -241,19 +235,16 @@
         );
 }
 
-int usage()
-{
+static int usage() {
     help();
     return 1;
 }
 
 #if defined(_WIN32)
 
-// Implemented in sysdeps_win32.c.
-extern "C" {
+// Implemented in sysdeps_win32.cpp.
 void stdin_raw_init(int fd);
 void stdin_raw_restore(int fd);
-}
 
 #else
 static termios g_saved_terminal_state;
@@ -330,7 +321,7 @@
         stdin_raw_init(STDIN_FILENO);
     }
 
-    for (;;) {
+    while (true) {
         if (inFd == STDIN_FILENO) {
             len = unix_read(inFd, buf, BUFSIZE);
         } else {
@@ -416,8 +407,7 @@
     return 0;
 }
 
-int interactive_shell(void)
-{
+static int interactive_shell() {
     adb_thread_t thr;
     int fdi, fd;
 
@@ -455,8 +445,8 @@
     }
 }
 
-int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
-                        unsigned progress)
+static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
+                               unsigned progress)
 {
     char buf[4096];
     unsigned total;
@@ -514,23 +504,6 @@
     return 0;
 }
 
-
-int adb_download(const char *service, const char *fn, unsigned progress)
-{
-    void *data;
-    unsigned sz;
-
-    data = load_file(fn, &sz);
-    if(data == 0) {
-        fprintf(stderr,"* cannot read '%s' *\n", fn);
-        return -1;
-    }
-
-    int status = adb_download_buffer(service, fn, data, sz, progress);
-    free(data);
-    return status;
-}
-
 #define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
 
 /*
@@ -552,7 +525,7 @@
  * - When the other side sends "DONEDONE" instead of a block number,
  *   we hang up.
  */
-int adb_sideload_host(const char* fn) {
+static int adb_sideload_host(const char* fn) {
     unsigned sz;
     size_t xfer = 0;
     int status;
@@ -581,7 +554,7 @@
 
     opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
 
-    for (;;) {
+    while (true) {
         if (!ReadFdExactly(fd, buf, 8)) {
             fprintf(stderr, "* failed to read command: %s\n", adb_error());
             status = -1;
@@ -683,50 +656,6 @@
     }
 }
 
-static int should_escape(const char c)
-{
-    return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
-}
-
-/* Duplicate and escape given argument. */
-static char *escape_arg(const char *s)
-{
-    const char *ts;
-    size_t alloc_len;
-    char *ret;
-    char *dest;
-
-    alloc_len = 0;
-    for (ts = s; *ts != '\0'; ts++) {
-        alloc_len++;
-        if (should_escape(*ts)) {
-            alloc_len++;
-        }
-    }
-
-    if (alloc_len == 0) {
-        // Preserve empty arguments
-        ret = (char *) malloc(3);
-        ret[0] = '\"';
-        ret[1] = '\"';
-        ret[2] = '\0';
-        return ret;
-    }
-
-    ret = (char *) malloc(alloc_len + 1);
-    dest = ret;
-
-    for (ts = s; *ts != '\0'; ts++) {
-        if (should_escape(*ts)) {
-            *dest++ = '\\';
-        }
-        *dest++ = *ts;
-    }
-    *dest++ = '\0';
-
-    return ret;
-}
-
 /**
  * Run ppp in "notty" mode against a resource listed as the first parameter
  * eg:
@@ -734,8 +663,7 @@
  * ppp dev:/dev/omap_csmi_tty0 <ppp options>
  *
  */
-int ppp(int argc, const char **argv)
-{
+static int ppp(int argc, const char** argv) {
 #if defined(_WIN32)
     fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
     return -1;
@@ -800,14 +728,12 @@
 #endif /* !defined(_WIN32) */
 }
 
-static int send_shellcommand(transport_type transport, const char* serial,
-                             char* buf)
-{
-    int fd, ret;
-
-    for(;;) {
-        fd = adb_connect(buf);
-        if(fd >= 0)
+static int send_shell_command(transport_type transport, const char* serial,
+                              const std::string& command) {
+    int fd;
+    while (true) {
+        fd = adb_connect(command.c_str());
+        if (fd >= 0)
             break;
         fprintf(stderr,"- waiting for device -\n");
         adb_sleep_ms(1000);
@@ -815,41 +741,30 @@
     }
 
     read_and_dump(fd);
-    ret = adb_close(fd);
-    if (ret)
+    int rc = adb_close(fd);
+    if (rc) {
         perror("close");
-
-    return ret;
+    }
+    return rc;
 }
 
-static int logcat(transport_type transport, const char* serial, int argc,
-                  const char** argv)
-{
-    char buf[4096];
+static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
+    char* log_tags = getenv("ANDROID_LOG_TAGS");
+    std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
 
-    char *log_tags;
-    char *quoted;
-
-    log_tags = getenv("ANDROID_LOG_TAGS");
-    quoted = escape_arg(log_tags == NULL ? "" : log_tags);
-    snprintf(buf, sizeof(buf),
-            "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
-    free(quoted);
+    std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
 
     if (!strcmp(argv[0], "longcat")) {
-        strncat(buf, " -v long", sizeof(buf) - 1);
+        cmd += " -v long";
     }
 
-    argc -= 1;
-    argv += 1;
-    while(argc-- > 0) {
-        quoted = escape_arg(*argv++);
-        strncat(buf, " ", sizeof(buf) - 1);
-        strncat(buf, quoted, sizeof(buf) - 1);
-        free(quoted);
+    --argc;
+    ++argv;
+    while (argc-- > 0) {
+        cmd += " " + escape_arg(*argv++);
     }
 
-    send_shellcommand(transport, serial, buf);
+    send_shell_command(transport, serial, cmd);
     return 0;
 }
 
@@ -873,21 +788,17 @@
 }
 
 static int backup(int argc, const char** argv) {
-    char buf[4096];
-    char default_name[32];
-    const char* filename = strcpy(default_name, "./backup.ab");
-    int fd, outFd;
-    int i, j;
+    const char* filename = "./backup.ab";
 
     /* find, extract, and use any -f argument */
-    for (i = 1; i < argc; i++) {
+    for (int i = 1; i < argc; i++) {
         if (!strcmp("-f", argv[i])) {
             if (i == argc-1) {
                 fprintf(stderr, "adb: -f passed with no filename\n");
                 return usage();
             }
             filename = argv[i+1];
-            for (j = i+2; j <= argc; ) {
+            for (int j = i+2; j <= argc; ) {
                 argv[i++] = argv[j++];
             }
             argc -= 2;
@@ -900,20 +811,21 @@
 
     adb_unlink(filename);
     mkdirs(filename);
-    outFd = adb_creat(filename, 0640);
+    int outFd = adb_creat(filename, 0640);
     if (outFd < 0) {
         fprintf(stderr, "adb: unable to open file %s\n", filename);
         return -1;
     }
 
-    snprintf(buf, sizeof(buf), "backup");
-    for (argc--, argv++; argc; argc--, argv++) {
-        strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
-        strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
+    std::string cmd = "backup:";
+    --argc;
+    ++argv;
+    while (argc-- > 0) {
+        cmd += " " + escape_arg(*argv++);
     }
 
-    D("backup. filename=%s buf=%s\n", filename, buf);
-    fd = adb_connect(buf);
+    D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
+    int fd = adb_connect(cmd.c_str());
     if (fd < 0) {
         fprintf(stderr, "adb: unable to connect for backup\n");
         adb_close(outFd);
@@ -956,81 +868,9 @@
     return 0;
 }
 
-#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
-static int top_works(const char *top)
-{
-    if (top != NULL && adb_is_absolute_host_path(top)) {
-        char path_buf[PATH_MAX];
-        snprintf(path_buf, sizeof(path_buf),
-                "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
-        return access(path_buf, F_OK) == 0;
-    }
-    return 0;
-}
-
-static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
-{
-    strcpy(path_buf, indir);
-    while (1) {
-        if (top_works(path_buf)) {
-            return path_buf;
-        }
-        char *s = adb_dirstop(path_buf);
-        if (s != NULL) {
-            *s = '\0';
-        } else {
-            path_buf[0] = '\0';
-            return NULL;
-        }
-    }
-}
-
-static char *find_top(char path_buf[PATH_MAX])
-{
-    char *top = getenv("ANDROID_BUILD_TOP");
-    if (top != NULL && top[0] != '\0') {
-        if (!top_works(top)) {
-            fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
-            return NULL;
-        }
-    } else {
-        top = getenv("TOP");
-        if (top != NULL && top[0] != '\0') {
-            if (!top_works(top)) {
-                fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
-                return NULL;
-            }
-        } else {
-            top = NULL;
-        }
-    }
-
-    if (top != NULL) {
-        /* The environment pointed to a top directory that works.
-         */
-        strcpy(path_buf, top);
-        return path_buf;
-    }
-
-    /* The environment didn't help.  Walk up the tree from the CWD
-     * to see if we can find the top.
-     */
-    char dir[PATH_MAX];
-    top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
-    if (top == NULL) {
-        /* If the CWD isn't under a good-looking top, see if the
-         * executable is.
-         */
-        get_my_path(dir, PATH_MAX);
-        top = find_top_from(dir, path_buf);
-    }
-    return top;
-}
-
 /* <hint> may be:
  * - A simple product name
  *   e.g., "sooner"
-TODO: debug?  sooner-debug, sooner:debug?
  * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
  *   e.g., "out/target/product/sooner"
  * - An absolute path to the PRODUCT_OUT dir
@@ -1039,62 +879,52 @@
  * Given <hint>, try to construct an absolute path to the
  * ANDROID_PRODUCT_OUT dir.
  */
-static const char *find_product_out_path(const char *hint)
-{
-    static char path_buf[PATH_MAX];
-
+static std::string find_product_out_path(const char* hint) {
     if (hint == NULL || hint[0] == '\0') {
-        return NULL;
+        return "";
     }
 
-    /* If it's already absolute, don't bother doing any work.
-     */
+    // If it's already absolute, don't bother doing any work.
     if (adb_is_absolute_host_path(hint)) {
-        strcpy(path_buf, hint);
-        return path_buf;
+        return hint;
     }
 
-    /* If there are any slashes in it, assume it's a relative path;
-     * make it absolute.
-     */
-    if (adb_dirstart(hint) != NULL) {
-        if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
-            fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
-            return NULL;
+    // If there are any slashes in it, assume it's a relative path;
+    // make it absolute.
+    if (adb_dirstart(hint) != nullptr) {
+        std::string cwd;
+        if (!getcwd(&cwd)) {
+            fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
+            return "";
         }
-        if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
-            fprintf(stderr, "adb: Couldn't assemble path\n");
-            return NULL;
-        }
-        strcat(path_buf, OS_PATH_SEPARATOR_STR);
-        strcat(path_buf, hint);
-        return path_buf;
+        return android::base::StringPrintf("%s%s%s", cwd.c_str(), OS_PATH_SEPARATOR_STR, hint);
     }
 
-    /* It's a string without any slashes.  Try to do something with it.
-     *
-     * Try to find the root of the build tree, and build a PRODUCT_OUT
-     * path from there.
-     */
-    char top_buf[PATH_MAX];
-    const char *top = find_top(top_buf);
-    if (top == NULL) {
-        fprintf(stderr, "adb: Couldn't find top of build tree\n");
-        return NULL;
+    // It's a string without any slashes.  Try to do something with it.
+    //
+    // Try to find the root of the build tree, and build a PRODUCT_OUT
+    // path from there.
+    char* top = getenv("ANDROID_BUILD_TOP");
+    if (top == nullptr) {
+        fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
+        return "";
     }
-//TODO: if we have a way to indicate debug, look in out/debug/target/...
-    snprintf(path_buf, sizeof(path_buf),
-            "%s" OS_PATH_SEPARATOR_STR
-            "out" OS_PATH_SEPARATOR_STR
-            "target" OS_PATH_SEPARATOR_STR
-            "product" OS_PATH_SEPARATOR_STR
-            "%s", top_buf, hint);
-    if (access(path_buf, F_OK) < 0) {
-        fprintf(stderr, "adb: Couldn't find a product dir "
-                "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
-        return NULL;
+
+    std::string path = top;
+    path += OS_PATH_SEPARATOR_STR;
+    path += "out";
+    path += OS_PATH_SEPARATOR_STR;
+    path += "target";
+    path += OS_PATH_SEPARATOR_STR;
+    path += "product";
+    path += OS_PATH_SEPARATOR_STR;
+    path += hint;
+    if (!directory_exists(path)) {
+        fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
+                        "\"%s\" doesn't exist\n", hint, path.c_str());
+        return "";
     }
-    return path_buf;
+    return path;
 }
 
 static void parse_push_pull_args(const char **arg, int narg, char const **path1,
@@ -1149,15 +979,14 @@
     const char* serial = NULL;
     const char* server_port_str = NULL;
 
-        /* If defined, this should be an absolute path to
-         * the directory containing all of the various system images
-         * for a particular product.  If not defined, and the adb
-         * command requires this information, then the user must
-         * specify the path using "-p".
-         */
-    gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
-    if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
-        gProductOutPath = NULL;
+    // If defined, this should be an absolute path to
+    // the directory containing all of the various system images
+    // for a particular product.  If not defined, and the adb
+    // command requires this information, then the user must
+    // specify the path using "-p".
+    char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
+    if (ANDROID_PRODUCT_OUT != nullptr) {
+        gProductOutPath = ANDROID_PRODUCT_OUT;
     }
     // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
 
@@ -1198,9 +1027,8 @@
                 product = argv[0] + 2;
             }
             gProductOutPath = find_product_out_path(product);
-            if (gProductOutPath == NULL) {
-                fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
-                        product);
+            if (gProductOutPath.empty()) {
+                fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
                 return usage();
             }
         } else if (argv[0][0]=='-' && argv[0][1]=='s') {
@@ -1372,9 +1200,6 @@
         return adb_send_emulator_command(argc, argv);
     }
     else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
-        int r;
-        int fd;
-
         char h = (argv[0][0] == 'h');
 
         if (h) {
@@ -1392,19 +1217,18 @@
             return r;
         }
 
-        snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
+        std::string cmd = "shell:";
+        cmd += argv[1];
         argc -= 2;
         argv += 2;
         while (argc-- > 0) {
-            char *quoted = escape_arg(*argv++);
-            strncat(buf, " ", sizeof(buf) - 1);
-            strncat(buf, quoted, sizeof(buf) - 1);
-            free(quoted);
+            cmd += " " + escape_arg(*argv++);
         }
 
-        for(;;) {
-            D("interactive shell loop. buff=%s\n", buf);
-            fd = adb_connect(buf);
+        while (true) {
+            D("interactive shell loop. cmd=%s\n", cmd.c_str());
+            int fd = adb_connect(cmd.c_str());
+            int r;
             if (fd >= 0) {
                 D("about to read_and_dump(fd=%d)\n", fd);
                 read_and_dump(fd);
@@ -1432,19 +1256,16 @@
     }
     else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
         int exec_in = !strcmp(argv[0], "exec-in");
-        int fd;
 
-        snprintf(buf, sizeof buf, "exec:%s", argv[1]);
+        std::string cmd = "exec:";
+        cmd += argv[1];
         argc -= 2;
         argv += 2;
         while (argc-- > 0) {
-            char *quoted = escape_arg(*argv++);
-            strncat(buf, " ", sizeof(buf) - 1);
-            strncat(buf, quoted, sizeof(buf) - 1);
-            free(quoted);
+            cmd += " " + escape_arg(*argv++);
         }
 
-        fd = adb_connect(buf);
+        int fd = adb_connect(cmd.c_str());
         if (fd < 0) {
             fprintf(stderr, "error: %s\n", adb_error());
             return -1;
@@ -1636,46 +1457,55 @@
         return uninstall_app(ttype, serial, argc, argv);
     }
     else if (!strcmp(argv[0], "sync")) {
-        const char* srcarg;
-        char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
-
-        int listonly = 0;
-
-        int ret;
+        std::string src_arg;
+        bool list_only = false;
         if (argc < 2) {
-            /* No local path was specified. */
-            srcarg = NULL;
+            // No local path was specified.
+            src_arg = "";
         } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
-            listonly = 1;
+            list_only = 1;
             if (argc == 3) {
-                srcarg = argv[2];
+                src_arg = argv[2];
             } else {
-                srcarg = NULL;
+                src_arg = "";
             }
         } else if (argc == 2) {
-            /* A local path or "android"/"data" arg was specified. */
-            srcarg = argv[1];
+            // A local path or "android"/"data" arg was specified.
+            src_arg = argv[1];
         } else {
             return usage();
         }
-        ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
-                &oem_srcpath);
-        if (ret != 0) return usage();
 
-        if (system_srcpath != NULL)
-            ret = do_sync_sync(system_srcpath, "/system", listonly);
-        if (ret == 0 && vendor_srcpath != NULL)
-            ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
-        if(ret == 0 && oem_srcpath != NULL)
-            ret = do_sync_sync(oem_srcpath, "/oem", listonly);
-        if (ret == 0 && data_srcpath != NULL)
-            ret = do_sync_sync(data_srcpath, "/data", listonly);
+        if (src_arg != "" &&
+            src_arg != "system" && src_arg != "data" && src_arg != "vendor" && src_arg != "oem") {
+            return usage();
+        }
 
-        free(system_srcpath);
-        free(vendor_srcpath);
-        free(oem_srcpath);
-        free(data_srcpath);
-        return ret;
+        std::string system_src_path = product_file("system");
+        std::string data_src_path = product_file("data");
+        std::string vendor_src_path = product_file("vendor");
+        std::string oem_src_path = product_file("oem");
+        if (!directory_exists(vendor_src_path)) {
+            vendor_src_path = "";
+        }
+        if (!directory_exists(oem_src_path)) {
+            oem_src_path = "";
+        }
+
+        int rc = 0;
+        if (rc == 0 && (src_arg.empty() || src_arg == "system")) {
+            rc = do_sync_sync(system_src_path.c_str(), "/system", list_only);
+        }
+        if (rc == 0 && (src_arg.empty() || src_arg == "vendor")) {
+            rc = do_sync_sync(vendor_src_path.c_str(), "/vendor", list_only);
+        }
+        if(rc == 0 && (src_arg.empty() || src_arg == "oem")) {
+            rc = do_sync_sync(oem_src_path.c_str(), "/oem", list_only);
+        }
+        if (rc == 0 && (src_arg.empty() || src_arg == "data")) {
+            rc = do_sync_sync(data_src_path.c_str(), "/data", list_only);
+        }
+        return rc;
     }
     /* passthrough commands */
     else if (!strcmp(argv[0],"get-state") ||
@@ -1770,84 +1600,21 @@
     return adb_commandline(argc, argv);
 }
 
-int find_sync_dirs(const char *srcarg,
-        char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
-        char **oem_srcdir_out)
-{
-    char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
-    struct stat st;
-
-    if(srcarg == NULL) {
-        system_srcdir = product_file("system");
-        data_srcdir = product_file("data");
-        vendor_srcdir = product_file("vendor");
-        oem_srcdir = product_file("oem");
-        // Check if vendor partition exists.
-        if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
-            vendor_srcdir = NULL;
-        // Check if oem partition exists.
-        if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
-            oem_srcdir = NULL;
-    } else {
-        // srcarg may be "data", "system", "vendor", "oem" or NULL.
-        // If srcarg is NULL, then all partitions are synced.
-        if(strcmp(srcarg, "system") == 0) {
-            system_srcdir = product_file("system");
-        } else if(strcmp(srcarg, "data") == 0) {
-            data_srcdir = product_file("data");
-        } else if(strcmp(srcarg, "vendor") == 0) {
-            vendor_srcdir = product_file("vendor");
-        } else if(strcmp(srcarg, "oem") == 0) {
-            oem_srcdir = product_file("oem");
-        } else {
-            // It's not "system", "data", "vendor", or "oem".
-            return 1;
-        }
-    }
-
-    if(system_srcdir_out != NULL)
-        *system_srcdir_out = system_srcdir;
-    else
-        free(system_srcdir);
-
-    if(vendor_srcdir_out != NULL)
-        *vendor_srcdir_out = vendor_srcdir;
-    else
-        free(vendor_srcdir);
-
-    if(oem_srcdir_out != NULL)
-        *oem_srcdir_out = oem_srcdir;
-    else
-        free(oem_srcdir);
-
-    if(data_srcdir_out != NULL)
-        *data_srcdir_out = data_srcdir;
-    else
-        free(data_srcdir);
-
-    return 0;
-}
-
 static int pm_command(transport_type transport, const char* serial,
                       int argc, const char** argv)
 {
-    char buf[4096];
+    std::string cmd = "shell:pm";
 
-    snprintf(buf, sizeof(buf), "shell:pm");
-
-    while(argc-- > 0) {
-        char *quoted = escape_arg(*argv++);
-        strncat(buf, " ", sizeof(buf) - 1);
-        strncat(buf, quoted, sizeof(buf) - 1);
-        free(quoted);
+    while (argc-- > 0) {
+        cmd += " " + escape_arg(*argv++);
     }
 
-    send_shellcommand(transport, serial, buf);
+    send_shell_command(transport, serial, cmd);
     return 0;
 }
 
-int uninstall_app(transport_type transport, const char* serial, int argc,
-                  const char** argv)
+static int uninstall_app(transport_type transport, const char* serial, int argc,
+                         const char** argv)
 {
     /* if the user choose the -k option, we refuse to do it until devices are
        out with the option to uninstall the remaining data somehow (adb/ui) */
@@ -1867,15 +1634,8 @@
 
 static int delete_file(transport_type transport, const char* serial, char* filename)
 {
-    char buf[4096];
-    char* quoted;
-
-    snprintf(buf, sizeof(buf), "shell:rm -f ");
-    quoted = escape_arg(filename);
-    strncat(buf, quoted, sizeof(buf)-1);
-    free(quoted);
-
-    send_shellcommand(transport, serial, buf);
+    std::string cmd = "shell:rm -f " + escape_arg(filename);
+    send_shell_command(transport, serial, cmd);
     return 0;
 }
 
@@ -1890,8 +1650,8 @@
     }
 }
 
-int install_app(transport_type transport, const char* serial, int argc,
-                const char** argv)
+static int install_app(transport_type transport, const char* serial, int argc,
+                       const char** argv)
 {
     static const char *const DATA_DEST = "/data/local/tmp/%s";
     static const char *const SD_DEST = "/sdcard/tmp/%s";
@@ -1944,13 +1704,12 @@
     return err;
 }
 
-int install_multiple_app(transport_type transport, const char* serial, int argc,
-                         const char** argv)
+static int install_multiple_app(transport_type transport, const char* serial, int argc,
+                                const char** argv)
 {
-    char buf[1024];
     int i;
     struct stat sb;
-    unsigned long long total_size = 0;
+    uint64_t total_size = 0;
 
     // Find all APK arguments starting at end.
     // All other arguments passed through verbatim.
@@ -1976,20 +1735,22 @@
         return 1;
     }
 
-    snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
+#if defined(_WIN32) // Remove when we're using clang for Win32.
+    std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
+#else
+    std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
+#endif
     for (i = 1; i < first_apk; i++) {
-        char *quoted = escape_arg(argv[i]);
-        strncat(buf, " ", sizeof(buf) - 1);
-        strncat(buf, quoted, sizeof(buf) - 1);
-        free(quoted);
+        cmd += " " + escape_arg(argv[i]);
     }
 
     // Create install session
-    int fd = adb_connect(buf);
+    int fd = adb_connect(cmd.c_str());
     if (fd < 0) {
         fprintf(stderr, "Connect error for create: %s\n", adb_error());
         return -1;
     }
+    char buf[BUFSIZ];
     read_status_line(fd, buf, sizeof(buf));
     adb_close(fd);
 
@@ -2018,8 +1779,15 @@
             goto finalize_session;
         }
 
-        snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
-                (long long int) sb.st_size, session_id, i, get_basename(file));
+#if defined(_WIN32) // Remove when we're using clang for Win32.
+        std::string cmd = android::base::StringPrintf(
+                "exec:pm install-write -S %u %d %d_%s -",
+                (unsigned) sb.st_size, session_id, i, get_basename(file));
+#else
+        std::string cmd = android::base::StringPrintf(
+                "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
+                static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
+#endif
 
         int localFd = adb_open(file, O_RDONLY);
         if (localFd < 0) {
@@ -2028,7 +1796,7 @@
             goto finalize_session;
         }
 
-        int remoteFd = adb_connect(buf);
+        int remoteFd = adb_connect(cmd.c_str());
         if (remoteFd < 0) {
             fprintf(stderr, "Connect error for write: %s\n", adb_error());
             adb_close(localFd);
diff --git a/adb/fdevent.h b/adb/fdevent.h
index a8102ca..8d84b29 100644
--- a/adb/fdevent.h
+++ b/adb/fdevent.h
@@ -19,10 +19,6 @@
 
 #include <stdint.h>  /* for int64_t */
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* events that may be observed */
 #define FDE_READ              0x0001
 #define FDE_WRITE             0x0002
@@ -32,7 +28,7 @@
 /* features that may be set (via the events set/add/del interface) */
 #define FDE_DONT_CLOSE        0x0080
 
-typedef struct fdevent fdevent;
+struct fdevent;
 
 typedef void (*fd_func)(int fd, unsigned events, void *userdata);
 
@@ -82,8 +78,4 @@
     void *arg;
 };
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 4ba730b..730a5e2 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -130,8 +130,6 @@
     return -1;
 }
 
-typedef struct syncsendbuf syncsendbuf;
-
 struct syncsendbuf {
     unsigned id;
     unsigned size;
@@ -557,8 +555,6 @@
     }
 }
 
-typedef struct copyinfo copyinfo;
-
 struct copyinfo
 {
     copyinfo *next;
@@ -804,12 +800,12 @@
 }
 
 
-typedef struct {
+struct sync_ls_build_list_cb_args {
     copyinfo **filelist;
     copyinfo **dirlist;
     const char *rpath;
     const char *lpath;
-} sync_ls_build_list_cb_args;
+};
 
 void
 sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 5b69a63..6e1ccce 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -17,10 +17,6 @@
 #ifndef _FILE_SYNC_SERVICE_H_
 #define _FILE_SYNC_SERVICE_H_
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define htoll(x) (x)
 #define ltohl(x) (x)
 
@@ -38,7 +34,7 @@
 #define ID_FAIL MKID('F','A','I','L')
 #define ID_QUIT MKID('Q','U','I','T')
 
-typedef union {
+union syncmsg {
     unsigned id;
     struct {
         unsigned id;
@@ -65,7 +61,7 @@
         unsigned id;
         unsigned msglen;
     } status;
-} syncmsg;
+} ;
 
 
 void file_sync_service(int fd, void *cookie);
@@ -76,8 +72,4 @@
 
 #define SYNC_DATA_MAX (64*1024)
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/adb/get_my_path_darwin.c b/adb/get_my_path_darwin.cpp
similarity index 100%
rename from adb/get_my_path_darwin.c
rename to adb/get_my_path_darwin.cpp
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index 9cf084e..c0f7ec2 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -121,7 +121,6 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
-typedef struct JdwpProcess  JdwpProcess;
 struct JdwpProcess {
     JdwpProcess*  next;
     JdwpProcess*  prev;
@@ -455,11 +454,10 @@
 #define  JDWP_CONTROL_NAME      "\0jdwp-control"
 #define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)
 
-typedef struct {
+struct JdwpControl {
     int       listen_socket;
     fdevent*  fde;
-
-} JdwpControl;
+};
 
 
 static void
@@ -570,10 +568,10 @@
  ** this simply returns the list of known JDWP process pids
  **/
 
-typedef struct {
+struct JdwpSocket {
     asocket  socket;
     int      pass;
-} JdwpSocket;
+};
 
 static void
 jdwp_socket_close( asocket*  s )
@@ -642,8 +640,6 @@
  ** to the client...
  **/
 
-typedef struct JdwpTracker  JdwpTracker;
-
 struct JdwpTracker {
     asocket       socket;
     JdwpTracker*  next;
@@ -754,4 +750,3 @@
 }
 
 #endif /* !ADB_HOST */
-
diff --git a/adb/qemu_tracing.h b/adb/qemu_tracing.h
index bf80457..ff42d4f 100644
--- a/adb/qemu_tracing.h
+++ b/adb/qemu_tracing.h
@@ -21,16 +21,8 @@
 #ifndef __QEMU_TRACING_H
 #define __QEMU_TRACING_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Initializes connection with the adb-debug qemud service in the emulator. */
 int adb_qemu_trace_init(void);
 void adb_qemu_trace(const char* fmt, ...);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* __QEMU_TRACING_H */
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index b150274..1eaee73 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -31,6 +31,7 @@
 
 #include "adb.h"
 #include "adb_io.h"
+#include "adb_utils.h"
 #include "cutils/properties.h"
 
 static int system_ro = 1;
@@ -56,11 +57,6 @@
     return device;
 }
 
-static bool has_partition(const char* path) {
-    struct stat sb;
-    return (lstat(path, &sb) == 0 && S_ISDIR(sb.st_mode));
-}
-
 int make_block_device_writable(const std::string& dev) {
     int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
     if (fd == -1) {
@@ -90,7 +86,7 @@
 }
 
 static bool remount_partition(int fd, const char* partition, int* ro) {
-  if (!has_partition(partition)) {
+  if (!directory_exists(partition)) {
     return true;
   }
   if (remount(partition, ro)) {
diff --git a/adb/services.cpp b/adb/services.cpp
index 12eb406..ff13722 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -31,6 +31,8 @@
 #include <unistd.h>
 #endif
 
+#include <base/stringprintf.h>
+
 #if !ADB_HOST
 #include "base/file.h"
 #include "cutils/android_reboot.h"
@@ -43,8 +45,6 @@
 #include "remount_service.h"
 #include "transport.h"
 
-typedef struct stinfo stinfo;
-
 struct stinfo {
     void (*func)(int fd, void *cookie);
     int fd;
@@ -194,7 +194,7 @@
     if (reboot_service_impl(fd, static_cast<const char*>(arg))) {
         // Don't return early. Give the reboot command time to take effect
         // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
-        while (1) {
+        while (true) {
             pause();
         }
     }
@@ -375,7 +375,7 @@
     pid_t pid = (pid_t) (uintptr_t) cookie;
 
     D("entered. fd=%d of pid=%d\n", fd, pid);
-    for (;;) {
+    while (true) {
         int status;
         pid_t p = waitpid(pid, &status, 0);
         if (p == pid) {
@@ -501,19 +501,8 @@
     } else if(!strncmp(name, "unroot:", 7)) {
         ret = create_service_thread(restart_unroot_service, NULL);
     } else if(!strncmp(name, "backup:", 7)) {
-        char* arg = strdup(name + 7);
-        if (arg == NULL) return -1;
-        char* c = arg;
-        for (; *c != '\0'; c++) {
-            if (*c == ':')
-                *c = ' ';
-        }
-        char* cmd;
-        if (asprintf(&cmd, "/system/bin/bu backup %s", arg) != -1) {
-            ret = create_subproc_thread(cmd, SUBPROC_RAW);
-            free(cmd);
-        }
-        free(arg);
+        ret = create_subproc_thread(android::base::StringPrintf("/system/bin/bu backup %s",
+                                                                (name + 7)).c_str(), SUBPROC_RAW);
     } else if(!strncmp(name, "restore:", 8)) {
         ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW);
     } else if(!strncmp(name, "tcpip:", 6)) {
@@ -559,12 +548,12 @@
 
     D("wait_for_state %d\n", sinfo->state);
 
-    const char* err = "unknown error";
-    atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
-    if(t != 0) {
+    std::string error_msg = "unknown error";
+    atransport* t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &error_msg);
+    if (t != 0) {
         WriteFdExactly(fd, "OKAY", 4);
     } else {
-        sendfailmsg(fd, err);
+        sendfailmsg(fd, error_msg.c_str());
     }
 
     if (sinfo->serial)
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 48d02d6..f468029 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -487,10 +487,10 @@
 /* a Remote socket is used to send/receive data to/from a given transport object
 ** it needs to be closed when the transport is forcibly destroyed by the user
 */
-typedef struct aremotesocket {
+struct aremotesocket {
     asocket      socket;
     adisconnect  disconnect;
-} aremotesocket;
+};
 
 static int remote_socket_enqueue(asocket *s, apacket *p)
 {
@@ -827,12 +827,11 @@
     }
 #else /* !ADB_HOST */
     if (s->transport == NULL) {
-        const char* error_string = "unknown failure";
-        s->transport = acquire_one_transport (CS_ANY,
-                kTransportAny, NULL, &error_string);
+        std::string error_msg = "unknown failure";
+        s->transport = acquire_one_transport(CS_ANY, kTransportAny, NULL, &error_msg);
 
         if (s->transport == NULL) {
-            sendfailmsg(s->peer->fd, error_string);
+            sendfailmsg(s->peer->fd, error_msg.c_str());
             goto fail;
         }
     }
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 2ad28fa..d9a1518 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -54,10 +54,6 @@
 
 #include "fdevent.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define OS_PATH_SEPARATOR '\\'
 #define OS_PATH_SEPARATOR_STR "\\"
 #define ENV_PATH_SEPARATOR_STR ";"
@@ -296,10 +292,6 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define OS_PATH_SEPARATOR '/'
 #define OS_PATH_SEPARATOR_STR "/"
 #define ENV_PATH_SEPARATOR_STR ":"
@@ -540,8 +532,4 @@
 
 #endif /* !_WIN32 */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* _ADB_SYSDEPS_H */
diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.cpp
similarity index 97%
rename from adb/sysdeps_win32.c
rename to adb/sysdeps_win32.cpp
index c2742f1..de47638 100644
--- a/adb/sysdeps_win32.c
+++ b/adb/sysdeps_win32.cpp
@@ -30,6 +30,53 @@
 
 extern void fatal(const char *fmt, ...);
 
+/* forward declarations */
+
+typedef const struct FHClassRec_* FHClass;
+typedef struct FHRec_* FH;
+typedef struct EventHookRec_* EventHook;
+
+typedef struct FHClassRec_ {
+    void (*_fh_init)(FH);
+    int (*_fh_close)(FH);
+    int (*_fh_lseek)(FH, int, int);
+    int (*_fh_read)(FH, void*, int);
+    int (*_fh_write)(FH, const void*, int);
+    void (*_fh_hook)(FH, int, EventHook);
+} FHClassRec;
+
+static void _fh_file_init(FH);
+static int _fh_file_close(FH);
+static int _fh_file_lseek(FH, int, int);
+static int _fh_file_read(FH, void*, int);
+static int _fh_file_write(FH, const void*, int);
+static void _fh_file_hook(FH, int, EventHook);
+
+static const FHClassRec _fh_file_class = {
+    _fh_file_init,
+    _fh_file_close,
+    _fh_file_lseek,
+    _fh_file_read,
+    _fh_file_write,
+    _fh_file_hook
+};
+
+static void _fh_socket_init(FH);
+static int _fh_socket_close(FH);
+static int _fh_socket_lseek(FH, int, int);
+static int _fh_socket_read(FH, void*, int);
+static int _fh_socket_write(FH, const void*, int);
+static void _fh_socket_hook(FH, int, EventHook);
+
+static const FHClassRec _fh_socket_class = {
+    _fh_socket_init,
+    _fh_socket_close,
+    _fh_socket_lseek,
+    _fh_socket_read,
+    _fh_socket_write,
+    _fh_socket_hook
+};
+
 #define assert(cond)  do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
 
 /**************************************************************************/
@@ -92,23 +139,6 @@
 /**************************************************************************/
 /**************************************************************************/
 
-typedef const struct FHClassRec_*   FHClass;
-
-typedef struct FHRec_*          FH;
-
-typedef struct EventHookRec_*  EventHook;
-
-typedef struct FHClassRec_
-{
-    void (*_fh_init) ( FH  f );
-    int  (*_fh_close)( FH  f );
-    int  (*_fh_lseek)( FH  f, int  pos, int  origin );
-    int  (*_fh_read) ( FH  f, void*  buf, int  len );
-    int  (*_fh_write)( FH  f, const void*  buf, int  len );
-    void (*_fh_hook) ( FH  f, int  events, EventHook  hook );
-
-} FHClassRec;
-
 /* used to emulate unix-domain socket pairs */
 typedef struct SocketPairRec_*  SocketPair;
 
@@ -220,10 +250,6 @@
     return 0;
 }
 
-/* forward definitions */
-static const FHClassRec   _fh_file_class;
-static const FHClassRec   _fh_socket_class;
-
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -232,23 +258,17 @@
 /**************************************************************************/
 /**************************************************************************/
 
-static void
-_fh_file_init( FH  f )
-{
+static void _fh_file_init( FH  f ) {
     f->fh_handle = INVALID_HANDLE_VALUE;
 }
 
-static int
-_fh_file_close( FH  f )
-{
+static int _fh_file_close( FH  f ) {
     CloseHandle( f->fh_handle );
     f->fh_handle = INVALID_HANDLE_VALUE;
     return 0;
 }
 
-static int
-_fh_file_read( FH  f,  void*  buf, int   len )
-{
+static int _fh_file_read( FH  f,  void*  buf, int   len ) {
     DWORD  read_bytes;
 
     if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) {
@@ -261,9 +281,7 @@
     return (int)read_bytes;
 }
 
-static int
-_fh_file_write( FH  f,  const void*  buf, int   len )
-{
+static int _fh_file_write( FH  f,  const void*  buf, int   len ) {
     DWORD  wrote_bytes;
 
     if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) {
@@ -276,9 +294,7 @@
     return  (int)wrote_bytes;
 }
 
-static int
-_fh_file_lseek( FH  f, int  pos, int  origin )
-{
+static int _fh_file_lseek( FH  f, int  pos, int  origin ) {
     DWORD  method;
     DWORD  result;
 
@@ -302,17 +318,6 @@
     return (int)result;
 }
 
-static void  _fh_file_hook( FH  f, int  event, EventHook  eventhook );  /* forward */
-
-static const FHClassRec  _fh_file_class =
-{
-    _fh_file_init,
-    _fh_file_close,
-    _fh_file_lseek,
-    _fh_file_read,
-    _fh_file_write,
-    _fh_file_hook
-};
 
 /**************************************************************************/
 /**************************************************************************/
@@ -495,9 +500,7 @@
 
 #undef setsockopt
 
-static void
-_socket_set_errno( void )
-{
+static void _socket_set_errno( void ) {
     switch (WSAGetLastError()) {
     case 0:              errno = 0; break;
     case WSAEWOULDBLOCK: errno = EAGAIN; break;
@@ -508,17 +511,13 @@
     }
 }
 
-static void
-_fh_socket_init( FH  f )
-{
+static void _fh_socket_init( FH  f ) {
     f->fh_socket = INVALID_SOCKET;
     f->event     = WSACreateEvent();
     f->mask      = 0;
 }
 
-static int
-_fh_socket_close( FH  f )
-{
+static int _fh_socket_close( FH  f ) {
     /* gently tell any peer that we're closing the socket */
     shutdown( f->fh_socket, SD_BOTH );
     closesocket( f->fh_socket );
@@ -528,17 +527,13 @@
     return 0;
 }
 
-static int
-_fh_socket_lseek( FH  f, int pos, int origin )
-{
+static int _fh_socket_lseek( FH  f, int pos, int origin ) {
     errno = EPIPE;
     return -1;
 }
 
-static int
-_fh_socket_read( FH  f, void*  buf, int  len )
-{
-    int  result = recv( f->fh_socket, buf, len, 0 );
+static int _fh_socket_read(FH f, void* buf, int len) {
+    int  result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
     if (result == SOCKET_ERROR) {
         _socket_set_errno();
         result = -1;
@@ -546,10 +541,8 @@
     return  result;
 }
 
-static int
-_fh_socket_write( FH  f, const void*  buf, int  len )
-{
-    int  result = send( f->fh_socket, buf, len, 0 );
+static int _fh_socket_write(FH f, const void* buf, int len) {
+    int  result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
     if (result == SOCKET_ERROR) {
         _socket_set_errno();
         result = -1;
@@ -557,18 +550,6 @@
     return result;
 }
 
-static void  _fh_socket_hook( FH  f, int  event, EventHook  hook );  /* forward */
-
-static const FHClassRec  _fh_socket_class =
-{
-    _fh_socket_init,
-    _fh_socket_close,
-    _fh_socket_lseek,
-    _fh_socket_read,
-    _fh_socket_write,
-    _fh_socket_hook
-};
-
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -819,7 +800,7 @@
         return -1;
     }
 
-    return setsockopt( fh->fh_socket, level, optname, optval, optlen );
+    return setsockopt( fh->fh_socket, level, optname, reinterpret_cast<const char*>(optval), optlen );
 }
 
 /**************************************************************************/
@@ -1219,18 +1200,16 @@
 };
 
 
-int  adb_socketpair( int  sv[2] )
-{
-    FH          fa, fb;
-    SocketPair  pair;
+int  adb_socketpair(int sv[2]) {
+    SocketPair pair;
 
-    fa = _fh_alloc( &_fh_socketpair_class );
-    fb = _fh_alloc( &_fh_socketpair_class );
+    FH fa = _fh_alloc(&_fh_socketpair_class);
+    FH fb = _fh_alloc(&_fh_socketpair_class);
 
     if (!fa || !fb)
         goto Fail;
 
-    pair = malloc( sizeof(*pair) );
+    pair = reinterpret_cast<SocketPair>(malloc(sizeof(*pair)));
     if (pair == NULL) {
         D("adb_socketpair: not enough memory to allocate pipes\n" );
         goto Fail;
@@ -1328,13 +1307,12 @@
 static EventHook  _free_hooks;
 
 static EventHook
-event_hook_alloc( FH  fh )
-{
-    EventHook  hook = _free_hooks;
-    if (hook != NULL)
+event_hook_alloc(FH fh) {
+    EventHook hook = _free_hooks;
+    if (hook != NULL) {
         _free_hooks = hook->next;
-    else {
-        hook = malloc( sizeof(*hook) );
+    } else {
+        hook = reinterpret_cast<EventHook>(malloc(sizeof(*hook)));
         if (hook == NULL)
             fatal( "could not allocate event hook\n" );
     }
@@ -1796,7 +1774,7 @@
         while(fd_table_max <= fd) {
             fd_table_max *= 2;
         }
-        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
+        fd_table = reinterpret_cast<fdevent**>(realloc(fd_table, sizeof(fdevent*) * fd_table_max));
         if(fd_table == 0) {
             FATAL("could not expand fd_table to %d entries\n", fd_table_max);
         }
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 4b9eeeb..37f9d7b 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -406,7 +406,6 @@
  * number of client connections that want it through a single
  * live TCP connection
  */
-typedef struct device_tracker  device_tracker;
 struct device_tracker {
     asocket          socket;
     int              update_needed;
@@ -536,7 +535,6 @@
 }
 #endif // ADB_HOST
 
-typedef struct tmsg tmsg;
 struct tmsg
 {
     atransport *transport;
@@ -800,22 +798,20 @@
     return !*to_test;
 }
 
-atransport *acquire_one_transport(int state, transport_type ttype,
-                                  const char* serial, const char** error_out)
+atransport* acquire_one_transport(int state, transport_type ttype,
+                                  const char* serial, std::string* error_out)
 {
     atransport *t;
     atransport *result = NULL;
     int ambiguous = 0;
 
 retry:
-    if (error_out)
-        *error_out = "device not found";
+    if (error_out) *error_out = "device not found";
 
     adb_mutex_lock(&transport_lock);
     for (t = transport_list.next; t != &transport_list; t = t->next) {
         if (t->connection_state == CS_NOPERM) {
-        if (error_out)
-            *error_out = "insufficient permissions for device";
+            if (error_out) *error_out = "insufficient permissions for device";
             continue;
         }
 
@@ -827,8 +823,7 @@
                 qual_match(serial, "model:", t->model, true) ||
                 qual_match(serial, "device:", t->device, false)) {
                 if (result) {
-                    if (error_out)
-                        *error_out = "more than one device";
+                    if (error_out) *error_out = "more than one device";
                     ambiguous = 1;
                     result = NULL;
                     break;
@@ -838,8 +833,7 @@
         } else {
             if (ttype == kTransportUsb && t->type == kTransportUsb) {
                 if (result) {
-                    if (error_out)
-                        *error_out = "more than one device";
+                    if (error_out) *error_out = "more than one device";
                     ambiguous = 1;
                     result = NULL;
                     break;
@@ -847,8 +841,7 @@
                 result = t;
             } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
                 if (result) {
-                    if (error_out)
-                        *error_out = "more than one emulator";
+                    if (error_out) *error_out = "more than one emulator";
                     ambiguous = 1;
                     result = NULL;
                     break;
@@ -856,8 +849,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 and emulator";
                     ambiguous = 1;
                     result = NULL;
                     break;
@@ -870,29 +862,33 @@
 
     if (result) {
         if (result->connection_state == CS_UNAUTHORIZED) {
-            if (error_out)
-                *error_out = "device unauthorized. Please check the confirmation dialog on your device.";
+            if (error_out) {
+                *error_out = "device unauthorized.\n";
+                char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
+                *error_out += "This adbd's $ADB_VENDOR_KEYS is ";
+                *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
+                *error_out += "; try 'adb kill-server' if that seems wrong.\n";
+                *error_out += "Otherwise check for a confirmation dialog on your device.";
+            }
             result = NULL;
         }
 
-         /* offline devices are ignored -- they are either being born or dying */
+        /* offline devices are ignored -- they are either being born or dying */
         if (result && result->connection_state == CS_OFFLINE) {
-            if (error_out)
-                *error_out = "device offline";
+            if (error_out) *error_out = "device offline";
             result = NULL;
         }
-         /* check for required connection state */
+
+        /* check for required connection state */
         if (result && state != CS_ANY && result->connection_state != state) {
-            if (error_out)
-                *error_out = "invalid device state";
+            if (error_out) *error_out = "invalid device state";
             result = NULL;
         }
     }
 
     if (result) {
         /* found one that we can take */
-        if (error_out)
-            *error_out = NULL;
+        if (error_out) *error_out = "success";
     } else if (state != CS_ANY && (serial || !ambiguous)) {
         adb_sleep_ms(1000);
         goto retry;
diff --git a/adb/transport.h b/adb/transport.h
index 36a0e40..a2077e8 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -17,14 +17,11 @@
 #ifndef __TRANSPORT_H
 #define __TRANSPORT_H
 
-#include <stdbool.h>
 #include <sys/types.h>
 
-#include "adb.h"
+#include <string>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "adb.h"
 
 #if ADB_TRACE
 void dump_hex(const unsigned char* ptr, size_t  len);
@@ -37,7 +34,7 @@
  * If no suitable transport is found, error is set.
  */
 atransport* acquire_one_transport(int state, transport_type ttype,
-                                  const char* serial, const char** error_out);
+                                  const char* serial, std::string* error_out);
 void add_transport_disconnect(atransport* t, adisconnect* dis);
 void remove_transport_disconnect(atransport* t, adisconnect* dis);
 void kick_transport(atransport* t);
@@ -74,8 +71,4 @@
 
 asocket* create_device_tracker(void);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif   /* __TRANSPORT_H */
diff --git a/adb/usb_linux_client.c b/adb/usb_linux_client.cpp
similarity index 93%
rename from adb/usb_linux_client.c
rename to adb/usb_linux_client.cpp
index 434451c..343f20c 100644
--- a/adb/usb_linux_client.c
+++ b/adb/usb_linux_client.cpp
@@ -163,7 +163,7 @@
     struct usb_handle *usb = (struct usb_handle *)x;
     int fd;
 
-    while (1) {
+    while (true) {
         // wait until the USB device needs opening
         adb_mutex_lock(&usb->lock);
         while (usb->fd != -1)
@@ -239,12 +239,7 @@
 
 static void usb_adb_init()
 {
-    usb_handle *h;
-    adb_thread_t tid;
-    int fd;
-
-    h = calloc(1, sizeof(usb_handle));
-
+    usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
     h->write = usb_adb_write;
     h->read = usb_adb_read;
     h->kick = usb_adb_kick;
@@ -253,12 +248,12 @@
     adb_cond_init(&h->notify, 0);
     adb_mutex_init(&h->lock, 0);
 
-    // Open the file /dev/android_adb_enable to trigger 
+    // Open the file /dev/android_adb_enable to trigger
     // the enabling of the adb USB function in the kernel.
     // We never touch this file again - just leave it open
     // indefinitely so the kernel will know when we are running
     // and when we are not.
-    fd = unix_open("/dev/android_adb_enable", O_RDWR);
+    int fd = unix_open("/dev/android_adb_enable", O_RDWR);
     if (fd < 0) {
        D("failed to open /dev/android_adb_enable\n");
     } else {
@@ -266,6 +261,7 @@
     }
 
     D("[ usb_init - starting thread ]\n");
+    adb_thread_t tid;
     if(adb_thread_create(&tid, usb_adb_open_thread, h)){
         fatal_errno("cannot create usb thread");
     }
@@ -351,14 +347,14 @@
 {
     struct usb_handle *usb = (struct usb_handle *)x;
 
-    while (1) {
+    while (true) {
         // wait until the USB device needs opening
         adb_mutex_lock(&usb->lock);
         while (usb->control != -1 && usb->bulk_in != -1 && usb->bulk_out != -1)
             adb_cond_wait(&usb->notify, &usb->lock);
         adb_mutex_unlock(&usb->lock);
 
-        while (1) {
+        while (true) {
             init_functionfs(usb);
 
             if (usb->control >= 0 && usb->bulk_in >= 0 && usb->bulk_out >= 0)
@@ -375,7 +371,7 @@
     return 0;
 }
 
-static int bulk_write(int bulk_in, const char *buf, size_t length)
+static int bulk_write(int bulk_in, const uint8_t* buf, size_t length)
 {
     size_t count = 0;
     int ret;
@@ -394,22 +390,19 @@
     return count;
 }
 
-static int usb_ffs_write(usb_handle *h, const void *data, int len)
+static int usb_ffs_write(usb_handle* h, const void* data, int len)
 {
-    int n;
-
     D("about to write (fd=%d, len=%d)\n", h->bulk_in, len);
-    n = bulk_write(h->bulk_in, data, len);
+    int n = bulk_write(h->bulk_in, reinterpret_cast<const uint8_t*>(data), len);
     if (n != len) {
-        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
-            h->bulk_in, n, errno, strerror(errno));
+        D("ERROR: fd = %d, n = %d: %s\n", h->bulk_in, n, strerror(errno));
         return -1;
     }
     D("[ done fd=%d ]\n", h->bulk_in);
     return 0;
 }
 
-static int bulk_read(int bulk_out, char *buf, size_t length)
+static int bulk_read(int bulk_out, uint8_t* buf, size_t length)
 {
     size_t count = 0;
     int ret;
@@ -430,15 +423,12 @@
     return count;
 }
 
-static int usb_ffs_read(usb_handle *h, void *data, int len)
+static int usb_ffs_read(usb_handle* h, void* data, int len)
 {
-    int n;
-
     D("about to read (fd=%d, len=%d)\n", h->bulk_out, len);
-    n = bulk_read(h->bulk_out, data, len);
+    int n = bulk_read(h->bulk_out, reinterpret_cast<uint8_t*>(data), len);
     if (n != len) {
-        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
-            h->bulk_out, n, errno, strerror(errno));
+        D("ERROR: fd = %d, n = %d: %s\n", h->bulk_out, n, strerror(errno));
         return -1;
     }
     D("[ done fd=%d ]\n", h->bulk_out);
@@ -473,18 +463,13 @@
 
 static void usb_ffs_init()
 {
-    usb_handle *h;
-    adb_thread_t tid;
-
     D("[ usb_init - using FunctionFS ]\n");
 
-    h = calloc(1, sizeof(usb_handle));
-
+    usb_handle* h = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
     h->write = usb_ffs_write;
     h->read = usb_ffs_read;
     h->kick = usb_ffs_kick;
-
-    h->control  = -1;
+    h->control = -1;
     h->bulk_out = -1;
     h->bulk_out = -1;
 
@@ -492,6 +477,7 @@
     adb_mutex_init(&h->lock, 0);
 
     D("[ usb_init - starting thread ]\n");
+    adb_thread_t tid;
     if (adb_thread_create(&tid, usb_ffs_open_thread, h)){
         fatal_errno("[ cannot create usb thread ]\n");
     }
diff --git a/adb/usb_osx.c b/adb/usb_osx.cpp
similarity index 96%
rename from adb/usb_osx.c
rename to adb/usb_osx.cpp
index 94c8cfe..303ae45 100644
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.cpp
@@ -26,6 +26,7 @@
 #include <IOKit/IOMessage.h>
 #include <mach/mach_port.h>
 
+#include <inttypes.h>
 #include <stdio.h>
 
 #include "adb.h"
@@ -111,7 +112,7 @@
     HRESULT                  result;
     SInt32                   score;
     UInt32                   locationId;
-    UInt8                    class, subclass, protocol;
+    UInt8                    if_class, subclass, protocol;
     UInt16                   vendor;
     UInt16                   product;
     UInt8                    serialIndex;
@@ -132,9 +133,9 @@
         }
 
         //* This gets us the interface object
-        result = (*plugInInterface)->QueryInterface(plugInInterface,
-                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)
-                &iface);
+        result = (*plugInInterface)->QueryInterface(
+            plugInInterface,
+            CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*)&iface);
         //* We only needed the plugin to get the interface, so discard it
         (*plugInInterface)->Release(plugInInterface);
         if (result || !iface) {
@@ -142,12 +143,12 @@
             continue;
         }
 
-        kr = (*iface)->GetInterfaceClass(iface, &class);
+        kr = (*iface)->GetInterfaceClass(iface, &if_class);
         kr = (*iface)->GetInterfaceSubClass(iface, &subclass);
         kr = (*iface)->GetInterfaceProtocol(iface, &protocol);
-        if(class != ADB_CLASS || subclass != ADB_SUBCLASS || protocol != ADB_PROTOCOL) {
+        if(if_class != ADB_CLASS || subclass != ADB_SUBCLASS || protocol != ADB_PROTOCOL) {
             // Ignore non-ADB devices.
-            DBG("Ignoring interface with incorrect class/subclass/protocol - %d, %d, %d\n", class, subclass, protocol);
+            DBG("Ignoring interface with incorrect class/subclass/protocol - %d, %d, %d\n", if_class, subclass, protocol);
             (*iface)->Release(iface);
             continue;
         }
@@ -177,7 +178,7 @@
         }
 
         result = (*plugInInterface)->QueryInterface(plugInInterface,
-                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
+            CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*)&dev);
         //* only needed this to query the plugin
         (*plugInInterface)->Release(plugInInterface);
         if (result || !dev) {
@@ -334,7 +335,7 @@
                 interfaceSubClass, interfaceProtocol))
         goto err_bad_adb_interface;
 
-    handle = calloc(1, sizeof(usb_handle));
+    handle = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
 
     //* Iterate over the endpoints for this interface and find the first
     //* bulk in/out pipes available.  These will be our read/write pipes.
diff --git a/base/include/base/strings.h b/base/include/base/strings.h
index ab56aad..3559342 100644
--- a/base/include/base/strings.h
+++ b/base/include/base/strings.h
@@ -25,7 +25,7 @@
 
 // Splits a string into a vector of strings.
 //
-// The string is split at each occurence of a character in delimiters.
+// The string is split at each occurrence of a character in delimiters.
 //
 // Empty splits will be omitted. I.e. Split("a,,b", ",") -> {"a", "b"}
 //
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index 9d039e6..e4ed179 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -18,6 +18,7 @@
 #define _LIBS_CUTILS_TRACE_H
 
 #include <inttypes.h>
+#include <stdatomic.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -25,7 +26,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <cutils/atomic.h>
 #include <cutils/compiler.h>
 
 __BEGIN_DECLS
@@ -113,7 +113,7 @@
  * Nonzero indicates setup has completed.
  * Note: This does NOT indicate whether or not setup was successful.
  */
-extern volatile int32_t atrace_is_ready;
+extern atomic_bool atrace_is_ready;
 
 /**
  * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY.
@@ -136,7 +136,7 @@
 #define ATRACE_INIT() atrace_init()
 static inline void atrace_init()
 {
-    if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) {
+    if (CC_UNLIKELY(!atomic_load_explicit(&atrace_is_ready, memory_order_acquire))) {
         atrace_setup();
     }
 }
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index fed81f8..02fe2b5 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -215,6 +215,8 @@
 void fs_config(const char *path, int dir,
                unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities);
 
+ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc);
+
 __END_DECLS
 
 #endif
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 2fa81d4..8544951 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -508,7 +508,6 @@
 
 void load_all_props() {
     load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);
-    load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT, NULL);
     load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);
     load_properties_from_file(PROP_PATH_BOOTIMAGE_BUILD, NULL);
     load_properties_from_file(PROP_PATH_FACTORY, "ro.*");
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index b875efd..54cace9 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -57,7 +57,6 @@
 libbacktrace_shared_libraries := \
 	libbase \
 	libunwind \
-	libunwind-ptrace \
 
 libbacktrace_shared_libraries_host := \
 	liblog \
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index c636196..9dc15d1 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -111,8 +111,9 @@
 
 LOCAL_SRC_FILES_arm += arch-arm/memset32.S
 LOCAL_SRC_FILES_arm64 += arch-arm64/android_memset.S
-LOCAL_SRC_FILES_mips += arch-mips/android_memset.S
-LOCAL_SRC_FILES_mips64 += arch-mips/android_memset.S
+
+LOCAL_SRC_FILES_mips += arch-mips/android_memset.c
+LOCAL_SRC_FILES_mips64 += arch-mips/android_memset.c
 
 LOCAL_SRC_FILES_x86 += \
         arch-x86/android_memset16.S \
diff --git a/libcutils/arch-mips/android_memset.S b/libcutils/arch-mips/android_memset.S
deleted file mode 100644
index 6811de0..0000000
--- a/libcutils/arch-mips/android_memset.S
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2009
- *      MIPS Technologies, Inc., California.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
- *    contributors may be used to endorse or promote products derived from
- *    this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/************************************************************************
- *
- *  memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops
- *  Version: "043009"
- *
- ************************************************************************/
-
-
-/************************************************************************
- *  Include files
- ************************************************************************/
-
-#include <machine/asm.h>
-#define END(f) .cfi_endproc; .size f, .-f; .end f
-
-/*
- * This routine could be optimized for MIPS64. The current code only
- * uses MIPS32 instructions.
- */
-
-#if defined(__MIPSEB__)
-#  define SWHI	swl		/* high part is left in big-endian	*/
-#  define SWLO	swr		/* low part is right in big-endian	*/
-#endif
-
-#if defined(__MIPSEL__)
-#  define SWHI	swr		/* high part is right in little-endian	*/
-#  define SWLO	swl		/* low part is left in little-endian	*/
-#endif
-
-#if !(defined(XGPROF) || defined(XPROF))
-#undef SETUP_GP
-#define SETUP_GP
-#endif
-
-#ifdef NDEBUG
-#define DBG #
-#else
-#define DBG
-#endif
-
-/*
- * void android_memset16(uint16_t* dst, uint16_t value, size_t size);
- */
-
-LEAF(android_memset16,0)
-	.set noreorder
-DBG	/* Check parameters */
-DBG	andi	t0,a0,1			# a0 must be halfword aligned
-DBG	tne	t0,zero
-DBG	andi	t2,a2,1			# a2 must be even
-DBG	tne	t2,zero
-
-#ifdef FIXARGS
-	# ensure count is even
-#if (__mips==32) && (__mips_isa_rev>=2)
-	ins	a2,zero,0,1
-#else
-	ori	a2,1
-	xori	a2,1
-#endif
-#endif
-
-#if (__mips==32) && (__mips_isa_rev>=2)
-	ins	a1,a1,16,16
-#else
-	andi	a1,0xffff
-	sll	t3,a1,16
-	or	a1,t3
-#endif
-
-	beqz	a2,.Ldone
-	 andi	t1,a0,2
-	beqz	t1,.Lalignok
-	 addu	t0,a0,a2		# t0 is the "past the end" address
-	sh	a1,0(a0)		# store one halfword to get aligned
-	addu	a0,2
-	subu	a2,2
-.Lalignok:
-	slti	t1,a2,4			# .Laligned for 4 or more bytes
-	beqz	t1,.Laligned
-	 sne	t1,a2,2			# one more halfword?
-	bnez	t1,.Ldone
-	 nop
-	sh	a1,0(a0)
-.Ldone:
-	j	ra
-	 nop
-	.set reorder
-END(android_memset16)
-
-/*
- * void android_memset32(uint32_t* dst, uint32_t value, size_t size);
- */
-
-LEAF(android_memset32,0)
-	.set noreorder
-DBG	/* Check parameters */
-DBG	andi	t0,a0,3			# a0 must be word aligned
-DBG	tne	t0,zero
-DBG	andi	t2,a2,3			# a2 must be a multiple of 4 bytes
-DBG	tne	t2,zero
-
-#ifdef FIXARGS
-	# ensure count is a multiple of 4
-#if (__mips==32) && (__mips_isa_rev>=2)
-	ins	$a2,$0,0,2
-#else
-	ori	a2,3
-	xori	a2,3
-#endif
-#endif
-
-	bnez	a2,.Laligned		# any work to do?
-	 addu	t0,a0,a2		# t0 is the "past the end" address
-
-	j	ra
-	 nop
-	.set reorder
-END(android_memset32)
-
-LEAF(memset,0)
-
-	.set	noreorder
-	.set	noat
-
-	addu	t0,a0,a2		# t0 is the "past the end" address
-	slti	AT,a2,4			# is a2 less than 4?
-	bne	AT,zero,.Llast4		# if yes, go to last4
-	 move	v0,a0			# memset returns the dst pointer
-
-	beq	a1,zero,.Lset0
-	 subu	v1,zero,a0
-
-	# smear byte into 32 bit word
-#if (__mips==32) && (__mips_isa_rev>=2)
-	ins     a1, a1, 8, 8        # Replicate fill byte into half-word.
-	ins     a1, a1, 16, 16      # Replicate fill byte into word.
-#else
-	and	a1,0xff
-	sll	AT,a1,8
-	or	a1,AT
-	sll	AT,a1,16
-	or	a1,AT
-#endif
-
-.Lset0:
-	andi	v1,v1,0x3		# word-unaligned address?
-	beq	v1,zero,.Laligned	# v1 is the unalignment count
-	 subu	a2,a2,v1
-	SWHI	a1,0(a0)
-	addu	a0,a0,v1
-
-# Here we have the "word-aligned" a0 (until the "last4")
-.Laligned:
-	andi	t8,a2,0x3f	# any 64-byte chunks?
-				# t8 is the byte count past 64-byte chunks
-	beq	a2,t8,.Lchk8w	# when a2==t8, no 64-byte chunks
-				# There will be at most 1 32-byte chunk then
-	 subu	a3,a2,t8	# subtract from a2 the reminder
-				# Here a3 counts bytes in 16w chunks
-	addu	a3,a0,a3	# Now a3 is the final dst after 64-byte chunks
-
-# Find out, if there are any 64-byte chunks after which will be still at least
-# 96 bytes left. The value "96" is calculated as needed buffer for
-# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after
-# incrementing "a0" by 64.
-# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk.
-#
-	sltiu	v1,a2,160
-	bgtz	v1,.Lloop16w_nopref30	# skip "pref 30,0(a0)"
-	 subu	t7,a2,96	# subtract "pref 30 unsafe" region
-		# below we have at least 1 64-byte chunk which is "pref 30 safe"
-	andi	t6,t7,0x3f	# t6 is past "64-byte safe chunks" reminder
-	subu	t5,t7,t6	# subtract from t7 the reminder
-				# Here t5 counts bytes in 16w "safe" chunks
-	addu	t4,a0,t5	# Now t4 is the dst after 64-byte "safe" chunks
-
-# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line
-#	pref	30,0(a0)
-# Here we are in the region, where it is safe to use "pref 30,64(a0)"
-.Lloop16w:
-	addiu	a0,a0,64
-	pref	30,-32(a0)	# continue setting up the dest, addr 64-32
-	sw	a1,-64(a0)
-	sw	a1,-60(a0)
-	sw	a1,-56(a0)
-	sw	a1,-52(a0)
-	sw	a1,-48(a0)
-	sw	a1,-44(a0)
-	sw	a1,-40(a0)
-	sw	a1,-36(a0)
-	nop
-	nop			# the extra nop instructions help to balance
-	nop			# cycles needed for "store" + "fill" + "evict"
-	nop			# For 64byte store there are needed 8 fill
-	nop			# and 8 evict cycles, i.e. at least 32 instr.
-	nop
-	nop
-	pref	30,0(a0)	# continue setting up the dest, addr 64-0
-	sw	a1,-32(a0)
-	sw	a1,-28(a0)
-	sw	a1,-24(a0)
-	sw	a1,-20(a0)
-	sw	a1,-16(a0)
-	sw	a1,-12(a0)
-	sw	a1,-8(a0)
-	sw	a1,-4(a0)
-	nop
-	nop
-	nop
-	nop			# NOTE: adding 14 nop-s instead of 12 nop-s
-	nop			# gives better results for "fast" memory
-	nop
-	bne	a0,t4,.Lloop16w
-	 nop
-
-	beq	a0,a3,.Lchk8w	# maybe no more 64-byte chunks?
-	 nop			# this "delayed slot" is useless ...
-
-.Lloop16w_nopref30:	# there could be up to 3 "64-byte nopref30" chunks
-	addiu	a0,a0,64
-	sw	a1,-64(a0)
-	sw	a1,-60(a0)
-	sw	a1,-56(a0)
-	sw	a1,-52(a0)
-	sw	a1,-48(a0)
-	sw	a1,-44(a0)
-	sw	a1,-40(a0)
-	sw	a1,-36(a0)
-	sw	a1,-32(a0)
-	sw	a1,-28(a0)
-	sw	a1,-24(a0)
-	sw	a1,-20(a0)
-	sw	a1,-16(a0)
-	sw	a1,-12(a0)
-	sw	a1,-8(a0)
-	bne	a0,a3,.Lloop16w_nopref30
-	 sw	a1,-4(a0)
-
-.Lchk8w:		# t8 here is the byte count past 64-byte chunks
-
-	andi	t7,t8,0x1f	# is there a 32-byte chunk?
-				# the t7 is the reminder count past 32-bytes
-	beq	t8,t7,.Lchk1w	# when t8==t7, no 32-byte chunk
-	 move	a2,t7
-
-	sw	a1,0(a0)
-	sw	a1,4(a0)
-	sw	a1,8(a0)
-	sw	a1,12(a0)
-	sw	a1,16(a0)
-	sw	a1,20(a0)
-	sw	a1,24(a0)
-	sw	a1,28(a0)
-	addiu	a0,a0,32
-
-.Lchk1w:
-	andi	t8,a2,0x3	# now t8 is the reminder past 1w chunks
-	beq	a2,t8,.Llast4aligned
-	 subu	a3,a2,t8	# a3 is the count of bytes in 1w chunks
-	addu	a3,a0,a3	# now a3 is the dst address past the 1w chunks
-
-# copying in words (4-byte chunks)
-.LwordCopy_loop:
-	addiu	a0,a0,4
-	bne	a0,a3,.LwordCopy_loop
-	 sw	a1,-4(a0)
-
-# store last 0-3 bytes
-# this will repeat the last store if the memset finishes on a word boundary
-.Llast4aligned:
-	j	ra
-	 SWLO	a1,-1(t0)
-
-.Llast4:
-	beq	a0,t0,.Llast4e
-.Llast4l:
-	 addiu	a0,a0,1
-	bne	a0,t0,.Llast4l
-	 sb	a1,-1(a0)
-.Llast4e:
-	j	ra
-	 nop
-
-	.set	at
-	.set	reorder
-
-END(memset)
-
-
-/************************************************************************
- *  Implementation : Static functions
- ************************************************************************/
diff --git a/libcutils/arch-mips/android_memset.c b/libcutils/arch-mips/android_memset.c
new file mode 100644
index 0000000..a6b7496
--- /dev/null
+++ b/libcutils/arch-mips/android_memset.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* generic C version for any machine */
+
+#include <cutils/memory.h>
+
+void android_memset16(uint16_t* dst, uint16_t value, size_t size)
+{
+   /* optimized version of
+      size >>= 1;
+      while (size--)
+        *dst++ = value;
+   */
+
+   size >>= 1;
+   if (((uintptr_t)dst & 2) && size) {
+      /* fill unpaired first elem separately */
+      *dst++ = value;
+      size--;
+   }
+   /* dst is now 32-bit-aligned */
+   /* fill body with 32-bit pairs */
+   uint32_t value32 = (value << 16) | value;
+   android_memset32((uint32_t*) dst, value32, size<<1);
+   if (size & 1) {
+      dst[size-1] = value;  /* fill unpaired last elem */
+   }
+}
+
+
+void android_memset32(uint32_t* dst, uint32_t value, size_t size)
+{
+   /* optimized version of
+      size >>= 2;
+      while (size--)
+         *dst++ = value;
+   */
+
+   size >>= 2;
+   if (((uintptr_t)dst & 4) && size) {
+      /* fill unpaired first 32-bit elem separately */
+      *dst++ = value;
+      size--;
+   }
+   /* dst is now 64-bit aligned */
+   /* fill body with 64-bit pairs */
+   uint64_t value64 = (((uint64_t)value)<<32) | value;
+   uint64_t* dst64 = (uint64_t*)dst;
+
+   while (size >= 12) {
+      dst64[0] = value64;
+      dst64[1] = value64;
+      dst64[2] = value64;
+      dst64[3] = value64;
+      dst64[4] = value64;
+      dst64[5] = value64;
+      size  -= 12;
+      dst64 += 6;
+   }
+
+   /* fill remainder with original 32-bit single-elem loop */
+   dst = (uint32_t*) dst64;
+   while (size--) {
+      *dst++ = value;
+   }
+
+}
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 659f614..9f8023e 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -19,11 +19,54 @@
 ** by the device side of adb.
 */
 
+#define LOG_TAG "fs_config"
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
 #include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 
+#include <log/log.h>
 #include <private/android_filesystem_config.h>
+#include <utils/Compat.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* The following structure is stored little endian */
+struct fs_path_config_from_file {
+    uint16_t len;
+    uint16_t mode;
+    uint16_t uid;
+    uint16_t gid;
+    uint64_t capabilities;
+    char prefix[];
+} __attribute__((__aligned__(sizeof(uint64_t))));
+
+/* My kingdom for <endian.h> */
+static inline uint16_t get2LE(const uint8_t* src)
+{
+    return src[0] | (src[1] << 8);
+}
+
+static inline uint64_t get8LE(const uint8_t* src)
+{
+    uint32_t low, high;
+
+    low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+    high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
+    return ((uint64_t) high << 32) | (uint64_t) low;
+}
+
+#define ALIGN(x, alignment) ( ((x) + ((alignment) - 1)) & ~((alignment) - 1) )
 
 /* Rules for directories.
 ** These rules are applied based on "first match", so they
@@ -61,6 +104,9 @@
 ** way up to the root. Prefixes ending in * denotes wildcard
 ** and will allow partial matches.
 */
+static const char conf_dir[] = "/system/etc/fs_config_dirs";
+static const char conf_file[] = "/system/etc/fs_config_files";
+
 static const struct fs_path_config android_files[] = {
     { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },
     { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },
@@ -68,6 +114,8 @@
     { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, conf_dir + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, conf_file + 1 },
     { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
     { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
     { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
@@ -101,30 +149,102 @@
     { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
 };
 
+static int fs_config_open(int dir)
+{
+    int fd = -1;
+
+    const char *out = getenv("OUT");
+    if (out && *out) {
+        char *name = NULL;
+        asprintf(&name, "%s%s", out, dir ? conf_dir : conf_file);
+        if (name) {
+            fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_BINARY));
+            free(name);
+        }
+    }
+    if (fd < 0) {
+        fd = TEMP_FAILURE_RETRY(open(dir ? conf_dir : conf_file, O_RDONLY | O_BINARY));
+    }
+    return fd;
+}
+
+static bool fs_config_cmp(bool dir, const char *prefix, size_t len,
+                                    const char *path, size_t plen)
+{
+    if (dir) {
+        if (plen < len) {
+            return false;
+        }
+    } else {
+        /* If name ends in * then allow partial matches. */
+        if (prefix[len - 1] == '*') {
+            return !strncmp(prefix, path, len - 1);
+        }
+        if (plen != len) {
+            return false;
+        }
+    }
+    return !strncmp(prefix, path, len);
+}
+
 void fs_config(const char *path, int dir,
                unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
 {
     const struct fs_path_config *pc;
-    int plen;
+    int fd, plen;
 
     if (path[0] == '/') {
         path++;
     }
 
-    pc = dir ? android_dirs : android_files;
     plen = strlen(path);
-    for(; pc->prefix; pc++){
-        int len = strlen(pc->prefix);
-        if (dir) {
-            if(plen < len) continue;
-            if(!strncmp(pc->prefix, path, len)) break;
-            continue;
+
+    fd = fs_config_open(dir);
+    if (fd >= 0) {
+        struct fs_path_config_from_file header;
+
+        while (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) == sizeof(header)) {
+            char *prefix;
+            uint16_t host_len = get2LE((const uint8_t *)&header.len);
+            ssize_t len, remainder = host_len - sizeof(header);
+            if (remainder <= 0) {
+                ALOGE("%s len is corrupted", dir ? conf_dir : conf_file);
+                break;
+            }
+            prefix = calloc(1, remainder);
+            if (!prefix) {
+                ALOGE("%s out of memory", dir ? conf_dir : conf_file);
+                break;
+            }
+            if (TEMP_FAILURE_RETRY(read(fd, prefix, remainder)) != remainder) {
+                free(prefix);
+                ALOGE("%s prefix is truncated", dir ? conf_dir : conf_file);
+                break;
+            }
+            len = strnlen(prefix, remainder);
+            if (len >= remainder) { /* missing a terminating null */
+                free(prefix);
+                ALOGE("%s is corrupted", dir ? conf_dir : conf_file);
+                break;
+            }
+            if (fs_config_cmp(dir, prefix, len, path, plen)) {
+                free(prefix);
+                close(fd);
+                *uid = get2LE((const uint8_t *)&(header.uid));
+                *gid = get2LE((const uint8_t *)&(header.gid));
+                *mode = (*mode & (~07777)) | get2LE((const uint8_t *)&(header.mode));
+                *capabilities = get8LE((const uint8_t *)&(header.capabilities));
+                return;
+            }
+            free(prefix);
         }
-        /* If name ends in * then allow partial matches. */
-        if (pc->prefix[len -1] == '*') {
-            if(!strncmp(pc->prefix, path, len - 1)) break;
-        } else if (plen == len){
-            if(!strncmp(pc->prefix, path, len)) break;
+        close(fd);
+    }
+
+    pc = dir ? android_dirs : android_files;
+    for(; pc->prefix; pc++){
+        if (fs_config_cmp(dir, pc->prefix, strlen(pc->prefix), path, plen)) {
+            break;
         }
     }
     *uid = pc->uid;
@@ -132,3 +252,22 @@
     *mode = (*mode & (~07777)) | pc->mode;
     *capabilities = pc->capabilities;
 }
+
+ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc)
+{
+    struct fs_path_config_from_file *p = (struct fs_path_config_from_file *)buffer;
+    size_t len = ALIGN(sizeof(*p) + strlen(pc->prefix) + 1, sizeof(uint64_t));
+
+    if ((length < len) || (len > UINT16_MAX)) {
+        return -ENOSPC;
+    }
+    memset(p, 0, len);
+    uint16_t host_len = len;
+    p->len = get2LE((const uint8_t *)&host_len);
+    p->mode = get2LE((const uint8_t *)&(pc->mode));
+    p->uid = get2LE((const uint8_t *)&(pc->uid));
+    p->gid = get2LE((const uint8_t *)&(pc->gid));
+    p->capabilities = get8LE((const uint8_t *)&(pc->capabilities));
+    strcpy(p->prefix, pc->prefix);
+    return len;
+}
diff --git a/libcutils/trace-dev.c b/libcutils/trace-dev.c
index 4396625..a06987e 100644
--- a/libcutils/trace-dev.c
+++ b/libcutils/trace-dev.c
@@ -18,11 +18,11 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <pthread.h>
+#include <stdatomic.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-#include <cutils/atomic.h>
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
 #include <cutils/trace.h>
@@ -37,11 +37,11 @@
  */
 #define ATRACE_MESSAGE_LENGTH 1024
 
-volatile int32_t        atrace_is_ready      = 0;
+atomic_bool             atrace_is_ready      = ATOMIC_VAR_INIT(false);
 int                     atrace_marker_fd     = -1;
 uint64_t                atrace_enabled_tags  = ATRACE_TAG_NOT_READY;
 static bool             atrace_is_debuggable = false;
-static volatile int32_t atrace_is_enabled    = 1;
+static atomic_bool      atrace_is_enabled    = ATOMIC_VAR_INIT(true);
 static pthread_once_t   atrace_once_control  = PTHREAD_ONCE_INIT;
 static pthread_mutex_t  atrace_tags_mutex    = PTHREAD_MUTEX_INITIALIZER;
 
@@ -58,7 +58,7 @@
 // the Zygote process from tracing.
 void atrace_set_tracing_enabled(bool enabled)
 {
-    android_atomic_release_store(enabled ? 1 : 0, &atrace_is_enabled);
+    atomic_store_explicit(&atrace_is_enabled, enabled, memory_order_release);
     atrace_update_tags();
 }
 
@@ -155,8 +155,8 @@
 void atrace_update_tags()
 {
     uint64_t tags;
-    if (CC_UNLIKELY(android_atomic_acquire_load(&atrace_is_ready))) {
-        if (android_atomic_acquire_load(&atrace_is_enabled)) {
+    if (CC_UNLIKELY(atomic_load_explicit(&atrace_is_ready, memory_order_acquire))) {
+        if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
             tags = atrace_get_property();
             pthread_mutex_lock(&atrace_tags_mutex);
             atrace_enabled_tags = tags;
@@ -183,7 +183,7 @@
     atrace_enabled_tags = atrace_get_property();
 
 done:
-    android_atomic_release_store(1, &atrace_is_ready);
+    atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
 }
 
 void atrace_setup()
diff --git a/libcutils/trace-host.c b/libcutils/trace-host.c
index b87e543..6478e3e 100644
--- a/libcutils/trace-host.c
+++ b/libcutils/trace-host.c
@@ -20,7 +20,7 @@
 #define __unused __attribute__((__unused__))
 #endif
 
-volatile int32_t        atrace_is_ready      = 1;
+atomic_bool             atrace_is_ready      = ATOMIC_VAR_INIT(true);
 int                     atrace_marker_fd     = -1;
 uint64_t                atrace_enabled_tags  = 0;
 
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index 65c09e0..311678a 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -238,14 +238,15 @@
 	struct backed_block *last_bb = NULL;
 	struct backed_block *bb;
 	struct backed_block *start;
+	unsigned int last_block = 0;
 	int64_t file_len = 0;
 	int ret;
 
 	/*
-	 * overhead is sparse file header, initial skip chunk, split chunk, end
-	 * skip chunk, and crc chunk.
+	 * overhead is sparse file header, the potential end skip
+	 * chunk and crc chunk.
 	 */
-	int overhead = sizeof(sparse_header_t) + 4 * sizeof(chunk_header_t) +
+	int overhead = sizeof(sparse_header_t) + 2 * sizeof(chunk_header_t) +
 			sizeof(uint32_t);
 	len -= overhead;
 
@@ -258,6 +259,11 @@
 
 	for (bb = start; bb; bb = backed_block_iter_next(bb)) {
 		count = 0;
+		if (backed_block_block(bb) > last_block)
+			count += sizeof(chunk_header_t);
+		last_block = backed_block_block(bb) +
+				DIV_ROUND_UP(backed_block_len(bb), to->block_size);
+
 		/* will call out_counter_write to update count */
 		ret = sparse_file_write_block(out_counter, bb);
 		if (ret) {
@@ -270,6 +276,7 @@
 			 * requested size, split the chunk.  Results in sparse files that
 			 * are at least 7/8ths of the requested size
 			 */
+			file_len += sizeof(chunk_header_t);
 			if (!last_bb || (len - file_len > (len / 8))) {
 				backed_block_split(from->backed_block_list, bb, len - file_len);
 				last_bb = bb;
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 57c46a3..8582344 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -1131,7 +1131,22 @@
     return kIoError;
   }
 
-  int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
+  int result = 0;
+#if defined(__linux__)
+  // Make sure we have enough space on the volume to extract the compressed
+  // entry. Note that the call to ftruncate below will change the file size but
+  // will not allocate space on disk.
+  if (declared_length > 0) {
+    result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
+    if (result == -1) {
+      ALOGW("Zip: unable to allocate space for file to %" PRId64 ": %s",
+            static_cast<int64_t>(declared_length + current_offset), strerror(errno));
+      return kIoError;
+    }
+  }
+#endif  // defined(__linux__)
+
+  result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
   if (result == -1) {
     ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
           static_cast<int64_t>(declared_length + current_offset), strerror(errno));
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 90370e9..caae54b 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -155,12 +155,14 @@
         event->length = htole32(l);
         memcpy(event->data, str, l);
 
-        logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
-                    reinterpret_cast<char *>(event),
-                    (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+        rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
+                         reinterpret_cast<char *>(event),
+                         (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
         free(event);
 
-        notify = true;
+        if (rc >= 0) {
+            notify = true;
+        }
     }
 
     // log to main
@@ -197,17 +199,22 @@
         strncpy(newstr + 1 + l, str, estr - str);
         strcpy(newstr + 1 + l + (estr - str), ecomm);
 
-        logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
-                    (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+        rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
+                         (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
         free(newstr);
 
-        notify = true;
+        if (rc >= 0) {
+            notify = true;
+        }
     }
 
     free(str);
 
     if (notify) {
         reader->notifyNewLog();
+        if (rc < 0) {
+            rc = n;
+        }
     }
 
     return rc;
@@ -216,7 +223,7 @@
 int LogAudit::log(char *buf) {
     char *audit = strstr(buf, " audit(");
     if (!audit) {
-        return 0;
+        return -EXDEV;
     }
 
     *audit = '\0';
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 260e237..a0436ef 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <ctype.h>
+#include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/user.h>
@@ -132,11 +133,11 @@
     init();
 }
 
-void LogBuffer::log(log_id_t log_id, log_time realtime,
-                    uid_t uid, pid_t pid, pid_t tid,
-                    const char *msg, unsigned short len) {
+int LogBuffer::log(log_id_t log_id, log_time realtime,
+                   uid_t uid, pid_t pid, pid_t tid,
+                   const char *msg, unsigned short len) {
     if ((log_id >= LOG_ID_MAX) || (log_id < 0)) {
-        return;
+        return -EINVAL;
     }
     LogBufferElement *elem = new LogBufferElement(log_id, realtime,
                                                   uid, pid, tid, msg, len);
@@ -193,6 +194,8 @@
     stats.add(elem);
     maybePrune(log_id);
     pthread_mutex_unlock(&mLogElementsLock);
+
+    return len;
 }
 
 // If we're using more than 256K of memory for log entries, prune
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index a29e015..9ee243d 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -48,9 +48,9 @@
     LogBuffer(LastLogTimes *times);
     void init();
 
-    void log(log_id_t log_id, log_time realtime,
-             uid_t uid, pid_t pid, pid_t tid,
-             const char *msg, unsigned short len);
+    int log(log_id_t log_id, log_time realtime,
+            uid_t uid, pid_t pid, pid_t tid,
+            const char *msg, unsigned short len);
     uint64_t flushTo(SocketClient *writer, const uint64_t start,
                      bool privileged,
                      int (*filter)(const LogBufferElement *element, void *arg) = NULL,
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 3b4ef88..05ced06 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -98,10 +98,11 @@
     // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
     // truncated message to the logs.
 
-    logbuf->log((log_id_t)header->id, header->realtime,
-        cred->uid, cred->pid, header->tid, msg,
-        ((size_t) n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
-    reader->notifyNewLog();
+    if (logbuf->log((log_id_t)header->id, header->realtime,
+            cred->uid, cred->pid, header->tid, msg,
+            ((size_t) n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX) >= 0) {
+        reader->notifyNewLog();
+    }
 
     return true;
 }
diff --git a/logd/main.cpp b/logd/main.cpp
index 4aa38b3..eb29596 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -367,12 +367,12 @@
 
             int rc = klogctl(KLOG_READ_ALL, buf, len);
 
-            buf[len - 1] = '\0';
+            if (rc >= 0) {
+                buf[len - 1] = '\0';
 
-            for(char *ptr, *tok = buf;
-                    (rc >= 0) && ((tok = strtok_r(tok, "\r\n", &ptr)));
-                    tok = NULL) {
-                rc = al->log(tok);
+                for (char *ptr, *tok = buf; (tok = strtok_r(tok, "\r\n", &ptr)); tok = NULL) {
+                    al->log(tok);
+                }
             }
         }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a2b8f59..a5ea60a 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -248,6 +248,7 @@
     mkdir /data/misc/bluedroid 0770 bluetooth net_bt_stack
     mkdir /data/misc/bluetooth 0770 system system
     mkdir /data/misc/keystore 0700 keystore keystore
+    mkdir /data/misc/gatekeeper 0700 system system
     mkdir /data/misc/keychain 0771 system system
     mkdir /data/misc/net 0750 root shell
     mkdir /data/misc/radio 0770 system radio