aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Barber <smbarber@chromium.org>2017-09-19 11:22:24 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-09-22 17:55:28 -0700
commit84b910fe90e91ef14e6ddec7c7f0a869e1ae5ec6 (patch)
treeeb2c4c8b72b2f2472d3edf6eddec5d53a16ff46a
parent35dcdc75d8e20ebe9ab68b8b8eafe6fb11817d69 (diff)
downloadplatform_external_libbrillo-84b910fe90e91ef14e6ddec7c7f0a869e1ae5ec6.tar.gz
platform_external_libbrillo-84b910fe90e91ef14e6ddec7c7f0a869e1ae5ec6.tar.bz2
platform_external_libbrillo-84b910fe90e91ef14e6ddec7c7f0a869e1ae5ec6.zip
libbrillo: allow redirecting process input
Add a RedirectInput method to Process that allows redirecting stdin to read from a file. BUG=chromium:767088 TEST=unittests Change-Id: Id3d440048792a9c89e1ffb3b59ba26f888191678 Reviewed-on: https://chromium-review.googlesource.com/673355 Commit-Ready: Stephen Barber <smbarber@chromium.org> Tested-by: Stephen Barber <smbarber@chromium.org> Reviewed-by: Mike Frysinger <vapier@chromium.org>
-rw-r--r--brillo/process.cc27
-rw-r--r--brillo/process.h10
-rw-r--r--brillo/process_mock.h2
-rw-r--r--brillo/process_unittest.cc12
4 files changed, 50 insertions, 1 deletions
diff --git a/brillo/process.cc b/brillo/process.cc
index 7af8fbb..5efbe5c 100644
--- a/brillo/process.cc
+++ b/brillo/process.cc
@@ -15,6 +15,7 @@
#include <map>
#include <memory>
+#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
@@ -64,6 +65,10 @@ void ProcessImpl::AddArg(const std::string& arg) {
arguments_.push_back(arg);
}
+void ProcessImpl::RedirectInput(const std::string& input_file) {
+ input_file_ = input_file;
+}
+
void ProcessImpl::RedirectOutput(const std::string& output_file) {
output_file_ = output_file;
}
@@ -257,6 +262,28 @@ bool ProcessImpl::Start() {
continue;
IGNORE_EINTR(close(i->second.child_fd_));
}
+
+ if (!input_file_.empty()) {
+ int input_handle =
+ HANDLE_EINTR(open(input_file_.c_str(),
+ O_RDONLY | O_NOFOLLOW | O_NOCTTY));
+ if (input_handle < 0) {
+ PLOG(ERROR) << "Could not open " << input_file_;
+ // Avoid exit() to avoid atexit handlers from parent.
+ _exit(kErrorExitStatus);
+ }
+
+ // It's possible input_handle is already stdin. But if not, we need
+ // to dup into that file descriptor and close the original.
+ if (input_handle != STDIN_FILENO) {
+ if (HANDLE_EINTR(dup2(input_handle, STDIN_FILENO)) < 0) {
+ PLOG(ERROR) << "Could not dup fd to stdin for " << input_file_;
+ _exit(kErrorExitStatus);
+ }
+ IGNORE_EINTR(close(input_handle));
+ }
+ }
+
if (!output_file_.empty()) {
int output_handle = HANDLE_EINTR(open(
output_file_.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW,
diff --git a/brillo/process.h b/brillo/process.h
index 9760ab3..d69d38b 100644
--- a/brillo/process.h
+++ b/brillo/process.h
@@ -13,6 +13,7 @@
#include <base/bind.h>
#include <base/callback.h>
+#include <base/files/file_path.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/brillo_export.h>
@@ -48,7 +49,12 @@ class BRILLO_EXPORT Process {
AddArg(base::StringPrintf("%d", value));
}
- // Redirects stderr and stdout to |output_file|.
+ // Redirects to read stdin from |input_file|. |input_file| must not be
+ // a symlink.
+ virtual void RedirectInput(const std::string& input_file) = 0;
+
+ // Redirects stderr and stdout to |output_file|. |output_file| must not be
+ // a symlink.
virtual void RedirectOutput(const std::string& output_file) = 0;
// Indicates we want to redirect |child_fd| in the child process's
@@ -163,6 +169,7 @@ class BRILLO_EXPORT ProcessImpl : public Process {
virtual ~ProcessImpl();
virtual void AddArg(const std::string& arg);
+ virtual void RedirectInput(const std::string& input_file);
virtual void RedirectOutput(const std::string& output_file);
virtual void RedirectUsingPipe(int child_fd, bool is_input);
virtual void BindFd(int parent_fd, int child_fd);
@@ -212,6 +219,7 @@ class BRILLO_EXPORT ProcessImpl : public Process {
// process. pid must not be modified except by calling
// UpdatePid(new_pid).
pid_t pid_;
+ std::string input_file_;
std::string output_file_;
std::vector<std::string> arguments_;
// Map of child target file descriptors (first) to information about
diff --git a/brillo/process_mock.h b/brillo/process_mock.h
index f73d242..92ffa0a 100644
--- a/brillo/process_mock.h
+++ b/brillo/process_mock.h
@@ -7,6 +7,7 @@
#include <string>
+#include <base/files/file_path.h>
#include <gmock/gmock.h>
#include "brillo/process.h"
@@ -19,6 +20,7 @@ class ProcessMock : public Process {
virtual ~ProcessMock() {}
MOCK_METHOD1(AddArg, void(const std::string& arg));
+ MOCK_METHOD1(RedirectInput, void(const std::string& input_file));
MOCK_METHOD1(RedirectOutput, void(const std::string& output_file));
MOCK_METHOD2(RedirectUsingPipe, void(int child_fd, bool is_input));
MOCK_METHOD2(BindFd, void(int parent_fd, int child_fd));
diff --git a/brillo/process_unittest.cc b/brillo/process_unittest.cc
index d2c92e6..2416e76 100644
--- a/brillo/process_unittest.cc
+++ b/brillo/process_unittest.cc
@@ -157,6 +157,18 @@ TEST_F(ProcessTest, NonZeroReturnValue) {
EXPECT_EQ("", GetLog());
}
+TEST_F(ProcessTest, RedirectInputDevNull) {
+ process_.AddArg(kBinCat);
+ process_.RedirectInput("/dev/null");
+ EXPECT_EQ(0, process_.Run());
+}
+
+TEST_F(ProcessTest, BadInputFile) {
+ process_.AddArg(kBinCat);
+ process_.RedirectInput("/bad/path");
+ EXPECT_EQ(static_cast<pid_t>(Process::kErrorExitStatus), process_.Run());
+}
+
TEST_F(ProcessTest, BadOutputFile) {
process_.AddArg(kBinEcho);
process_.RedirectOutput("/bad/path");