1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
#include "bash_command.h"
#include "profiler_file.h"
#include "sys/wait.h"
#include "utils/log.h"
using std::string;
using profiler::Log;
namespace {
const char *const kRunAsExecutable = "/system/bin/run-as";
}
namespace profiler {
BashCommandRunner::BashCommandRunner(const string &executable_path)
: executable_path_(executable_path) {}
bool BashCommandRunner::RunAs(const string ¶meters,
const string &package_name,
string *output) const {
string cmd;
cmd.append(kRunAsExecutable);
cmd.append(" ");
cmd.append(package_name);
// TODO: The single quote can interfer with parameters. Disregarding
// this potential issue for now.
cmd.append(" sh -c '");
cmd.append(executable_path_);
cmd.append(" ");
cmd.append(parameters);
cmd.append("'");
return RunAndReadOutput(cmd, output);
}
bool BashCommandRunner::Run(const string ¶meters, string *output) const {
string cmd;
cmd.append(executable_path_);
cmd.append(" ");
cmd.append(parameters);
return RunAndReadOutput(cmd, output);
}
bool BashCommandRunner::RunAndReadOutput(const string &cmd,
string *output) const {
Log::I("Running '%s'.\n", cmd.c_str());
char buffer[1024];
FILE *pipe = popen(cmd.c_str(), "r");
while (!feof(pipe)) {
if (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
output->append(buffer);
}
}
int ret = pclose(pipe);
return WEXITSTATUS(ret) == 0;
}
bool BashCommandRunner::IsRunAsCapable() {
ProfilerFile run_as = ProfilerFile(kRunAsExecutable);
// Checking for run-as existance is not enough: We also need to
// check capabilities.
// TODO: Use listxattr (as in
// https://groups.google.com/forum/#!topic/android-kernel/iYakEvY24n4)
// to makes sure run-as has CAP_SETUID and CAP_SETGID capability.
// See bug report: https://code.google.com/p/android/issues/detail?id=187955
return run_as.Exists();
}
}
|