Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07db1196 authored by Josh Gao's avatar Josh Gao
Browse files

adb: don't explode directories when pushing/pulling.

Previously, `adb pull /data/local/tmp` would spew all of the contents of
/data/local/tmp into the current directory. This patch makes push/pull
keep directories intact.

Bug: http://b/25394682
Change-Id: I2304ae9e61745a2b9536f58a6012640bf8ff422a
parent 12a2ae9a
Loading
Loading
Loading
Loading
+47 −15
Original line number Diff line number Diff line
@@ -657,8 +657,9 @@ bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
    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 (!S_ISDIR(dst_mode)) {
    if (!dst_isdir) {
        if (srcs.size() > 1) {
            sc.Error("target '%s' is not a directory", dst);
            return false;
@@ -684,12 +685,30 @@ bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
        }

        if (S_ISDIR(st.st_mode)) {
            success &= copy_local_dir_remote(sc, src_path, dst, false, false);
            std::string dst_dir = dst;

            // If the destination path existed originally, the source directory
            // should be copied as a child of the destination.
            if (dst_exists) {
                if (!dst_isdir) {
                    sc.Error("target '%s' is not a directory", dst);
                    return false;
                }
                // dst is a POSIX path, so we don't want to use the sysdeps
                // helpers here.
                if (dst_dir.back() != '/') {
                    dst_dir.push_back('/');
                }
                dst_dir.append(adb_basename(src_path));
            }

            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(),
                                             false, false);
            continue;
        }

        std::string path_holder;
        if (S_ISDIR(dst_mode)) {
        if (dst_isdir) {
            // If we're copying a local file to a remote directory,
            // we really want to copy to remote_dir + "/" + local_filename.
            path_holder = android::base::StringPrintf(
@@ -859,7 +878,8 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
        }
    }

    if (dst_exists && !S_ISDIR(st.st_mode)) {
    bool dst_isdir = dst_exists && S_ISDIR(st.st_mode);
    if (!dst_isdir) {
        if (srcs.size() > 1) {
            sc.Error("target '%s' is not a directory", dst);
            return false;
@@ -890,17 +910,13 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
        if (S_ISREG(src_mode) || S_ISLNK(src_mode)) {
            // TODO(b/25601283): symlinks shouldn't be handled as files.
            std::string path_holder;
            struct stat st;
            if (stat(dst_path, &st) == 0) {
                if (S_ISDIR(st.st_mode)) {
                    // If we're copying a remote file to a local directory,
                    // we really want to copy to local_dir + "/" +
                    // basename(remote).
            if (dst_isdir) {
                // If we're copying a remote file to a local directory, we
                // really want to copy to local_dir + "/" + basename(remote).
                path_holder = android::base::StringPrintf(
                    "%s/%s", dst_path, adb_basename(src_path).c_str());
                dst_path = path_holder.c_str();
            }
            }
            if (!sync_recv(sc, src_path, dst_path)) {
                success = false;
                continue;
@@ -912,7 +928,23 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
                }
            }
        } else if (S_ISDIR(src_mode)) {
            success &= copy_remote_dir_local(sc, src_path, dst_path, copy_attrs);
            std::string dst_dir = dst;

            // If the destination path existed originally, the source directory
            // should be copied as a child of the destination.
            if (dst_exists) {
                if (!dst_isdir) {
                    sc.Error("target '%s' is not a directory", dst);
                    return false;
                }
                if (!adb_is_separator(dst_dir.back())) {
                    dst_dir.push_back(OS_PATH_SEPARATOR);
                }
                dst_dir.append(adb_basename(src_path));
            }

            success &= copy_remote_dir_local(sc, src_path, dst_dir.c_str(),
                                             copy_attrs);
            continue;
        } else {
            sc.Error("remote object '%s' not a file or directory", src_path);
+8 −0
Original line number Diff line number Diff line
@@ -81,6 +81,10 @@
#define OS_PATH_SEPARATOR_STR "\\"
#define ENV_PATH_SEPARATOR_STR ";"

static __inline__ bool adb_is_separator(char c) {
    return c == '\\' || c == '/';
}

typedef CRITICAL_SECTION          adb_mutex_t;

#define  ADB_MUTEX_DEFINE(x)     adb_mutex_t   x
@@ -425,6 +429,10 @@ typedef std::unique_ptr<HANDLE, handle_deleter> unique_handle;
#define OS_PATH_SEPARATOR_STR "/"
#define ENV_PATH_SEPARATOR_STR ":"

static __inline__ bool adb_is_separator(char c) {
    return c == '/';
}

typedef  pthread_mutex_t          adb_mutex_t;

#define  ADB_MUTEX_INITIALIZER    PTHREAD_MUTEX_INITIALIZER