blob: f57e8c3faf2b575ae8bb48349ec947ca130d0246 [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
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000037const uint32_t kReadTimeout = 1000000; // 1 second
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
53} // namespace
54
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000055Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000056AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000057{
58 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000059 auto error = adb.GetDevices(connect_devices);
60 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000061 return error;
62
Chaoren Lin3ea689b2015-05-01 16:49:28 +000063 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000064 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000065 if (connect_devices.size() != 1)
66 return Error("Expected a single connected device, got instead %" PRIu64,
67 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000068
Chaoren Lin3ea689b2015-05-01 16:49:28 +000069 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000070 }
71 else
72 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000073 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
74 if (find_it == connect_devices.end())
75 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000076
Chaoren Lin3ea689b2015-05-01 16:49:28 +000077 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000078 }
79 return error;
80}
81
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000082AdbClient::AdbClient (const std::string &device_id)
83 : m_device_id (device_id)
84{
85}
86
87void
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +000088AdbClient::SetDeviceID (const std::string &device_id)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000089{
90 m_device_id = device_id;
91}
92
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000093const std::string&
94AdbClient::GetDeviceID() const
95{
96 return m_device_id;
97}
98
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000099Error
100AdbClient::Connect ()
101{
102 Error error;
103 m_conn.Connect ("connect://localhost:5037", &error);
104
105 return error;
106}
107
108Error
109AdbClient::GetDevices (DeviceIDList &device_list)
110{
111 device_list.clear ();
112
113 auto error = SendMessage ("host:devices");
114 if (error.Fail ())
115 return error;
116
117 error = ReadResponseStatus ();
118 if (error.Fail ())
119 return error;
120
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000121 std::vector<char> in_buffer;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000122 error = ReadMessage (in_buffer);
123
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000124 llvm::StringRef response (&in_buffer[0], in_buffer.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000125 llvm::SmallVector<llvm::StringRef, 4> devices;
126 response.split (devices, "\n", -1, false);
127
128 for (const auto device: devices)
129 device_list.push_back (device.split ('\t').first);
130
131 return error;
132}
133
134Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000135AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000136{
137 char message[48];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000138 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000139
140 const auto error = SendDeviceMessage (message);
141 if (error.Fail ())
142 return error;
143
144 return ReadResponseStatus ();
145}
146
147Error
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000148AdbClient::SetPortForwarding (const uint16_t local_port, const char* remote_socket_name)
149{
150 char message[PATH_MAX];
151 snprintf (message, sizeof (message), "forward:tcp:%d;localfilesystem:%s", local_port, remote_socket_name);
152
153 const auto error = SendDeviceMessage (message);
154 if (error.Fail ())
155 return error;
156
157 return ReadResponseStatus ();
158}
159
160Error
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000161AdbClient::DeletePortForwarding (const uint16_t local_port)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000162{
163 char message[32];
Oleksiy Vyalove7eabbb2015-09-01 19:02:14 +0000164 snprintf (message, sizeof (message), "killforward:tcp:%d", local_port);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000165
166 const auto error = SendDeviceMessage (message);
167 if (error.Fail ())
168 return error;
169
170 return ReadResponseStatus ();
171}
172
173Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000174AdbClient::SendMessage (const std::string &packet, const bool reconnect)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000175{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000176 Error error;
177 if (reconnect)
178 {
179 error = Connect ();
180 if (error.Fail ())
181 return error;
182 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000183
184 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000185 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000186
187 ConnectionStatus status;
188
189 m_conn.Write (length_buffer, 4, status, &error);
190 if (error.Fail ())
191 return error;
192
193 m_conn.Write (packet.c_str (), packet.size (), status, &error);
194 return error;
195}
196
197Error
198AdbClient::SendDeviceMessage (const std::string &packet)
199{
200 std::ostringstream msg;
201 msg << "host-serial:" << m_device_id << ":" << packet;
202 return SendMessage (msg.str ());
203}
204
205Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000206AdbClient::ReadMessage (std::vector<char> &message)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000207{
208 message.clear ();
209
210 char buffer[5];
211 buffer[4] = 0;
212
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000213 auto error = ReadAllBytes (buffer, 4);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000214 if (error.Fail ())
215 return error;
216
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000217 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000218 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000219
220 message.resize (packet_len, 0);
221 error = ReadAllBytes (&message[0], packet_len);
222 if (error.Fail ())
223 message.clear ();
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000224
225 return error;
226}
227
228Error
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000229AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms)
230{
231 auto start = std::chrono::steady_clock::now();
232 message.clear();
233
234 Error error;
235 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
236 char buffer[1024];
237 while (error.Success() && status == lldb::eConnectionStatusSuccess)
238 {
239 auto end = std::chrono::steady_clock::now();
240 uint32_t elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
241 if (elapsed_time >= timeout_ms)
242 return Error("Timed out");
243
244 size_t n = m_conn.Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error);
245 if (n > 0)
246 message.insert(message.end(), &buffer[0], &buffer[n]);
247 }
248 return error;
249}
250
251Error
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000252AdbClient::ReadResponseStatus()
253{
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000254 char response_id[5];
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000255
256 static const size_t packet_len = 4;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000257 response_id[packet_len] = 0;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000258
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000259 auto error = ReadAllBytes (response_id, packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000260 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000261 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000262
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000263 if (strncmp (response_id, kOKAY, packet_len) != 0)
264 return GetResponseError (response_id);
265
266 return error;
267}
268
269Error
270AdbClient::GetResponseError (const char *response_id)
271{
272 if (strcmp (response_id, kFAIL) != 0)
273 return Error ("Got unexpected response id from adb: \"%s\"", response_id);
274
275 std::vector<char> error_message;
276 auto error = ReadMessage (error_message);
277 if (error.Success ())
278 error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
279
280 return error;
281}
282
283Error
284AdbClient::SwitchDeviceTransport ()
285{
286 std::ostringstream msg;
287 msg << "host:transport:" << m_device_id;
288
289 auto error = SendMessage (msg.str ());
290 if (error.Fail ())
291 return error;
292
293 return ReadResponseStatus ();
294}
295
296Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000297AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000298{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000299 auto error = StartSync ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000300 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000301 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000302
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000303 const auto local_file_path = local_file.GetPath ();
304 llvm::FileRemover local_file_remover (local_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000305
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000306 std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000307 if (!dst.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000308 return Error ("Unable to open local file %s", local_file_path.c_str());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000309
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000310 const auto remote_file_path = remote_file.GetPath (false);
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000311 error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000312 if (error.Fail ())
313 return error;
314
315 std::vector<char> chunk;
316 bool eof = false;
317 while (!eof)
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000318 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000319 error = PullFileChunk (chunk, eof);
320 if (error.Fail ())
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000321 return error;
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000322 if (!eof)
323 dst.write (&chunk[0], chunk.size ());
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000324 }
325
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000326 local_file_remover.releaseFile ();
327 return error;
328}
329
330Error
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000331AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
Robert Flack62efb1f2015-05-27 02:18:50 +0000332{
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000333 auto error = StartSync ();
Robert Flack62efb1f2015-05-27 02:18:50 +0000334 if (error.Fail ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000335 return error;
Robert Flack62efb1f2015-05-27 02:18:50 +0000336
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000337 const auto local_file_path (local_file.GetPath ());
338 std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
Robert Flack62efb1f2015-05-27 02:18:50 +0000339 if (!src.is_open ())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000340 return Error ("Unable to open local file %s", local_file_path.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000341
342 std::stringstream file_description;
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000343 file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
Robert Flack62efb1f2015-05-27 02:18:50 +0000344 std::string file_description_str = file_description.str();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000345 error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
Robert Flack62efb1f2015-05-27 02:18:50 +0000346 if (error.Fail ())
347 return error;
348
349 char chunk[kMaxPushData];
350 while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
351 {
352 size_t chunk_size = src.gcount();
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000353 error = SendSyncRequest(kDATA, chunk_size, chunk);
Robert Flack62efb1f2015-05-27 02:18:50 +0000354 if (error.Fail ())
355 return Error ("Failed to send file chunk: %s", error.AsCString ());
356 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000357 error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
Robert Flack62efb1f2015-05-27 02:18:50 +0000358 if (error.Fail ())
359 return error;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000360
361 std::string response_id;
Jason Molendad10f6aa2015-10-28 23:31:03 +0000362 uint32_t data_len;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000363 error = ReadSyncHeader (response_id, data_len);
364 if (error.Fail ())
365 return Error ("Failed to read DONE response: %s", error.AsCString ());
366 if (response_id == kFAIL)
367 {
368 std::string error_message (data_len, 0);
369 error = ReadAllBytes (&error_message[0], data_len);
370 if (error.Fail ())
371 return Error ("Failed to read DONE error message: %s", error.AsCString ());
372 return Error ("Failed to push file: %s", error_message.c_str ());
373 }
374 else if (response_id != kOKAY)
375 return Error ("Got unexpected DONE response: %s", response_id.c_str ());
376
Robert Flack62efb1f2015-05-27 02:18:50 +0000377 // If there was an error reading the source file, finish the adb file
378 // transfer first so that adb isn't expecting any more data.
379 if (src.bad())
Oleksiy Vyalov0b5ebef2015-05-28 17:42:48 +0000380 return Error ("Failed read on %s", local_file_path.c_str());
381 return error;
382}
383
384Error
385AdbClient::StartSync ()
386{
387 auto error = SwitchDeviceTransport ();
388 if (error.Fail ())
389 return Error ("Failed to switch to device transport: %s", error.AsCString ());
390
391 error = Sync ();
392 if (error.Fail ())
393 return Error ("Sync failed: %s", error.AsCString ());
394
Robert Flack62efb1f2015-05-27 02:18:50 +0000395 return error;
396}
397
398Error
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000399AdbClient::Sync ()
400{
401 auto error = SendMessage ("sync:", false);
402 if (error.Fail ())
403 return error;
404
405 return ReadResponseStatus ();
406}
407
408Error
409AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
410{
411 buffer.clear ();
412
413 std::string response_id;
414 uint32_t data_len;
415 auto error = ReadSyncHeader (response_id, data_len);
416 if (error.Fail ())
417 return error;
418
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000419 if (response_id == kDATA)
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000420 {
421 buffer.resize (data_len, 0);
422 error = ReadAllBytes (&buffer[0], data_len);
423 if (error.Fail ())
424 buffer.clear ();
425 }
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000426 else if (response_id == kDONE)
427 {
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000428 eof = true;
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000429 }
430 else if (response_id == kFAIL)
431 {
432 std::string error_message (data_len, 0);
433 error = ReadAllBytes (&error_message[0], data_len);
434 if (error.Fail ())
435 return Error ("Failed to read pull error message: %s", error.AsCString ());
436 return Error ("Failed to pull file: %s", error_message.c_str ());
437 }
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000438 else
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000439 return Error ("Pull failed with unknown response: %s", response_id.c_str ());
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000440
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000441 return Error ();
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000442}
443
444Error
445AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
446{
447 const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
448 DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
449 auto offset = encoder.PutData (0, request_id, strlen(request_id));
450 encoder.PutU32 (offset, data_len);
451
452 Error error;
453 ConnectionStatus status;
454 m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
455 if (error.Fail ())
456 return error;
457
Robert Flack62efb1f2015-05-27 02:18:50 +0000458 if (data)
459 m_conn.Write (data, data_len, status, &error);
Oleksiy Vyalov09e9079d2015-05-18 23:44:06 +0000460 return error;
461}
462
463Error
464AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
465{
466 char buffer[kSyncPacketLen];
467
468 auto error = ReadAllBytes (buffer, kSyncPacketLen);
469 if (error.Success ())
470 {
471 response_id.assign (&buffer[0], 4);
472 DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
473 offset_t offset = 0;
474 data_len = extractor.GetU32 (&offset);
475 }
476
477 return error;
478}
479
480Error
481AdbClient::ReadAllBytes (void *buffer, size_t size)
482{
483 Error error;
484 ConnectionStatus status;
485 char *read_buffer = static_cast<char*>(buffer);
486
487 size_t tota_read_bytes = 0;
488 while (tota_read_bytes < size)
489 {
490 auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error);
491 if (error.Fail ())
492 return error;
493 tota_read_bytes += read_bytes;
494 }
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000495 return error;
496}
Oleksiy Vyalov6002a312015-06-05 01:32:45 +0000497
498Error
499AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
500{
501 auto error = StartSync ();
502 if (error.Fail ())
503 return error;
504
505 const std::string remote_file_path (remote_file.GetPath (false));
506 error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
507 if (error.Fail ())
508 return Error ("Failed to send request: %s", error.AsCString ());
509
510 static const size_t stat_len = strlen (kSTAT);
511 static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
512
513 std::vector<char> buffer (response_len);
514 error = ReadAllBytes (&buffer[0], buffer.size ());
515 if (error.Fail ())
516 return Error ("Failed to read response: %s", error.AsCString ());
517
518 DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
519 offset_t offset = 0;
520
521 const void* command = extractor.GetData (&offset, stat_len);
522 if (!command)
523 return Error ("Failed to get response command");
524 const char* command_str = static_cast<const char*> (command);
525 if (strncmp (command_str, kSTAT, stat_len))
526 return Error ("Got invalid stat command: %s", command_str);
527
528 mode = extractor.GetU32 (&offset);
529 size = extractor.GetU32 (&offset);
530 mtime = extractor.GetU32 (&offset);
531 return Error ();
532}
Tamas Berghammer9d8dde82015-09-29 11:04:18 +0000533
534Error
535AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
536{
537 auto error = SwitchDeviceTransport ();
538 if (error.Fail ())
539 return Error ("Failed to switch to device transport: %s", error.AsCString ());
540
541 StreamString adb_command;
542 adb_command.Printf("shell:%s", command);
543 error = SendMessage (adb_command.GetData(), false);
544 if (error.Fail ())
545 return error;
546
547 error = ReadResponseStatus ();
548 if (error.Fail ())
549 return error;
550
551 std::vector<char> in_buffer;
552 error = ReadMessageStream (in_buffer, timeout_ms);
553 if (error.Fail())
554 return error;
555
556 if (output)
557 output->assign(in_buffer.begin(), in_buffer.end());
558 return error;
559}