diff options
author | Stephen Barber <smbarber@chromium.org> | 2017-09-19 11:22:24 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-09-22 17:55:28 -0700 |
commit | 84b910fe90e91ef14e6ddec7c7f0a869e1ae5ec6 (patch) | |
tree | eb2c4c8b72b2f2472d3edf6eddec5d53a16ff46a | |
parent | 35dcdc75d8e20ebe9ab68b8b8eafe6fb11817d69 (diff) | |
download | platform_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.cc | 27 | ||||
-rw-r--r-- | brillo/process.h | 10 | ||||
-rw-r--r-- | brillo/process_mock.h | 2 | ||||
-rw-r--r-- | brillo/process_unittest.cc | 12 |
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"); |