Merge changes Ie7becb64,I02ced540

* changes:
  Revert "adb: extend sync protocol's stat support."
  Revert "adb: move adb_strerror to sysdeps/win32/errno.cpp."
diff --git a/adb/Android.mk b/adb/Android.mk
index 16ed991..be04cfa 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -50,7 +50,6 @@
     fdevent.cpp \
     sockets.cpp \
     socket_spec.cpp \
-    sysdeps/errno.cpp \
     transport.cpp \
     transport_local.cpp \
     transport_usb.cpp \
@@ -89,12 +88,10 @@
 
 LIBADB_windows_SRC_FILES := \
     sysdeps_win32.cpp \
-    sysdeps/win32/errno.cpp \
     sysdeps/win32/stat.cpp \
     usb_windows.cpp \
 
 LIBADB_TEST_windows_SRCS := \
-    sysdeps/win32/errno_test.cpp \
     sysdeps_win32_test.cpp \
 
 include $(CLEAR_VARS)
diff --git a/adb/adb.h b/adb/adb.h
index 19f09a3..df59aaa 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -51,7 +51,7 @@
 std::string adb_version();
 
 // Increment this when we want to force users to start a new adb server.
-#define ADB_SERVER_VERSION 38
+#define ADB_SERVER_VERSION 37
 
 class atransport;
 struct usb_handle;
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 5160569..caa7a5f 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -15,10 +15,12 @@
  */
 
 #include <dirent.h>
+#include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
@@ -41,7 +43,6 @@
 #include "adb_utils.h"
 #include "file_sync_service.h"
 #include "line_printer.h"
-#include "sysdeps/errno.h"
 #include "sysdeps/stat.h"
 
 #include <android-base/file.h>
@@ -74,8 +75,8 @@
 struct copyinfo {
     std::string lpath;
     std::string rpath;
-    int64_t time = 0;
-    uint32_t mode;
+    unsigned int time = 0;
+    unsigned int mode;
     uint64_t size = 0;
     bool skip = false;
 
@@ -202,16 +203,9 @@
         max = SYNC_DATA_MAX; // TODO: decide at runtime.
 
         std::string error;
-        FeatureSet features;
-        if (!adb_get_feature_set(&features, &error)) {
-            fd = -1;
-            Error("failed to get feature set: %s", error.c_str());
-        } else {
-            have_stat_v2_ = CanUseFeature(features, kFeatureStat2);
-            fd = adb_connect("sync:", &error);
-            if (fd < 0) {
-                Error("connect failed: %s", error.c_str());
-            }
+        fd = adb_connect("sync:", &error);
+        if (fd < 0) {
+            Error("connect failed: %s", error.c_str());
         }
     }
 
@@ -298,77 +292,6 @@
         return WriteFdExactly(fd, &buf[0], buf.size());
     }
 
-    bool SendStat(const char* path_and_mode) {
-        if (!have_stat_v2_) {
-            errno = ENOTSUP;
-            return false;
-        }
-        return SendRequest(ID_STAT_V2, path_and_mode);
-    }
-
-    bool SendLstat(const char* path_and_mode) {
-        if (have_stat_v2_) {
-            return SendRequest(ID_LSTAT_V2, path_and_mode);
-        } else {
-            return SendRequest(ID_LSTAT_V1, path_and_mode);
-        }
-    }
-
-    bool FinishStat(struct stat* st) {
-        syncmsg msg;
-
-        memset(st, 0, sizeof(*st));
-        if (have_stat_v2_) {
-            if (!ReadFdExactly(fd, &msg.stat_v2, sizeof(msg.stat_v2))) {
-                fatal_errno("protocol fault: failed to read stat response");
-            }
-
-            if (msg.stat_v2.id != ID_LSTAT_V2 && msg.stat_v2.id != ID_STAT_V2) {
-                fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
-                            msg.stat_v2.id);
-            }
-
-            if (msg.stat_v2.error != 0) {
-                errno = translate_linux_errno(msg.stat_v2.error);
-                return false;
-            }
-
-            st->st_dev = msg.stat_v2.dev;
-            st->st_ino = msg.stat_v2.ino;
-            st->st_mode = msg.stat_v2.mode;
-            st->st_nlink = msg.stat_v2.nlink;
-            st->st_uid = msg.stat_v2.uid;
-            st->st_gid = msg.stat_v2.gid;
-            st->st_size = msg.stat_v2.size;
-            st->st_atime = msg.stat_v2.atime;
-            st->st_mtime = msg.stat_v2.mtime;
-            st->st_ctime = msg.stat_v2.ctime;
-            return true;
-        } else {
-            if (!ReadFdExactly(fd, &msg.stat_v1, sizeof(msg.stat_v1))) {
-                fatal_errno("protocol fault: failed to read stat response");
-            }
-
-            if (msg.stat_v1.id != ID_LSTAT_V1) {
-                fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
-                            msg.stat_v1.id);
-            }
-
-            if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.time == 0) {
-                // There's no way for us to know what the error was.
-                errno = ENOPROTOOPT;
-                return false;
-            }
-
-            st->st_mode = msg.stat_v1.mode;
-            st->st_size = msg.stat_v1.size;
-            st->st_ctime = msg.stat_v1.time;
-            st->st_mtime = msg.stat_v1.time;
-        }
-
-        return true;
-    }
-
     // Sending header, payload, and footer in a single write makes a huge
     // difference to "adb sync" performance.
     bool SendSmallFile(const char* path_and_mode,
@@ -506,7 +429,7 @@
             return false;
         }
         buf[msg.status.msglen] = 0;
