blob: b4de0a44a4b6a1c89223e16c0aaf021e3740dda9 [file] [log] [blame]
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +00001//===-- AdbClient.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Other libraries and framework includes
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000011#include "lldb/Core/DataBuffer.h"
12#include "lldb/Core/DataBufferHeap.h"
13#include "lldb/Core/DataEncoder.h"
14#include "lldb/Core/DataExtractor.h"
Tamas Berghammer9d8dde82015-09-29 11:04:18 +000015#include "lldb/Core/StreamString.h"
Robert Flack62efb1f2015-05-27 02:18:50 +000016#include "lldb/Host/FileSpec.h"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000017#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/ADT/STLExtras.h"
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000020#include "llvm/Support/FileUtilities.h"
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000021
22// Project includes
23#include "AdbClient.h"
24
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000025#include <limits.h>
26
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000027#include <algorithm>
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000028#include <fstream>
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000029#include <sstream>
30
31using namespace lldb;
32using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000033using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000034
35namespace {
36
Pavel Labath24076022016-05-03 13:55:53 +000037const uint32_t kReadTimeout = 4000000; // 4 seconds
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000038const char * kOKAY = "OKAY";
39const char * kFAIL = "FAIL";
Oleksiy Vyalov6002a312015-06-05 01:32:45 +000040const char * kDATA = "DATA";
41const char * kDONE = "DONE";
42
43const char * kSEND = "SEND";
44const char * kRECV = "RECV";
45const char * kSTAT = "STAT";
46
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000047const size_t kSyncPacketLen = 8;
Robert Flack62efb1f2015-05-27 02:18:50 +000048// Maximum size of a filesync DATA packet.
49const size_t kMaxPushData = 2*1024;
50// Default mode for pushed files.
51const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000052
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +000053const char * kSocketNamespaceAbstract = "localabstract";
54const char * kSocketNamespaceFileSystem = "localfilesystem";
55
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000056} // namespace
57
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000058Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000059AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000060{
61 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000062 auto error = adb.GetDevices(connect_devices);
63 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000064 return error;
65
Chaoren Lin3ea689b2015-05-01 16:49:28 +000066 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000067 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000068 if (connect_devices.size() != 1)
69 return Error("Expected a single connected device, got instead %" PRIu64,
70 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000071
Chaoren Lin3ea689b2015-05-01 16:49:28 +000072 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000073 }
74 else
75 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000076 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
77 if (find_it == connect_devices.end())
78 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000079
Chaoren Lin3ea689b2015-05-01 16:49:28 +000080 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000081 }
82 return error;
83}
84
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000085AdbClient::AdbClient (const std::string &device_id)
86 : m_device_id (device_id)
87{
88}
89
90void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000091AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000092{
93 m_device_id = device_id;
94}
95
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000096const std::string&
97AdbClient::GetDeviceID() const
98{
99 return m_device_id;
100}
101
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000102Error
103AdbClient::Connect ()
104{
105 Error error;
106 m_conn.Connect ("connect://localhost:5037", &error);
107
108 return error;
109}
110
111Error
112AdbClient::GetDevices (DeviceIDList &device_list)
113{
114 device_list.clear ();
115
116 auto error = SendMessage ("host:devices");
117 if (error.Fail ())
118 return error;
119
120 error = ReadResponseStatus ();
121 if (error.Fail ())
122 return error;
123
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000124 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000125 error = ReadMessage (in_buffer);
126
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000127 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000128 llvm::SmallVector<llvm::StringRef, 4> devices;
129 response.split (devices, "\n", -1, false);
130
131 for (const auto device: devices)
132 device_list.push_back (device.split ('\t').first);
133
134 return error;
135}
136
137Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000138AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000139{
140 char message[48];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000141 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000142
143 const auto error = SendDeviceMessage (message);
144 if (error.Fail ())
145 return error;
146
147 return ReadResponseStatus ();
148}
149
150Error
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000151AdbClient::SetPortForwarding (const uint16_t local_port,
152 const char* remote_socket_name,
153 const UnixSocketNamespace socket_namespace)
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000154{
155 char message[PATH_MAX];
Oleksiy Vyalove7df5f52015-11-03 01:37:01 +0000156 const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ?
157 kSocketNamespaceAbstract : kSocketNamespaceFileSystem;
158 snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s",
159 local_port,
160 sock_namespace_str,
161 remote_socket_name);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000162
163 const auto error = SendDeviceMessage (message);
164 if (error.Fail ())
165 return error;
166
167 return ReadResponseStatus ();
168}
169
170Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000171AdbClient::DeletePortForwarding (const uint16_t local_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000172{
173 char message[32];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000174 snprintf (message, sizeof (message), "killforward:tcp:%d", local_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000175
176 const auto error = SendDeviceMessage (message);
177 if (error.Fail ())
178 return error;
179
180 return ReadResponseStatus ();
181}
182
183Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000184AdbClient::SendMessage (const std::string &packet, const bool reconnect)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000185{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000186 Error error;
187 if (reconnect)
188 {
189 error = Connect ();
190 if (error.Fail ())
191 return error;
192 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000193
194 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000195 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000196
197 ConnectionStatus status;
198
199 m_conn.Write (length_buffer, 4, status, &error);
200 if (error.Fail ())
201 return error;
202
203 m_conn.Write (packet.c_str (), packet.size (), status, &error);
204 return error;
205}
206
207Error
208AdbClient::SendDeviceMessage (const std::string &packet)
209{
210 std::ostringstream msg;
211 msg << "host-serial:" << m_device_id << ":" << packet;
212 return SendMessage (msg.str ());
213}
214
215Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000216AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000217{
218 message.clear ();
219
220 char buffer[5];
221 buffer[4] = 0;
222
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000223 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000224 if (error.Fail ())
225 return error;
226
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000227 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000228 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000229
230 message.resize (packet_len, 0);
231 error = ReadAllBytes (&message[0], packet_len);
232 if (error.Fail ())
233 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000234
235 return error;
236}
237
238Error
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000239AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms)
240{
241 auto start = std::chrono::steady_clock::now();
242 message.clear();
243
244 Error error;
245 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
246 char buffer[1024];
247 while (error.Success() && status == lldb::eConnectionStatusSuccess)
248 {
249 auto end = std::chrono::steady_clock::now();
250 uint32_t elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
251 if (elapsed_time >= timeout_ms)
252 return Error("Timed out");
253
Pavel Labath24076022016-05-03 13:55:53 +0000254 const bool read_full_buffer = true;
255 size_t n =
256 m_conn.Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), read_full_buffer, status, &error);
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000257 if (n > 0)
258 message.insert(message.end(), &buffer[0], &buffer[n]);
259 }
260 return error;
261}
262
263Error
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000264AdbClient::ReadResponseStatus()
265{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000266 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000267
268 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000269 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000270
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000271 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000272 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000273 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000274
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000275 if (strncmp (response_id, kOKAY, packet_len) != 0)
276 return GetResponseError (response_id);
277
278 return error;
279}
280
281Error
282AdbClient::GetResponseError (const char *response_id)
283{
284 if (strcmp (response_id, kFAIL) != 0)
285 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
286
287 std::vector<char> error_message;
288 auto error = ReadMessage (error_message);
289 if (error.Success ())
290 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
291
292 return error;
293}
294
295Error
296AdbClient::SwitchDeviceTransport ()
297{
298 std::ostringstream msg;
299 msg << "host:transport:" << m_device_id;
300
301 auto error = SendMessage (msg.str ());
302 if (error.Fail ())
303 return error;
304
305 return ReadResponseStatus ();
306}
307
308Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000309AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000310{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000311 auto error = StartSync ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000312 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000313 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000314
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000315 const auto local_file_path = local_file.GetPath ();
316 llvm::FileRemover local_file_remover (local_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000317
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000318 std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000319 if (!dst.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000320 return Error ("Unable to open local file %s", local_file_path.c_str());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000321
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000322 const auto remote_file_path = remote_file.GetPath (false);
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000323 error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000324 if (error.Fail ())
325 return error;
326
327 std::vector<char> chunk;
328 bool eof = false;
329 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000330 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000331 error = PullFileChunk (chunk, eof);
332 if (error.Fail ())
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000333 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000334 if (!eof)
335 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000336 }
337
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000338 local_file_remover.releaseFile ();
339 return error;
340}
341
342Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000343AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
Robert Flack62efb1f2015-05-27 02:18:50 +0000344{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000345 auto error = StartSync ();
Robert Flack62efb1f2015-05-27 02:18:50 +0000346 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000347 return error;
Robert Flack62efb1f2015-05-27 02:18:50 +0000348
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000349 const auto local_file_path (local_file.GetPath ());
350 std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
Robert Flack62efb1f2015-05-27 02:18:50 +0000351 if (!src.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000352 return Error ("Unable to open local file %s", local_file_path.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000353
354 std::stringstream file_description;
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000355 file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
Robert Flack62efb1f2015-05-27 02:18:50 +0000356 std::string file_description_str = file_description.str();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000357 error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000358 if (error.Fail ())
359 return error;
360
361 char chunk[kMaxPushData];
362 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
363 {
364 size_t chunk_size = src.gcount();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000365 error = SendSyncRequest(kDATA, chunk_size, chunk);
Robert Flack62efb1f2015-05-27 02:18:50 +0000366 if (error.Fail ())
367 return Error ("Failed to send file chunk: %s", error.AsCString ());
368 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000369 error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
Robert Flack62efb1f2015-05-27 02:18:50 +0000370 if (error.Fail ())
371 return error;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000372
373 std::string response_id;
Jason Molendad10f6aa2015-10-28 23:31:03 +0000374 uint32_t data_len;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000375 error = ReadSyncHeader (response_id, data_len);
376 if (error.Fail ())
377 return Error ("Failed to read DONE response: %s", error.AsCString ());
378 if (response_id == kFAIL)
379 {
380 std::string error_message (data_len, 0);
381 error = ReadAllBytes (&error_message[0], data_len);
382 if (error.Fail ())
383 return Error ("Failed to read DONE error message: %s", error.AsCString ());
384 return Error ("Failed to push file: %s", error_message.c_str ());
385 }
386 else if (response_id != kOKAY)
387 return Error ("Got unexpected DONE response: %s", response_id.c_str ());
388
Robert Flack62efb1f2015-05-27 02:18:50 +0000389 // If there was an error reading the source file, finish the adb file
390 // transfer first so that adb isn't expecting any more data.
391 if (src.bad())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000392 return Error ("Failed read on %s", local_file_path.c_str());
393 return error;
394}
395
396Error
397AdbClient::StartSync ()
398{
399 auto error = SwitchDeviceTransport ();
400 if (error.Fail ())
401 return Error ("Failed to switch to device transport: %s", error.AsCString ());
402
403 error = Sync ();
404 if (error.Fail ())
405 return Error ("Sync failed: %s", error.AsCString ());
406
Robert Flack62efb1f2015-05-27 02:18:50 +0000407 return error;
408}
409
410Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000411AdbClient::Sync ()
412{
413 auto error = SendMessage ("sync:", false);
414 if (error.Fail ())
415 return error;
416
417 return ReadResponseStatus ();
418}
419
420Error
421AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
422{
423 buffer.clear ();
424
425 std::string response_id;
426 uint32_t data_len;
427 auto error = ReadSyncHeader (response_id, data_len);
428 if (error.Fail ())
429 return error;
430
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000431 if (response_id == kDATA)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000432 {
433 buffer.resize (data_len, 0);
434 error = ReadAllBytes (&buffer[0], data_len);
435 if (error.Fail ())
436 buffer.clear ();
437 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000438 else if (response_id == kDONE)
439 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000440 eof = true;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000441 }
442 else if (response_id == kFAIL)
443 {
444 std::string error_message (data_len, 0);
445 error = ReadAllBytes (&error_message[0], data_len);
446 if (error.Fail ())
447 return Error ("Failed to read pull error message: %s", error.AsCString ());
448 return Error ("Failed to pull file: %s", error_message.c_str ());
449 }
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000450 else
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000451 return Error ("Pull failed with unknown response: %s", response_id.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000452
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000453 return Error ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000454}
455
456Error
457AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
458{
459 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
460 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
461 auto offset = encoder.PutData (0, request_id, strlen(request_id));
462 encoder.PutU32 (offset, data_len);
463
464 Error error;
465 ConnectionStatus status;
466 m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
467 if (error.Fail ())
468 return error;
469
Robert Flack62efb1f2015-05-27 02:18:50 +0000470 if (data)
471 m_conn.Write (data, data_len, status, &error);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000472 return error;
473}
474
475Error
476AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
477{
478 char buffer[kSyncPacketLen];
479
480 auto error = ReadAllBytes (buffer, kSyncPacketLen);
481 if (error.Success ())
482 {
483 response_id.assign (&buffer[0], 4);
484 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
485 offset_t offset = 0;
486 data_len = extractor.GetU32 (&offset);
487 }
488
489 return error;
490}
491
492Error
493AdbClient::ReadAllBytes (void *buffer, size_t size)
494{
Pavel Labath24076022016-05-03 13:55:53 +0000495 const bool read_full_buffer = true;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000496 Error error;
497 ConnectionStatus status;
Pavel Labath24076022016-05-03 13:55:53 +0000498 size_t read_bytes = m_conn.Read(buffer, size, kReadTimeout, read_full_buffer, status, &error);
499 if (error.Fail())
500 return error;
501 if (read_bytes < size)
502 return Error("Unable to read full buffer.");
503 return Error();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000504}
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000505
506Error
507AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
508{
509 auto error = StartSync ();
510 if (error.Fail ())
511 return error;
512
513 const std::string remote_file_path (remote_file.GetPath (false));
514 error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
515 if (error.Fail ())
516 return Error ("Failed to send request: %s", error.AsCString ());
517
518 static const size_t stat_len = strlen (kSTAT);
519 static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
520
521 std::vector<char> buffer (response_len);
522 error = ReadAllBytes (&buffer[0], buffer.size ());
523 if (error.Fail ())
524 return Error ("Failed to read response: %s", error.AsCString ());
525
526 DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
527 offset_t offset = 0;
528
529 const void* command = extractor.GetData (&offset, stat_len);
530 if (!command)
531 return Error ("Failed to get response command");
532 const char* command_str = static_cast<const char*> (command);
533 if (strncmp (command_str, kSTAT, stat_len))
534 return Error ("Got invalid stat command: %s", command_str);
535
536 mode = extractor.GetU32 (&offset);
537 size = extractor.GetU32 (&offset);
538 mtime = extractor.GetU32 (&offset);
539 return Error ();
540}
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000541
542Error
543AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
544{
545 auto error = SwitchDeviceTransport ();
546 if (error.Fail ())
547 return Error ("Failed to switch to device transport: %s", error.AsCString ());
548
549 StreamString adb_command;
550 adb_command.Printf("shell:%s", command);
551 error = SendMessage (adb_command.GetData(), false);
552 if (error.Fail ())
553 return error;
554
555 error = ReadResponseStatus ();
556 if (error.Fail ())
557 return error;
558
559 std::vector<char> in_buffer;
560 error = ReadMessageStream (in_buffer, timeout_ms);
561 if (error.Fail())
562 return error;
563
564 if (output)
565 output->assign(in_buffer.begin(), in_buffer.end());
566 return error;
567}