ovyalov updated this revision to Diff 63173.
ovyalov added a comment.
Addressed review comments:
- Check whether shell command output starts with /system/bin/sh: in order to
find out whether command failed
- Fail-fast download if filename contains single-quotes
- clang-format
http://reviews.llvm.org/D22081
Files:
source/Plugins/Platform/Android/AdbClient.cpp
source/Plugins/Platform/Android/AdbClient.h
source/Plugins/Platform/Android/PlatformAndroid.cpp
Index: source/Plugins/Platform/Android/PlatformAndroid.cpp
===================================================================
--- source/Plugins/Platform/Android/PlatformAndroid.cpp
+++ source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -230,7 +230,30 @@
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
Index: source/Plugins/Platform/Android/AdbClient.h
===================================================================
--- source/Plugins/Platform/Android/AdbClient.h
+++ source/Plugins/Platform/Android/AdbClient.h
@@ -119,6 +119,9 @@
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);
@@ -156,8 +159,10 @@
Error
StartSync ();
- Error
- ReadAllBytes (void *buffer, size_t size);
+ Error 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;
Index: source/Plugins/Platform/Android/AdbClient.cpp
===================================================================
--- source/Plugins/Platform/Android/AdbClient.cpp
+++ source/Plugins/Platform/Android/AdbClient.cpp
@@ -383,31 +383,62 @@
return ::ReadAllBytes (*m_conn, buffer, size);
}
-Error
-AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
-{
- 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 ())
- return error;
-
- error = ReadResponseStatus ();
- if (error.Fail ())
- return error;
-
- std::vector<char> in_buffer;
- error = ReadMessageStream (in_buffer, timeout_ms);
- if (error.Fail())
- return error;
-
- if (output)
- output->assign(in_buffer.begin(), in_buffer.end());
- return error;
+Error AdbClient::internalShell(const char *command, uint32_t timeout_ms,
+ std::vector<char> &output_buf) {
+ 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()) return error;
+
+ error = ReadResponseStatus();
+ if (error.Fail()) return error;
+
+ 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(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>
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits