Index: source/Plugins/Platform/Android/AdbClient.h =================================================================== --- source/Plugins/Platform/Android/AdbClient.h +++ source/Plugins/Platform/Android/AdbClient.h @@ -53,6 +53,9 @@ Error PullFile (const char *remote_file, const char *local_file); + Error + PushFile (const char *local_file, const char *remote_file); + private: Error Connect (); Index: source/Plugins/Platform/Android/AdbClient.cpp =================================================================== --- source/Plugins/Platform/Android/AdbClient.cpp +++ source/Plugins/Platform/Android/AdbClient.cpp @@ -20,7 +20,9 @@ // Project includes #include "AdbClient.h" +#include #include +#include #include #include @@ -36,6 +38,10 @@ const char * kOKAY = "OKAY"; const char * kFAIL = "FAIL"; const size_t kSyncPacketLen = 8; +// Maximum size of a filesync DATA packet. +const size_t kMaxPushData = 2*1024; +// Default mode for pushed files. +const uint32_t kDefaultMode = S_IFREG | S_IRWXU | S_IRWXG; } // namespace @@ -281,6 +287,41 @@ } Error +AdbClient::PushFile (const char *local_file, const char *remote_file) +{ + auto error = SwitchDeviceTransport (); + if (error.Fail ()) + return Error ("Failed to switch to device transport: %s", error.AsCString ()); + + error = Sync (); + if (error.Fail ()) + return Error ("Sync failed: %s", error.AsCString ()); + + std::ifstream src (local_file, std::ios::in | std::ios::binary); + if (!src.is_open ()) + return Error ("Unable to open local file %s", local_file); + + std::stringstream file_description; + file_description << remote_file << "," << kDefaultMode; + error = SendSyncRequest ("SEND", file_description.str().length(), file_description.str().c_str()); + if (error.Fail ()) + return error; + + char chunk[kMaxPushData]; + while (!src.eof() && !src.read(chunk, kMaxPushData).bad()) { + size_t chunk_size = src.gcount(); + error = SendSyncRequest("DATA", chunk_size, chunk); + if (error.Fail ()) + return Error ("Failed to send file chunk: %s", error.AsCString ()); + } + time_t mtime = time(NULL); + error = SendSyncRequest("DONE", mtime, NULL); + if (error.Fail ()) + return error; + return ReadResponseStatus (); +} + +Error AdbClient::Sync () { auto error = SendMessage ("sync:", false); @@ -330,7 +371,8 @@ if (error.Fail ()) return error; - m_conn.Write (data, data_len, status, &error); + if (data) + m_conn.Write (data, data_len, status, &error); return error; } Index: source/Plugins/Platform/Android/PlatformAndroid.h =================================================================== --- source/Plugins/Platform/Android/PlatformAndroid.h +++ source/Plugins/Platform/Android/PlatformAndroid.h @@ -64,7 +64,13 @@ Error ConnectRemote (Args& args) override; - protected: + lldb_private::Error + PutFile (const lldb_private::FileSpec& source, + const lldb_private::FileSpec& destination, + uint32_t uid = UINT32_MAX, + uint32_t gid = UINT32_MAX) override; + + protected: const char * GetCacheHostname () override; Index: source/Plugins/Platform/Android/PlatformAndroid.cpp =================================================================== --- source/Plugins/Platform/Android/PlatformAndroid.cpp +++ source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -207,6 +207,21 @@ return error; } +lldb_private::Error +PlatformAndroid::PutFile (const lldb_private::FileSpec& source, + const lldb_private::FileSpec& destination, + uint32_t uid, + uint32_t gid) +{ + if (!IsHost() && m_remote_platform_sp) + { + AdbClient adb (m_device_id); + // TODO: Set correct uid and gid on remote file. + return adb.PushFile(source.GetPath().c_str(), destination.GetPath(false).c_str()); + } + return PlatformLinux::PutFile(source, destination, uid, gid); +} + const char * PlatformAndroid::GetCacheHostname () {