-        Error("failed to copy '%s' to '%s': remote %s", from, to, &buf[0]);
+        Error("failed to copy '%s' to '%s': %s", from, to, &buf[0]);
         return false;
     }
 
@@ -577,7 +500,6 @@
 
   private:
     bool expect_done_;
-    bool have_stat_v2_;
 
     TransferLedger global_ledger_;
     TransferLedger current_ledger_;
@@ -633,47 +555,25 @@
     }
 }
 
-static bool sync_stat(SyncConnection& sc, const char* path, struct stat* st) {
-    return sc.SendStat(path) && sc.FinishStat(st);
-}
-
-static bool sync_lstat(SyncConnection& sc, const char* path, struct stat* st) {
-    return sc.SendLstat(path) && sc.FinishStat(st);
-}
-
-static bool sync_stat_fallback(SyncConnection& sc, const char* path, struct stat* st) {
-    if (sync_stat(sc, path, st)) {
-        return true;
-    }
-
-    if (errno != ENOTSUP) {
+static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp,
+                             unsigned int* mode, unsigned int* size) {
+    syncmsg msg;
+    if (!ReadFdExactly(sc.fd, &msg.stat, sizeof(msg.stat)) || msg.stat.id != ID_STAT) {
         return false;
     }
 
-    // Try to emulate the parts we can when talking to older adbds.
-    bool lstat_result = sync_lstat(sc, path, st);
-    if (!lstat_result) {
-        return false;
-    }
+    if (timestamp) *timestamp = msg.stat.time;
+    if (mode) *mode = msg.stat.mode;
+    if (size) *size = msg.stat.size;
 
-    if (S_ISLNK(st->st_mode)) {
-        // If the target is a symlink, figure out whether it's a file or a directory.
-        // Also, zero out the st_size field, since no one actually cares what the path length is.
-        st->st_size = 0;
-        std::string dir_path = path;
-        dir_path.push_back('/');
-        struct stat tmp_st;
-
-        st->st_mode &= ~S_IFMT;
-        if (sync_lstat(sc, dir_path.c_str(), &tmp_st)) {
-            st->st_mode |= S_IFDIR;
-        } else {
-            st->st_mode |= S_IFREG;
-        }
-    }
     return true;
 }
 
+static bool sync_stat(SyncConnection& sc, const char* path,
+                      unsigned int* timestamp, unsigned int* mode, unsigned int* size) {
+    return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size);
+}
+
 static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
                       unsigned mtime, mode_t mode)
 {
@@ -721,11 +621,8 @@
 
 static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
                       const char* name=nullptr) {
-    struct stat st;
-    if (!sync_stat_fallback(sc, rpath, &st)) {
-        sc.Error("stat failed when trying to receive %s: %s", rpath, strerror(errno));
-        return false;
-    }
+    unsigned size = 0;
+    if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
 
     if (!sc.SendRequest(ID_RECV, rpath)) return false;
 
@@ -778,7 +675,7 @@
         bytes_copied += msg.data.size;
 
         sc.RecordBytesTransferred(msg.data.size);
-        sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, st.st_size);
+        sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, size);
     }
 
     sc.RecordFilesTransferred(1);
