AU: Add support for reading the output of synchronous exec calls.
This will be used in a subsequent patch to invoke 'crossystem hwid' to read the
HWID.
BUG=chromium-os:15255
TEST=unit tests, tested AU on device
Change-Id: Ie26bae3621626d40f92f08e8549eefda77151102
Reviewed-on: http://gerrit.chromium.org/gerrit/1047
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/delta_diff_generator.cc b/delta_diff_generator.cc
index a500054..f00ac7f 100644
--- a/delta_diff_generator.cc
+++ b/delta_diff_generator.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -1553,7 +1553,7 @@
int rc = 1;
vector<char> patch_file;
- TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc));
+ TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc, NULL));
TEST_AND_RETURN_FALSE(rc == 0);
TEST_AND_RETURN_FALSE(utils::ReadFile(patch_file_path, out));
unlink(patch_file_path.c_str());
diff --git a/delta_performer.cc b/delta_performer.cc
index 9978faf..6466795 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -517,8 +517,9 @@
int return_code = 0;
TEST_AND_RETURN_FALSE(
Subprocess::SynchronousExecFlags(cmd,
+ G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
&return_code,
- G_SPAWN_LEAVE_DESCRIPTORS_OPEN));
+ NULL));
TEST_AND_RETURN_FALSE(return_code == 0);
if (operation.dst_length() % block_size_) {
diff --git a/download_action.cc b/download_action.cc
index 933cbdd..1491caa 100644
--- a/download_action.cc
+++ b/download_action.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -140,7 +140,7 @@
command.push_back("/bin/sync");
int rc;
LOG(INFO) << "FlushLinuxCaches-sync...";
- Subprocess::SynchronousExec(command, &rc);
+ Subprocess::SynchronousExec(command, &rc, NULL);
LOG(INFO) << "FlushLinuxCaches-drop_caches...";
const char* const drop_cmd = "3\n";
diff --git a/payload_signer.cc b/payload_signer.cc
index f613f36..c27e3bc 100644
--- a/payload_signer.cc
+++ b/payload_signer.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -155,7 +155,7 @@
cmd[cmd.size() - 1] = sig_path;
int return_code = 0;
- TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &return_code));
+ TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &return_code, NULL));
TEST_AND_RETURN_FALSE(return_code == 0);
vector<char> signature;
diff --git a/subprocess.cc b/subprocess.cc
index 34f5994..a638145 100644
--- a/subprocess.cc
+++ b/subprocess.cc
@@ -117,7 +117,7 @@
};
} // namespace {}
-uint32_t Subprocess::Exec(const std::vector<std::string>& cmd,
+uint32_t Subprocess::Exec(const vector<string>& cmd,
ExecCallback callback,
void* p) {
GPid child_pid;
@@ -181,9 +181,13 @@
subprocess_records_[tag]->callback = NULL;
}
-bool Subprocess::SynchronousExecFlags(const std::vector<std::string>& cmd,
+bool Subprocess::SynchronousExecFlags(const vector<string>& cmd,
+ GSpawnFlags flags,
int* return_code,
- GSpawnFlags flags) {
+ string* stdout) {
+ if (stdout) {
+ *stdout = "";
+ }
GError* err = NULL;
scoped_array<char*> argv(new char*[cmd.size() + 1]);
for (unsigned int i = 0; i < cmd.size(); i++) {
@@ -221,7 +225,9 @@
g_error_free(err);
}
if (child_stdout) {
- if (strlen(child_stdout)) {
+ if (stdout) {
+ *stdout = child_stdout;
+ } else if (*child_stdout) {
LOG(INFO) << "Subprocess output:\n" << child_stdout;
}
g_free(child_stdout);
@@ -229,6 +235,15 @@
return success;
}
+bool Subprocess::SynchronousExec(const std::vector<std::string>& cmd,
+ int* return_code,
+ std::string* stdout) {
+ return SynchronousExecFlags(cmd,
+ static_cast<GSpawnFlags>(0),
+ return_code,
+ stdout);
+}
+
bool Subprocess::SubprocessInFlight() {
for (std::map<int, shared_ptr<SubprocessRecord> >::iterator it =
subprocess_records_.begin();
diff --git a/subprocess.h b/subprocess.h
index 3492e79..c55b090 100644
--- a/subprocess.h
+++ b/subprocess.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -41,14 +41,16 @@
// Used to cancel the callback. The process will still run to completion.
void CancelExec(uint32_t tag);
- // Executes a command synchronously. Returns true on success.
+ // Executes a command synchronously. Returns true on success. If |stdout| is
+ // non-null, the process output is stored in it, otherwise the output is
+ // logged. Note that stderr is redirected to stdout.
static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
+ GSpawnFlags flags,
int* return_code,
- GSpawnFlags flags);
+ std::string* stdout);
static bool SynchronousExec(const std::vector<std::string>& cmd,
- int* return_code) {
- return SynchronousExecFlags(cmd, return_code, static_cast<GSpawnFlags>(0));
- }
+ int* return_code,
+ std::string* stdout);
// Gets the one instance
static Subprocess& Get() {
diff --git a/subprocess_unittest.cc b/subprocess_unittest.cc
index 37deba9..6c0dcb2 100644
--- a/subprocess_unittest.cc
+++ b/subprocess_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -72,6 +72,28 @@
g_main_loop_unref(loop);
}
+TEST(SubprocessTest, SynchronousEchoTest) {
+ vector<string> cmd;
+ cmd.push_back("/bin/sh");
+ cmd.push_back("-c");
+ cmd.push_back("echo -n stdout-here; echo -n stderr-there > /dev/stderr");
+ int rc = -1;
+ string stdout;
+ ASSERT_TRUE(Subprocess::SynchronousExec(cmd, &rc, &stdout));
+ EXPECT_EQ(0, rc);
+ EXPECT_EQ("stdout-herestderr-there", stdout);
+}
+
+TEST(SubprocessTest, SynchronousEchoNoOutputTest) {
+ vector<string> cmd;
+ cmd.push_back("/bin/sh");
+ cmd.push_back("-c");
+ cmd.push_back("echo test");
+ int rc = -1;
+ ASSERT_TRUE(Subprocess::SynchronousExec(cmd, &rc, NULL));
+ EXPECT_EQ(0, rc);
+}
+
namespace {
void CallbackBad(int return_code, const string& output, void *p) {
CHECK(false) << "should never be called.";
diff --git a/test_utils.h b/test_utils.h
index 2283e6a..b5ac853 100644
--- a/test_utils.h
+++ b/test_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -121,7 +121,7 @@
args.push_back("-d");
args.push_back(dev_);
int return_code = 0;
- EXPECT_TRUE(Subprocess::SynchronousExec(args, &return_code));
+ EXPECT_TRUE(Subprocess::SynchronousExec(args, &return_code, NULL));
if (return_code == 0) {
return;
}
diff --git a/utils.cc b/utils.cc
index e1256a7..9c05a25 100644
--- a/utils.cc
+++ b/utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -60,7 +60,7 @@
// Assume dev mode if the dev switch is set to 1 and there was no error
// executing crossystem. Assume normal mode otherwise.
- bool success = Subprocess::SynchronousExec(cmd, &exit_code);
+ bool success = Subprocess::SynchronousExec(cmd, &exit_code, NULL);
bool dev_mode = success && exit_code == 0;
LOG_IF(INFO, dev_mode) << "Booted in dev mode.";
return !dev_mode;
@@ -513,7 +513,7 @@
command.push_back("-r");
command.push_back("now");
int rc = 0;
- Subprocess::SynchronousExec(command, &rc);
+ Subprocess::SynchronousExec(command, &rc, NULL);
TEST_AND_RETURN_FALSE(rc == 0);
return true;
}