Parse postinstall parameters from the payload metadata.
Payload v2 includes a description of the post-install command it should
run, while in payload v1 we use the default values. This patch mounts
the partition on the new top-level directory called /postinstall that
should already be created.
Bug: 27177071
TEST=FEATURES=test emerge-link update_engine
Change-Id: Iaedf3b01e5e1ad57c68bd316b4b6e79cbab35bb6
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index f95679c..f490c08 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -790,6 +790,12 @@
install_part.name = partition.partition_name();
install_part.run_postinstall =
partition.has_run_postinstall() && partition.run_postinstall();
+ if (install_part.run_postinstall) {
+ install_part.postinstall_path =
+ (partition.has_postinstall_path() ? partition.postinstall_path()
+ : kPostinstallDefaultScript);
+ install_part.filesystem_type = partition.filesystem_type();
+ }
if (partition.has_old_partition_info()) {
const PartitionInfo& info = partition.old_partition_info();
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index 572ff41..51e85b3 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -59,9 +59,13 @@
void InstallPlan::Dump() const {
string partitions_str;
for (const auto& partition : partitions) {
- partitions_str += base::StringPrintf(
- ", part: %s (source_size: %" PRIu64 ", target_size %" PRIu64 ")",
- partition.name.c_str(), partition.source_size, partition.target_size);
+ partitions_str +=
+ base::StringPrintf(", part: %s (source_size: %" PRIu64
+ ", target_size %" PRIu64 ", postinst:%s)",
+ partition.name.c_str(),
+ partition.source_size,
+ partition.target_size,
+ utils::ToString(partition.run_postinstall).c_str());
}
LOG(INFO) << "InstallPlan: "
@@ -109,7 +113,9 @@
target_path == that.target_path &&
target_size == that.target_size &&
target_hash == that.target_hash &&
- run_postinstall == that.run_postinstall);
+ run_postinstall == that.run_postinstall &&
+ postinstall_path == that.postinstall_path &&
+ filesystem_type == that.filesystem_type);
}
} // namespace chromeos_update_engine
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index d2f15fa..454dd78 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -90,8 +90,11 @@
uint64_t target_size{0};
brillo::Blob target_hash;
- // Whether we should run the postinstall script from this partition.
+ // Whether we should run the postinstall script from this partition and the
+ // postinstall parameters.
bool run_postinstall{false};
+ std::string postinstall_path;
+ std::string filesystem_type;
};
std::vector<Partition> partitions;
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index 84ca398..fe468cc 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -23,6 +23,7 @@
#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
+#include <base/strings/string_util.h>
#include "update_engine/common/action_processor.h"
#include "update_engine/common/boot_control_interface.h"
@@ -34,16 +35,6 @@
using std::string;
using std::vector;
-namespace {
-// The absolute path to the post install command.
-const char kPostinstallScript[] = "/postinst";
-
-// Path to the binary file used by kPostinstallScript. Used to get and log the
-// file format of the binary to debug issues when the ELF format on the update
-// doesn't match the one on the current system. This path is not executed.
-const char kDebugPostinstallBinaryPath[] = "/usr/bin/cros_installer";
-}
-
void PostinstallRunnerAction::PerformAction() {
CHECK(HasInputObject());
install_plan_ = GetInputObject();
@@ -60,6 +51,11 @@
}
void PostinstallRunnerAction::PerformPartitionPostinstall() {
+ if (install_plan_.download_url.empty()) {
+ LOG(INFO) << "Skipping post-install during rollback";
+ return CompletePostinstall(ErrorCode::kSuccess);
+ }
+
// Skip all the partitions that don't have a post-install step.
while (current_partition_ < install_plan_.partitions.size() &&
!install_plan_.partitions[current_partition_].run_postinstall) {
@@ -83,38 +79,44 @@
// Perform post-install for the current_partition_ partition. At this point we
// need to call CompletePartitionPostinstall to complete the operation and
// cleanup.
+#ifdef __ANDROID__
+ fs_mount_dir_ = "/postinstall";
+#else // __ANDROID__
TEST_AND_RETURN(
- utils::MakeTempDirectory("au_postint_mount.XXXXXX", &temp_rootfs_dir_));
+ utils::MakeTempDirectory("au_postint_mount.XXXXXX", &fs_mount_dir_));
+#endif // __ANDROID__
- if (!utils::MountFilesystem(mountable_device, temp_rootfs_dir_, MS_RDONLY)) {
+ string abs_path = base::FilePath(fs_mount_dir_)
+ .AppendASCII(partition.postinstall_path)
+ .value();
+ if (!base::StartsWith(
+ abs_path, fs_mount_dir_, base::CompareCase::SENSITIVE)) {
+ LOG(ERROR) << "Invalid relative postinstall path: "
+ << partition.postinstall_path;
+ return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
+ }
+
+ if (!utils::MountFilesystem(mountable_device,
+ fs_mount_dir_,
+ MS_RDONLY,
+ partition.filesystem_type)) {
return CompletePartitionPostinstall(
1, "Error mounting the device " + mountable_device);
}
- LOG(INFO) << "Performing postinst (" << kPostinstallScript
- << ") installed on device " << partition.target_path
+ LOG(INFO) << "Performing postinst (" << partition.postinstall_path << " at "
+ << abs_path << ") installed on device " << partition.target_path
<< " and mountable device " << mountable_device;
// Logs the file format of the postinstall script we are about to run. This
// will help debug when the postinstall script doesn't match the architecture
// of our build.
- LOG(INFO) << "Format file for new " << kPostinstallScript << " is: "
- << utils::GetFileFormat(temp_rootfs_dir_ + kPostinstallScript);
- LOG(INFO) << "Format file for new " << kDebugPostinstallBinaryPath << " is: "
- << utils::GetFileFormat(
- temp_rootfs_dir_ + kDebugPostinstallBinaryPath);
+ LOG(INFO) << "Format file for new " << partition.postinstall_path
+ << " is: " << utils::GetFileFormat(abs_path);
// Runs the postinstall script asynchronously to free up the main loop while
// it's running.
- vector<string> command;
- if (!install_plan_.download_url.empty()) {
- command.push_back(temp_rootfs_dir_ + kPostinstallScript);
- } else {
- // TODO(sosa): crbug.com/366207.
- // If we're doing a rollback, just run our own postinstall.
- command.push_back(kPostinstallScript);
- }
- command.push_back(partition.target_path);
+ vector<string> command = {abs_path, partition.target_path};
if (!Subprocess::Get().Exec(
command,
base::Bind(
@@ -127,11 +129,13 @@
void PostinstallRunnerAction::CompletePartitionPostinstall(
int return_code,
const string& output) {
- utils::UnmountFilesystem(temp_rootfs_dir_);
- if (!base::DeleteFile(base::FilePath(temp_rootfs_dir_), false)) {
- PLOG(WARNING) << "Not removing mountpoint " << temp_rootfs_dir_;
+ utils::UnmountFilesystem(fs_mount_dir_);
+#ifndef ANDROID
+ if (!base::DeleteFile(base::FilePath(fs_mount_dir_), false)) {
+ PLOG(WARNING) << "Not removing temporary mountpoint " << fs_mount_dir_;
}
- temp_rootfs_dir_.clear();
+#endif // !ANDROID
+ fs_mount_dir_.clear();
if (return_code != 0) {
LOG(ERROR) << "Postinst command failed with code: " << return_code;
diff --git a/payload_consumer/postinstall_runner_action.h b/payload_consumer/postinstall_runner_action.h
index ab267b8..b4defae 100644
--- a/payload_consumer/postinstall_runner_action.h
+++ b/payload_consumer/postinstall_runner_action.h
@@ -63,7 +63,9 @@
void CompletePostinstall(ErrorCode error_code);
InstallPlan install_plan_;
- std::string temp_rootfs_dir_;
+
+ // The path where the filesystem will be mounted during post-install.
+ std::string fs_mount_dir_;
// The partition being processed on the list of partitions specified in the
// InstallPlan.
diff --git a/payload_consumer/postinstall_runner_action_unittest.cc b/payload_consumer/postinstall_runner_action_unittest.cc
index c4c68b1..85535d7 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -191,6 +191,7 @@
part.name = "part";
part.target_path = dev;
part.run_postinstall = true;
+ part.postinstall_path = kPostinstallDefaultScript;
InstallPlan install_plan;
install_plan.partitions = {part};
install_plan.download_url = "http://devserver:8080/update";
@@ -215,7 +216,7 @@
EXPECT_TRUE(delegate.code_set_);
EXPECT_EQ(should_succeed, delegate.code_ == ErrorCode::kSuccess);
if (should_succeed)
- EXPECT_TRUE(install_plan == collector_action.object());
+ EXPECT_EQ(install_plan, collector_action.object());
const base::FilePath kPowerwashMarkerPath(powerwash_marker_file);
string actual_cmd;