mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 19:08:21 +08:00
Use shell cat command as a workaround if ADB stat cannot lookup a file.
http://reviews.llvm.org/D22081 llvm-svn: 274895
This commit is contained in:
@@ -25,8 +25,8 @@
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
@@ -384,32 +384,74 @@ AdbClient::ReadAllBytes (void *buffer, size_t size)
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
|
||||
AdbClient::internalShell(const char *command, uint32_t timeout_ms, std::vector<char> &output_buf)
|
||||
{
|
||||
auto error = SwitchDeviceTransport ();
|
||||
if (error.Fail ())
|
||||
return Error ("Failed to switch to device transport: %s", error.AsCString ());
|
||||
output_buf.clear();
|
||||
|
||||
auto error = SwitchDeviceTransport();
|
||||
if (error.Fail())
|
||||
return Error("Failed to switch to device transport: %s", error.AsCString());
|
||||
|
||||
StreamString adb_command;
|
||||
adb_command.Printf("shell:%s", command);
|
||||
error = SendMessage (adb_command.GetData(), false);
|
||||
if (error.Fail ())
|
||||
error = SendMessage(adb_command.GetData(), false);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
error = ReadResponseStatus ();
|
||||
if (error.Fail ())
|
||||
error = ReadResponseStatus();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
std::vector<char> in_buffer;
|
||||
error = ReadMessageStream (in_buffer, timeout_ms);
|
||||
error = ReadMessageStream(output_buf, timeout_ms);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
// ADB doesn't propagate return code of shell execution - if
|
||||
// output starts with /system/bin/sh: most likely command failed.
|
||||
static const char *kShellPrefix = "/system/bin/sh:";
|
||||
if (output_buf.size() > strlen(kShellPrefix))
|
||||
{
|
||||
if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix)))
|
||||
return Error("Shell command %s failed: %s", command,
|
||||
std::string(output_buf.begin(), output_buf.end()).c_str());
|
||||
}
|
||||
|
||||
return Error();
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::Shell(const char *command, uint32_t timeout_ms, std::string *output)
|
||||
{
|
||||
std::vector<char> output_buffer;
|
||||
auto error = internalShell(command, timeout_ms, output_buffer);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
if (output)
|
||||
output->assign(in_buffer.begin(), in_buffer.end());
|
||||
output->assign(output_buffer.begin(), output_buffer.end());
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::ShellToFile(const char *command, uint32_t timeout_ms, const FileSpec &output_file_spec)
|
||||
{
|
||||
std::vector<char> output_buffer;
|
||||
auto error = internalShell(command, timeout_ms, output_buffer);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
const auto output_filename = output_file_spec.GetPath();
|
||||
std::ofstream dst(output_filename, std::ios::out | std::ios::binary);
|
||||
if (!dst.is_open())
|
||||
return Error("Unable to open local file %s", output_filename.c_str());
|
||||
|
||||
dst.write(&output_buffer[0], output_buffer.size());
|
||||
dst.close();
|
||||
if (!dst)
|
||||
return Error("Failed to write file %s", output_filename.c_str());
|
||||
return Error();
|
||||
}
|
||||
|
||||
std::unique_ptr<AdbClient::SyncService>
|
||||
AdbClient::GetSyncService (Error &error)
|
||||
{
|
||||
|
||||
@@ -119,6 +119,9 @@ public:
|
||||
Error
|
||||
Shell (const char* command, uint32_t timeout_ms, std::string* output);
|
||||
|
||||
Error
|
||||
ShellToFile(const char *command, uint32_t timeout_ms, const FileSpec &output_file_spec);
|
||||
|
||||
std::unique_ptr<SyncService>
|
||||
GetSyncService (Error &error);
|
||||
|
||||
@@ -157,7 +160,10 @@ private:
|
||||
StartSync ();
|
||||
|
||||
Error
|
||||
ReadAllBytes (void *buffer, size_t size);
|
||||
internalShell(const char *command, uint32_t timeout_ms, std::vector<char> &output_buf);
|
||||
|
||||
Error
|
||||
ReadAllBytes(void *buffer, size_t size);
|
||||
|
||||
std::string m_device_id;
|
||||
std::unique_ptr<Connection> m_conn;
|
||||
|
||||
@@ -230,7 +230,31 @@ PlatformAndroid::GetFile (const FileSpec& source,
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
return sync_service->PullFile (source_spec, destination);
|
||||
uint32_t mode = 0, size = 0, mtime = 0;
|
||||
error = sync_service->Stat(source_spec, mode, size, mtime);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
if (mode != 0)
|
||||
return sync_service->PullFile(source_spec, destination);
|
||||
|
||||
auto source_file = source_spec.GetCString(false);
|
||||
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
|
||||
if (log)
|
||||
log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", source_file);
|
||||
|
||||
if (strchr(source_file, '\'') != nullptr)
|
||||
return Error("Doesn't support single-quotes in filenames");
|
||||
|
||||
// mode == 0 can signify that adbd cannot access the file
|
||||
// due security constraints - try "cat ..." as a fallback.
|
||||
AdbClient adb(m_device_id);
|
||||
|
||||
char cmd[PATH_MAX];
|
||||
snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);
|
||||
|
||||
return adb.ShellToFile(cmd, 60000 /* ms */, destination);
|
||||
}
|
||||
|
||||
Error
|
||||
|
||||
Reference in New Issue
Block a user