@@ -881,20 +778,20 @@
 
     if (check_timestamps) {
         for (const copyinfo& ci : file_list) {
-            if (!sc.SendLstat(ci.rpath.c_str())) {
-                sc.Error("failed to send lstat");
+            if (!sc.SendRequest(ID_STAT, ci.rpath.c_str())) {
                 return false;
             }
         }
         for (copyinfo& ci : file_list) {
-            struct stat st;
-            if (sc.FinishStat(&st)) {
-                if (st.st_size == static_cast<off_t>(ci.size)) {
-                    // For links, we cannot update the atime/mtime.
-                    if ((S_ISREG(ci.mode & st.st_mode) && st.st_mtime == ci.time) ||
-                        (S_ISLNK(ci.mode & st.st_mode) && st.st_mtime >= ci.time)) {
-                        ci.skip = true;
-                    }
+            unsigned int timestamp, mode, size;
+            if (!sync_finish_stat(sc, &timestamp, &mode, &size)) {
+                return false;
+            }
+            if (size == ci.size) {
+                // For links, we cannot update the atime/mtime.
+                if ((S_ISREG(ci.mode & mode) && timestamp == ci.time) ||
+                        (S_ISLNK(ci.mode & mode) && timestamp >= ci.time)) {
+                    ci.skip = true;
                 }
             }
         }
@@ -926,22 +823,10 @@
     if (!sc.IsValid()) return false;
 
     bool success = true;
-    bool dst_exists;
-    bool dst_isdir;
-
-    struct stat st;
-    if (sync_stat_fallback(sc, dst, &st)) {
-        dst_exists = true;
-        dst_isdir = S_ISDIR(st.st_mode);
-    } else {
-        if (errno == ENOENT || errno == ENOPROTOOPT) {
-            dst_exists = false;
-            dst_isdir = false;
-        } else {
-            sc.Error("stat failed when trying to push to %s: %s", dst, strerror(errno));
-            return false;
-        }
-    }
+    unsigned dst_mode;
+    if (!sync_stat(sc, dst, nullptr, &dst_mode, nullptr)) return false;
+    bool dst_exists = (dst_mode != 0);
+    bool dst_isdir = S_ISDIR(dst_mode);
 
     if (!dst_isdir) {
         if (srcs.size() > 1) {
@@ -986,7 +871,8 @@
                 dst_dir.append(adb_basename(src_path));
             }
 
-            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), false, false);
+            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(),
+                                             false, false);
             continue;
         } else if (!should_push_file(st.st_mode)) {
             sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
@@ -1015,6 +901,17 @@
     return success;
 }
 
+static bool remote_symlink_isdir(SyncConnection& sc, const std::string& rpath) {
+    unsigned mode;
+    std::string dir_path = rpath;
+    dir_path.push_back('/');
+    if (!sync_stat(sc, dir_path.c_str(), nullptr, &mode, nullptr)) {
+        sc.Error("failed to stat remote symlink '%s'", dir_path.c_str());
+        return false;
+    }
+    return S_ISDIR(mode);
+}
+
 static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
                               const std::string& rpath, const std::string& lpath) {
     std::vector<copyinfo> dirlist;
@@ -1052,13 +949,7 @@
 
     // Check each symlink we found to see whether it's a file or directory.
     for (copyinfo& link_ci : linklist) {
-        struct stat st;
-        if (!sync_stat_fallback(sc, link_ci.rpath.c_str(), &st)) {
-            sc.Warning("stat failed for path %s: %s", link_ci.rpath.c_str(), strerror(errno));
-            continue;
-        }
-
-        if (S_ISDIR(st.st_mode)) {
+        if (remote_symlink_isdir(sc, link_ci.rpath)) {
             dirlist.emplace_back(std::move(link_ci));
         } else {
             file_list->emplace_back(std::move(link_ci));
@@ -1184,19 +1075,22 @@
 
     for (const char* src_path : srcs) {
         const char* dst_path = dst;
-        struct stat src_st;
-        if (!sync_stat_fallback(sc, src_path, &src_st)) {
-            if (errno == ENOPROTOOPT) {
-                sc.Error("remote object '%s' does not exist", src_path);
-            } else {
-                sc.Error("failed to stat remote object '%s': %s", src_path, strerror(errno));
-            }
-
+        unsigned src_mode, src_time, src_size;
+        if (!sync_stat(sc, src_path, &src_time, &src_mode, &src_size)) {
+            sc.Error("failed to stat remote object '%s'", src_path);
+            return false;
+        }
+        if (src_mode == 0) {
+            sc.Error("remote object '%s' does not exist", src_path);
             success = false;
             continue;
         }
 
-        bool src_isdir = S_ISDIR(src_st.st_mode);
+        bool src_isdir = S_ISDIR(src_mode);
+        if (S_ISLNK(src_mode)) {
+            src_isdir = remote_symlink_isdir(sc, src_path);
+        }
+
         if (src_isdir) {
             std::string dst_dir = dst;
 
@@ -1215,8 +1109,8 @@
 
             success &= copy_remote_dir_local(sc, src_path, dst_dir.c_str(), copy_attrs);
             continue;
-        } else if (!should_pull_file(src_st.st_mode)) {
-            sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode);
+        } else if (!should_pull_file(src_mode)) {
+            sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_mode);
             continue;
         }
 
@@ -1231,13 +1125,13 @@
         }
 
         sc.NewTransfer();
-        sc.SetExpectedTotalBytes(src_st.st_size);
+        sc.SetExpectedTotalBytes(src_size);
         if (!sync_recv(sc, src_path, dst_path, name)) {
             success = false;
             continue;
         }
 
-        if (copy_attrs && set_time_and_mode(dst_path, src_st.st_mtime, src_st.st_mode) != 0) {
+        if (copy_attrs && set_time_and_mode(dst_path, src_time, src_mode) != 0) {
             success = false;
             continue;
         }
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 57a8a45..7a92d2e 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -98,47 +98,18 @@
     return true;
 }
 
-static bool do_lstat_v1(int s, const char* path) {
-    syncmsg msg = {};
-    msg.stat_v1.id = ID_LSTAT_V1;
+static bool do_stat(int s, const char* path) {
+    syncmsg msg;
+    msg.stat.id = ID_STAT;
 
     struct stat st = {};
+    // TODO: add a way to report that the stat failed!
     lstat(path, &st);
-    msg.stat_v1.mode = st.st_mode;
-    msg.stat_v1.size = st.st_size;
-    msg.stat_v1.time = st.st_mtime;
-    return WriteFdExactly(s, &msg.stat_v1, sizeof(msg.stat_v1));
-}
+    msg.stat.mode = st.st_mode;
+    msg.stat.size = st.st_size;
+    msg.stat.time = st.st_mtime;
 
-static bool do_stat_v2(int s, uint32_t id, const char* path) {
-    syncmsg msg = {};
-    msg.stat_v2.id = id;
-
-    decltype(&stat) stat_fn;
-    if (id == ID_STAT_V2) {
-        stat_fn = stat;
-    } else {
-        stat_fn = lstat;
-    }
-
-    struct stat st = {};
-    int rc = stat_fn(path, &st);
-    if (rc == -1) {
-        msg.stat_v2.error = errno;
-    } else {
-        msg.stat_v2.dev = st.st_dev;
-        msg.stat_v2.ino = st.st_ino;
-        msg.stat_v2.mode = st.st_mode;
-        msg.stat_v2.nlink = st.st_nlink;
-        msg.stat_v2.uid = st.st_uid;
-        msg.stat_v2.gid = st.st_gid;
-        msg.stat_v2.size = st.st_size;
-        msg.stat_v2.atime = st.st_atime;
-        msg.stat_v2.mtime = st.st_mtime;
-        msg.stat_v2.ctime = st.st_ctime;
-    }
-
-    return WriteFdExactly(s, &msg.stat_v2, sizeof(msg.stat_v2));
+    return WriteFdExactly(s, &msg.stat, sizeof(msg.stat));
 }
 
 static bool do_list(int s, const char* path) {
@@ -456,34 +427,30 @@
     D("sync: '%.4s' '%s'", id, name);
 
     switch (request.id) {
-        case ID_LSTAT_V1:
-            if (!do_lstat_v1(fd, name)) return false;
-            break;
-        case ID_LSTAT_V2:
-        case ID_STAT_V2:
-            if (!do_stat_v2(fd, request.id, name)) return false;
-            break;
-        case ID_LIST:
-            if (!do_list(fd, name)) return false;
-            break;
-        case ID_SEND:
-            if (!do_send(fd, name, buffer)) return false;
-            break;
-        case ID_RECV:
-            if (!do_recv(fd, name, buffer)) return false;
-            break;
-        case ID_QUIT:
-            return false;
-        default:
-            SendSyncFail(
-                fd, android::base::StringPrintf("unknown command '%.4s' (%08x)", id, request.id));
-            return false;
+      case ID_STAT:
+        if (!do_stat(fd, name)) return false;
+        break;
+      case ID_LIST:
+        if (!do_list(fd, name)) return false;
+        break;
+      case ID_SEND:
+        if (!do_send(fd, name, buffer)) return false;
+        break;
+      case ID_RECV:
+        if (!do_recv(fd, name, buffer)) return false;
+        break;
+      case ID_QUIT:
+        return false;
+      default:
+        SendSyncFail(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
+                                                     id, request.id));
+        return false;
     }
 
     return true;
 }
 
-void file_sync_service(int fd, void*) {
+void file_sync_service(int fd, void* cookie) {
     std::vector<char> buffer(SYNC_DATA_MAX);
 
     while (handle_sync_command(fd, buffer)) {
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 90f1965..0e25974 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -22,9 +22,7 @@
 
 #define MKID(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
 
-#define ID_LSTAT_V1 MKID('S','T','A','T')
-#define ID_STAT_V2 MKID('S','T','A','2')
-#define ID_LSTAT_V2 MKID('L','S','T','2')
+#define ID_STAT MKID('S','T','A','T')
 #define ID_LIST MKID('L','I','S','T')
 #define ID_SEND MKID('S','E','N','D')
 #define ID_RECV MKID('R','E','C','V')
@@ -47,21 +45,7 @@
         uint32_t mode;
         uint32_t size;
         uint32_t time;
-    } stat_v1;
-    struct __attribute__((packed)) {
-        uint32_t id;
-        uint32_t error;
-        uint64_t dev;
-        uint64_t ino;
-        uint32_t mode;
-        uint32_t nlink;
-        uint32_t uid;
-        uint32_t gid;
-        uint64_t size;
-        int64_t atime;
-        int64_t mtime;
-        int64_t ctime;
-    } stat_v2;
+    } stat;
     struct __attribute__((packed)) {
         uint32_t id;
         uint32_t mode;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 654072c..05d9fde 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -34,7 +34,6 @@
 #include <android-base/unique_fd.h>
 #include <android-base/utf8.h>
 
-#include "sysdeps/errno.h"
 #include "sysdeps/stat.h"
 
 /*
@@ -362,6 +361,9 @@
 
 #define getcwd adb_getcwd
 
+char* adb_strerror(int err);
+#define strerror adb_strerror
+
 // Helper class to convert UTF-16 argv from wmain() to UTF-8 args that can be
 // passed to main().
 class NarrowArgs {
diff --git a/adb/sysdeps/errno.cpp b/adb/sysdeps/errno.cpp
deleted file mode 100644
index 0f7f58a..0000000
--- a/adb/sysdeps/errno.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2016 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 "sysdeps/errno.h"
-
-#include <errno.h>
-
-#include <thread>
-#include <unordered_map>
-
-#include "adb.h"
-
-#if defined(_WIN32)
-#define ETXTBSY EBUSY
-#endif
-
-static std::unordered_map<int, int> initialize_translations() {
-    std::unordered_map<int, int> translations;
-#if defined(__linux__)
-#define ERRNO_VALUE(error_name, linux_value) static_assert((error_name) == (linux_value), "")
-#else
-#define ERRNO_VALUE(error_name, linux_value) \
-    translations.insert(std::make_pair((linux_value), (error_name)))
-#endif
-    // Untranslated errno values returned by open: EDQUOT, ENODEV, ENXIO, EWOULDBLOCK
-    ERRNO_VALUE(EACCES, 13);
-    ERRNO_VALUE(EEXIST, 17);
-    ERRNO_VALUE(EFAULT, 14);
-    ERRNO_VALUE(EFBIG, 27);
-    ERRNO_VALUE(EINTR, 4);
-    ERRNO_VALUE(EINVAL, 22);
-    ERRNO_VALUE(EIO, 5);
-    ERRNO_VALUE(EISDIR, 21);
-    ERRNO_VALUE(ELOOP, 40);
-    ERRNO_VALUE(EMFILE, 24);
-    ERRNO_VALUE(ENAMETOOLONG, 36);
-    ERRNO_VALUE(ENFILE, 23);
-    ERRNO_VALUE(ENOENT, 2);
-    ERRNO_VALUE(ENOMEM, 12);
-    ERRNO_VALUE(ENOSPC, 28);
-    ERRNO_VALUE(ENOTDIR, 20);
-    ERRNO_VALUE(EOVERFLOW, 75);
-    ERRNO_VALUE(EPERM, 1);
-    ERRNO_VALUE(EROFS, 30);
-    ERRNO_VALUE(ETXTBSY, 26);
-    return translations;
-}
-
-int translate_linux_errno(int error) {
-#if defined(__linux__)
-    UNUSED(initialize_translations);
-    return error;
-#else
-    static std::unordered_map<int, int> translations = initialize_translations();
-    auto it = translations.find(error);
-    if (it != translations.end()) {
-        return it->second;
-    }
-    fatal("received unexpected remote errno: %d", error);
-#endif
-}
diff --git a/adb/sysdeps/errno.h b/adb/sysdeps/errno.h
deleted file mode 100644
index f783b3a..0000000
--- a/adb/sysdeps/errno.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#pragma once
-
-#include <errno.h>
-#include <string.h>
-
-// Translate an errno value from linux to the host equivalent.
-int translate_linux_errno(int error);
-
-#if defined(_WIN32)
-char* adb_strerror(int err);
-#define strerror adb_strerror
-#endif
diff --git a/adb/sysdeps/win32/errno.cpp b/adb/sysdeps/win32/errno.cpp
deleted file mode 100644
index a3b9d9b..0000000
--- a/adb/sysdeps/win32/errno.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2016 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 "sysdeps/errno.h"
-
-#include <windows.h>
-
-#include <string>
-
-// Overrides strerror() to handle error codes not supported by the Windows C
-// Runtime (MSVCRT.DLL).
-char* adb_strerror(int err) {
-// sysdeps.h defines strerror to adb_strerror, but in this function, we
-// want to call the real C Runtime strerror().
-#pragma push_macro("strerror")
-#undef strerror
-    const int saved_err = errno;  // Save because we overwrite it later.
-
-    // Lookup the string for an unknown error.
-    char* errmsg = strerror(-1);
-    const std::string unknown_error = (errmsg == nullptr) ? "" : errmsg;
-
-    // Lookup the string for this error to see if the C Runtime has it.
-    errmsg = strerror(err);
-    if (errmsg != nullptr && unknown_error != errmsg) {
-        // The CRT returned an error message and it is different than the error
-        // message for an unknown error, so it is probably valid, so use it.
-    } else {
-        // Check if we have a string for this error code.
-        const char* custom_msg = nullptr;
-        switch (err) {
-#pragma push_macro("ERR")
-#undef ERR
-#define ERR(errnum, desc) case errnum: custom_msg = desc; break
-            // These error strings are from AOSP bionic/libc/include/sys/_errdefs.h.
-            // Note that these cannot be longer than 94 characters because we
-            // pass this to _strerror() which has that requirement.
-            ERR(ECONNRESET,    "Connection reset by peer");
-            ERR(EHOSTUNREACH,  "No route to host");
-            ERR(ENETDOWN,      "Network is down");
-            ERR(ENETRESET,     "Network dropped connection because of reset");
-            ERR(ENOBUFS,       "No buffer space available");
-            ERR(ENOPROTOOPT,   "Protocol not available");
-            ERR(ENOTCONN,      "Transport endpoint is not connected");
-            ERR(ENOTSOCK,      "Socket operation on non-socket");
-            ERR(EOPNOTSUPP,    "Operation not supported on transport endpoint");
-#pragma pop_macro("ERR")
-        }
-
-        if (custom_msg != nullptr) {
-            // Use _strerror() to write our string into the writable per-thread
-            // buffer used by strerror()/_strerror(). _strerror() appends the
-            // msg for the current value of errno, so set errno to a consistent
-            // value for every call so that our code-path is always the same.
-            errno = 0;
-            errmsg = _strerror(custom_msg);
-            const size_t custom_msg_len = strlen(custom_msg);
-            // Just in case _strerror() returned a read-only string, check if
-            // the returned string starts with our custom message because that
-            // implies that the string is not read-only.
-            if ((errmsg != nullptr) && !strncmp(custom_msg, errmsg, custom_msg_len)) {
-                // _strerror() puts other text after our custom message, so
-                // remove that by terminating after our message.
-                errmsg[custom_msg_len] = '\0';
-            } else {
-                // For some reason nullptr was returned or a pointer to a
-                // read-only string was returned, so fallback to whatever
-                // strerror() can muster (probably "Unknown error" or some
-                // generic CRT error string).
-                errmsg = strerror(err);
-            }
-        } else {
-            // We don't have a custom message, so use whatever strerror(err)
-            // returned earlier.
-        }
-    }
-
-    errno = saved_err;  // restore
-
-    return errmsg;
-#pragma pop_macro("strerror")
-}
diff --git a/adb/sysdeps/win32/errno_test.cpp b/adb/sysdeps/win32/errno_test.cpp
deleted file mode 100644
index 09ec52c..0000000
--- a/adb/sysdeps/win32/errno_test.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2016 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 "sysdeps/errno.h"
-
-#include <string>
-
-#include <gtest/gtest.h>
-
-void TestAdbStrError(int err, const char* expected) {
-    errno = 12345;
-    const char* result = adb_strerror(err);
-    // Check that errno is not overwritten.
-    EXPECT_EQ(12345, errno);
-    EXPECT_STREQ(expected, result);
-}
-
-TEST(sysdeps_win32, adb_strerror) {
-    // Test an error code that should not have a mapped string. Use an error
-    // code that is not used by the internal implementation of adb_strerror().
-    TestAdbStrError(-2, "Unknown error");
-    // adb_strerror() uses -1 internally, so test that it can still be passed
-    // as a parameter.
-    TestAdbStrError(-1, "Unknown error");
-    // Test very big, positive unknown error.
-    TestAdbStrError(1000000, "Unknown error");
-
-    // Test success case.
-    // Wine returns "Success" for strerror(0), Windows returns "No error", so accept both.
-    std::string success = adb_strerror(0);
-    EXPECT_TRUE(success == "Success" || success == "No error") << "strerror(0) = " << success;
-
-    // Test error that regular strerror() should have a string for.
-    TestAdbStrError(EPERM, "Operation not permitted");
-    // Test error that regular strerror() doesn't have a string for, but that
-    // adb_strerror() returns.
-    TestAdbStrError(ECONNRESET, "Connection reset by peer");
-}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index a4b5e69..4dd549d 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -477,6 +477,81 @@
     return 0;
 }
 
+// Overrides strerror() to handle error codes not supported by the Windows C
+// Runtime (MSVCRT.DLL).
+char* adb_strerror(int err) {
+    // sysdeps.h defines strerror to adb_strerror, but in this function, we
+    // want to call the real C Runtime strerror().
+#pragma push_macro("strerror")
+#undef strerror
+    const int saved_err = errno;      // Save because we overwrite it later.
+
+    // Lookup the string for an unknown error.
+    char* errmsg = strerror(-1);
+    const std::string unknown_error = (errmsg == nullptr) ? "" : errmsg;
+
+    // Lookup the string for this error to see if the C Runtime has it.
+    errmsg = strerror(err);
+    if (errmsg != nullptr && unknown_error != errmsg) {
+        // The CRT returned an error message and it is different than the error
+        // message for an unknown error, so it is probably valid, so use it.
+    } else {
+        // Check if we have a string for this error code.
+        const char* custom_msg = nullptr;
+        switch (err) {
+#pragma push_macro("ERR")
+#undef ERR
+#define ERR(errnum, desc) case errnum: custom_msg = desc; break
+            // These error strings are from AOSP bionic/libc/include/sys/_errdefs.h.
+            // Note that these cannot be longer than 94 characters because we
+            // pass this to _strerror() which has that requirement.
+            ERR(ECONNRESET,    "Connection reset by peer");
+            ERR(EHOSTUNREACH,  "No route to host");
+            ERR(ENETDOWN,      "Network is down");
+            ERR(ENETRESET,     "Network dropped connection because of reset");
+            ERR(ENOBUFS,       "No buffer space available");
+            ERR(ENOPROTOOPT,   "Protocol not available");
+            ERR(ENOTCONN,      "Transport endpoint is not connected");
+            ERR(ENOTSOCK,      "Socket operation on non-socket");
+            ERR(EOPNOTSUPP,    "Operation not supported on transport endpoint");
+#pragma pop_macro("ERR")
+        }
+
+        if (custom_msg != nullptr) {
+            // Use _strerror() to write our string into the writable per-thread
+            // buffer used by strerror()/_strerror(). _strerror() appends the
+            // msg for the current value of errno, so set errno to a consistent
+            // value for every call so that our code-path is always the same.
+            errno = 0;
+            errmsg = _strerror(custom_msg);
+            const size_t custom_msg_len = strlen(custom_msg);
+            // Just in case _strerror() returned a read-only string, check if
+            // the returned string starts with our custom message because that
+            // implies that the string is not read-only.
+            if ((errmsg != nullptr) &&
+                !strncmp(custom_msg, errmsg, custom_msg_len)) {
+                // _strerror() puts other text after our custom message, so
+                // remove that by terminating after our message.
+                errmsg[custom_msg_len] = '\0';
+            } else {
+                // For some reason nullptr was returned or a pointer to a
+                // read-only string was returned, so fallback to whatever
+                // strerror() can muster (probably "Unknown error" or some
+                // generic CRT error string).
+                errmsg = strerror(err);
+            }
+        } else {
+            // We don't have a custom message, so use whatever strerror(err)
+            // returned earlier.
+        }
+    }
+
+    errno = saved_err;  // restore
+
+    return errmsg;
+#pragma pop_macro("strerror")
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -490,7 +565,7 @@
 static void _socket_set_errno( const DWORD err ) {
     // Because the Windows C Runtime (MSVCRT.DLL) strerror() does not support a
     // lot of POSIX and socket error codes, some of the resulting error codes
-    // are mapped to strings by adb_strerror().
+    // are mapped to strings by adb_strerror() above.
     switch ( err ) {
     case 0:              errno = 0; break;
     // Don't map WSAEINTR since that is only for Winsock 1.1 which we don't use.
diff --git a/adb/sysdeps_win32_test.cpp b/adb/sysdeps_win32_test.cpp
index 529b212..c3a3fd7 100755
--- a/adb/sysdeps_win32_test.cpp
+++ b/adb/sysdeps_win32_test.cpp
@@ -70,6 +70,36 @@
     }
 }
 
+void TestAdbStrError(int err, const char* expected) {
+    errno = 12345;
+    const char* result = adb_strerror(err);
+    // Check that errno is not overwritten.
+    EXPECT_EQ(12345, errno);
+    EXPECT_STREQ(expected, result);
+}
+
+TEST(sysdeps_win32, adb_strerror) {
+    // Test an error code that should not have a mapped string. Use an error
+    // code that is not used by the internal implementation of adb_strerror().
+    TestAdbStrError(-2, "Unknown error");
+    // adb_strerror() uses -1 internally, so test that it can still be passed
+    // as a parameter.
+    TestAdbStrError(-1, "Unknown error");
+    // Test very big, positive unknown error.
+    TestAdbStrError(1000000, "Unknown error");
+
+    // Test success case.
+    // Wine returns "Success" for strerror(0), Windows returns "No error", so accept both.
+    std::string success = adb_strerror(0);
+    EXPECT_TRUE(success == "Success" || success == "No error") << "strerror(0) = " << success;
+
+    // Test error that regular strerror() should have a string for.
+    TestAdbStrError(EPERM, "Operation not permitted");
+    // Test error that regular strerror() doesn't have a string for, but that
+    // adb_strerror() returns.
+    TestAdbStrError(ECONNRESET, "Connection reset by peer");
+}
+
 TEST(sysdeps_win32, unix_isatty) {
     // stdin and stdout should be consoles. Use CONIN$ and CONOUT$ special files
     // so that we can test this even if stdin/stdout have been redirected. Read
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 7b82b19..132702d 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -49,7 +49,6 @@
 
 const char* const kFeatureShell2 = "shell_v2";
 const char* const kFeatureCmd = "cmd";
-const char* const kFeatureStat2 = "stat_v2";
 
 static std::string dump_packet(const char* name, const char* func, apacket* p) {
     unsigned  command = p->msg.command;
@@ -772,8 +771,7 @@
     // Local static allocation to avoid global non-POD variables.
     static const FeatureSet* features = new FeatureSet{
         kFeatureShell2,
-        kFeatureCmd,
-        kFeatureStat2,
+        kFeatureCmd
         // Increment ADB_SERVER_VERSION whenever the feature list changes to
         // make sure that the adb client and server features stay in sync
         // (http://b/24370690).
diff --git a/adb/transport.h b/adb/transport.h
index 3306388..b2df838 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -46,7 +46,6 @@
 extern const char* const kFeatureShell2;
 // The 'cmd' command is available
 extern const char* const kFeatureCmd;
-extern const char* const kFeatureStat2;
 
 class atransport {
 public: