blob: 2c8b943c3c986a6299cfc8657b447cfc92211806 [file] [log] [blame]
Darin Petkov6d5dbf62010-11-08 16:09:55 -08001// Copyright (c) 2010 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"
6#include <sys/mount.h>
7#include <stdlib.h>
Andrew de los Reyesf9714432010-05-04 10:21:23 -07008#include <vector>
9#include "update_engine/subprocess.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000010#include "update_engine/utils.h"
11
12namespace chromeos_update_engine {
13
14using std::string;
Andrew de los Reyesf9714432010-05-04 10:21:23 -070015using std::vector;
adlr@google.com3defe6a2009-12-04 20:57:17 +000016
17namespace {
Darin Petkov6f03a3b2010-11-10 14:27:14 -080018const char kPostinstallScript[] = "/postinst";
adlr@google.com3defe6a2009-12-04 20:57:17 +000019}
20
21void PostinstallRunnerAction::PerformAction() {
22 CHECK(HasInputObject());
Andrew de los Reyesf9714432010-05-04 10:21:23 -070023 const InstallPlan install_plan = GetInputObject();
24 const string install_device = install_plan.install_path;
25 ScopedActionCompleter completer(processor_, this);
Darin Petkovc1a8b422010-07-19 11:34:49 -070026
Darin Petkov6f03a3b2010-11-10 14:27:14 -080027 // Make mountpoint.
Andrew de los Reyesf9714432010-05-04 10:21:23 -070028 TEST_AND_RETURN(utils::MakeTempDirectory("/tmp/au_postint_mount.XXXXXX",
Darin Petkov6f03a3b2010-11-10 14:27:14 -080029 &temp_rootfs_dir_));
30 ScopedDirRemover temp_dir_remover(temp_rootfs_dir_);
Andrew de los Reyesf9714432010-05-04 10:21:23 -070031
Darin Petkov6f03a3b2010-11-10 14:27:14 -080032 unsigned long mountflags = MS_RDONLY;
33 int rc = mount(install_device.c_str(),
34 temp_rootfs_dir_.c_str(),
Andrew de los Reyesbfabc302011-01-31 17:23:50 -080035 "ext2",
Andrew de los Reyes3270f742010-07-15 22:28:14 -070036 mountflags,
37 NULL);
Darin Petkov6f03a3b2010-11-10 14:27:14 -080038 if (rc < 0) {
Andrew de los Reyesbfabc302011-01-31 17:23:50 -080039 LOG(INFO) << "Failed to mount install part as ext2. Trying ext3.";
Darin Petkov6f03a3b2010-11-10 14:27:14 -080040 rc = mount(install_device.c_str(),
41 temp_rootfs_dir_.c_str(),
42 "ext3",
43 mountflags,
44 NULL);
45 }
46 if (rc < 0) {
47 LOG(ERROR) << "Unable to mount destination device " << install_device
48 << " onto " << temp_rootfs_dir_;
49 return;
adlr@google.com3defe6a2009-12-04 20:57:17 +000050 }
51
Darin Petkov6f03a3b2010-11-10 14:27:14 -080052 temp_dir_remover.set_should_remove(false);
53 completer.set_should_complete(false);
54
55 // Runs the postinstall script asynchronously to free up the main loop while
56 // it's running.
57 vector<string> command;
58 command.push_back(temp_rootfs_dir_ + kPostinstallScript);
59 command.push_back(install_device);
60 Subprocess::Get().Exec(command, StaticCompletePostinstall, this);
61}
62
63void PostinstallRunnerAction::CompletePostinstall(int return_code) {
64 ScopedActionCompleter completer(processor_, this);
65 ScopedTempUnmounter temp_unmounter(temp_rootfs_dir_);
66 if (return_code != 0) {
67 LOG(ERROR) << "Postinst command failed with code: " << return_code;
Andrew de los Reyesc1d5c932011-04-20 17:15:47 -070068 if (return_code == 2) {
69 // This special return code means that we tried to update firmware,
70 // but couldn't because we booted from FW B, and we need to reboot
71 // to get back to FW A.
72 completer.set_code(kActionCodePostinstallBootedFromFirmwareB);
73 }
Darin Petkov6f03a3b2010-11-10 14:27:14 -080074 return;
75 }
Andrew de los Reyesf9714432010-05-04 10:21:23 -070076 if (HasOutputPipe()) {
Darin Petkov6f03a3b2010-11-10 14:27:14 -080077 CHECK(HasInputObject());
78 SetOutputObject(GetInputObject());
adlr@google.com3defe6a2009-12-04 20:57:17 +000079 }
Darin Petkovc1a8b422010-07-19 11:34:49 -070080 completer.set_code(kActionCodeSuccess);
adlr@google.com3defe6a2009-12-04 20:57:17 +000081}
82
Darin Petkov6f03a3b2010-11-10 14:27:14 -080083void PostinstallRunnerAction::StaticCompletePostinstall(int return_code,
84 const string& output,
85 void* p) {
86 reinterpret_cast<PostinstallRunnerAction*>(p)->CompletePostinstall(
87 return_code);
88}
89
adlr@google.com3defe6a2009-12-04 20:57:17 +000090} // namespace chromeos_update_engine