blob: 1143447354cc6afa6aca37c4f0b1becbfd286676 [file] [log] [blame]
Darin Petkov58dd1342011-05-06 12:05:13 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/postinstall_runner_action.h"
Jay Srinivasan1c0fe792013-03-28 16:45:25 -07006
adlr@google.com3defe6a2009-12-04 20:57:17 +00007#include <sys/mount.h>
8#include <stdlib.h>
Andrew de los Reyesf9714432010-05-04 10:21:23 -07009#include <vector>
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070010
Chris Sosabe45bef2013-04-09 18:25:12 -070011#include "update_engine/action_processor.h"
Andrew de los Reyesf9714432010-05-04 10:21:23 -070012#include "update_engine/subprocess.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000013#include "update_engine/utils.h"
14
15namespace chromeos_update_engine {
16
17using std::string;
Andrew de los Reyesf9714432010-05-04 10:21:23 -070018using std::vector;
adlr@google.com3defe6a2009-12-04 20:57:17 +000019
20namespace {
Darin Petkov6f03a3b2010-11-10 14:27:14 -080021const char kPostinstallScript[] = "/postinst";
adlr@google.com3defe6a2009-12-04 20:57:17 +000022}
23
24void PostinstallRunnerAction::PerformAction() {
25 CHECK(HasInputObject());
Chris Sosad317e402013-06-12 13:47:09 -070026 install_plan_ = GetInputObject();
27 const string install_device = install_plan_.install_path;
Andrew de los Reyesf9714432010-05-04 10:21:23 -070028 ScopedActionCompleter completer(processor_, this);
Darin Petkovc1a8b422010-07-19 11:34:49 -070029
Darin Petkov6f03a3b2010-11-10 14:27:14 -080030 // Make mountpoint.
Andrew de los Reyesf9714432010-05-04 10:21:23 -070031 TEST_AND_RETURN(utils::MakeTempDirectory("/tmp/au_postint_mount.XXXXXX",
Darin Petkov6f03a3b2010-11-10 14:27:14 -080032 &temp_rootfs_dir_));
33 ScopedDirRemover temp_dir_remover(temp_rootfs_dir_);
Andrew de los Reyesf9714432010-05-04 10:21:23 -070034
Darin Petkov6f03a3b2010-11-10 14:27:14 -080035 unsigned long mountflags = MS_RDONLY;
36 int rc = mount(install_device.c_str(),
37 temp_rootfs_dir_.c_str(),
Andrew de los Reyesbfabc302011-01-31 17:23:50 -080038 "ext2",
Andrew de los Reyes3270f742010-07-15 22:28:14 -070039 mountflags,
40 NULL);
Chris Sosad317e402013-06-12 13:47:09 -070041 // TODO(sosa): Remove once crbug.com/208022 is resolved.
Darin Petkov6f03a3b2010-11-10 14:27:14 -080042 if (rc < 0) {
Chris Sosad317e402013-06-12 13:47:09 -070043 LOG(INFO) << "Failed to mount install part "
44 << install_device << " as ext2. Trying ext3.";
Darin Petkov6f03a3b2010-11-10 14:27:14 -080045 rc = mount(install_device.c_str(),
46 temp_rootfs_dir_.c_str(),
47 "ext3",
48 mountflags,
49 NULL);
50 }
51 if (rc < 0) {
52 LOG(ERROR) << "Unable to mount destination device " << install_device
53 << " onto " << temp_rootfs_dir_;
54 return;
adlr@google.com3defe6a2009-12-04 20:57:17 +000055 }
56
Darin Petkov6f03a3b2010-11-10 14:27:14 -080057 temp_dir_remover.set_should_remove(false);
58 completer.set_should_complete(false);
59
Chris Sosad317e402013-06-12 13:47:09 -070060 if (install_plan_.powerwash_required) {
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070061 if (utils::CreatePowerwashMarkerFile()) {
62 powerwash_marker_created_ = true;
63 } else {
David Zeuthena99981f2013-04-29 13:42:47 -070064 completer.set_code(kErrorCodePostinstallPowerwashError);
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070065 return;
66 }
67 }
68
Darin Petkov6f03a3b2010-11-10 14:27:14 -080069 // Runs the postinstall script asynchronously to free up the main loop while
70 // it's running.
71 vector<string> command;
72 command.push_back(temp_rootfs_dir_ + kPostinstallScript);
73 command.push_back(install_device);
Darin Petkov58dd1342011-05-06 12:05:13 -070074 if (!Subprocess::Get().Exec(command, StaticCompletePostinstall, this)) {
75 CompletePostinstall(1);
76 }
Darin Petkov6f03a3b2010-11-10 14:27:14 -080077}
78
79void PostinstallRunnerAction::CompletePostinstall(int return_code) {
80 ScopedActionCompleter completer(processor_, this);
81 ScopedTempUnmounter temp_unmounter(temp_rootfs_dir_);
82 if (return_code != 0) {
83 LOG(ERROR) << "Postinst command failed with code: " << return_code;
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070084
85 // Undo any changes done to trigger Powerwash using clobber-state.
86 if (powerwash_marker_created_)
87 utils::DeletePowerwashMarkerFile();
88
Andrew de los Reyesfe57d542011-06-07 09:00:36 -070089 if (return_code == 3) {
Andrew de los Reyesc1d5c932011-04-20 17:15:47 -070090 // This special return code means that we tried to update firmware,
91 // but couldn't because we booted from FW B, and we need to reboot
92 // to get back to FW A.
David Zeuthena99981f2013-04-29 13:42:47 -070093 completer.set_code(kErrorCodePostinstallBootedFromFirmwareB);
Andrew de los Reyesc1d5c932011-04-20 17:15:47 -070094 }
Darin Petkov6f03a3b2010-11-10 14:27:14 -080095 return;
96 }
Jay Srinivasanae4697c2013-03-18 17:08:08 -070097
98 LOG(INFO) << "Postinst command succeeded";
Chris Sosad317e402013-06-12 13:47:09 -070099 if (HasOutputPipe()) {
100 SetOutputObject(install_plan_);
101 }
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700102
David Zeuthena99981f2013-04-29 13:42:47 -0700103 completer.set_code(kErrorCodeSuccess);
adlr@google.com3defe6a2009-12-04 20:57:17 +0000104}
105
Darin Petkov6f03a3b2010-11-10 14:27:14 -0800106void PostinstallRunnerAction::StaticCompletePostinstall(int return_code,
107 const string& output,
108 void* p) {
109 reinterpret_cast<PostinstallRunnerAction*>(p)->CompletePostinstall(
110 return_code);
111}
112
adlr@google.com3defe6a2009-12-04 20:57:17 +0000113} // namespace chromeos_update_engine