OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "update_engine/postinstall_runner_action.h" | 5 #include "update_engine/postinstall_runner_action.h" |
6 #include <sys/mount.h> | 6 #include <sys/mount.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <vector> | 8 #include <vector> |
9 #include "update_engine/subprocess.h" | 9 #include "update_engine/subprocess.h" |
10 #include "update_engine/utils.h" | 10 #include "update_engine/utils.h" |
11 | 11 |
12 namespace chromeos_update_engine { | 12 namespace chromeos_update_engine { |
13 | 13 |
14 using std::string; | 14 using std::string; |
15 using std::vector; | 15 using std::vector; |
16 | 16 |
17 namespace { | 17 namespace { |
18 const string kPostinstallScript("/postinst"); | 18 const char kPostinstallScript[] = "/postinst"; |
19 } | 19 } |
20 | 20 |
21 void PostinstallRunnerAction::PerformAction() { | 21 void PostinstallRunnerAction::PerformAction() { |
22 CHECK(HasInputObject()); | 22 CHECK(HasInputObject()); |
23 const InstallPlan install_plan = GetInputObject(); | 23 const InstallPlan install_plan = GetInputObject(); |
24 const string install_device = install_plan.install_path; | 24 const string install_device = install_plan.install_path; |
25 ScopedActionCompleter completer(processor_, this); | 25 ScopedActionCompleter completer(processor_, this); |
26 | 26 |
27 // Make mountpoint | 27 // Make mountpoint. |
28 string temp_dir; | |
29 TEST_AND_RETURN(utils::MakeTempDirectory("/tmp/au_postint_mount.XXXXXX", | 28 TEST_AND_RETURN(utils::MakeTempDirectory("/tmp/au_postint_mount.XXXXXX", |
30 &temp_dir)); | 29 &temp_rootfs_dir_)); |
31 ScopedDirRemover temp_dir_remover(temp_dir); | 30 ScopedDirRemover temp_dir_remover(temp_rootfs_dir_); |
32 | 31 |
33 { | 32 unsigned long mountflags = MS_RDONLY; |
34 // Scope for the mount | 33 int rc = mount(install_device.c_str(), |
35 unsigned long mountflags = MS_RDONLY; | 34 temp_rootfs_dir_.c_str(), |
36 | 35 "ext4", |
37 int rc = mount(install_device.c_str(), | |
38 temp_dir.c_str(), | |
39 "ext4", | |
40 mountflags, | |
41 NULL); | |
42 if (rc < 0) { | |
43 LOG(INFO) << "Failed to mount install part as ext4. Trying ext3."; | |
44 rc = mount(install_device.c_str(), | |
45 temp_dir.c_str(), | |
46 "ext3", | |
47 mountflags, | 36 mountflags, |
48 NULL); | 37 NULL); |
49 } | 38 if (rc < 0) { |
50 if (rc < 0) { | 39 LOG(INFO) << "Failed to mount install part as ext4. Trying ext3."; |
51 LOG(ERROR) << "Unable to mount destination device " << install_device | 40 rc = mount(install_device.c_str(), |
52 << " onto " << temp_dir; | 41 temp_rootfs_dir_.c_str(), |
53 return; | 42 "ext3", |
54 } | 43 mountflags, |
55 ScopedFilesystemUnmounter unmounter(temp_dir); | 44 NULL); |
56 | 45 } |
57 // run postinstall script | 46 if (rc < 0) { |
58 vector<string> command; | 47 LOG(ERROR) << "Unable to mount destination device " << install_device |
59 command.push_back(temp_dir + kPostinstallScript); | 48 << " onto " << temp_rootfs_dir_; |
60 command.push_back(install_device); | 49 return; |
61 rc = 0; | |
62 TEST_AND_RETURN(Subprocess::SynchronousExec(command, &rc)); | |
63 bool success = (rc == 0); | |
64 if (!success) { | |
65 LOG(ERROR) << "Postinst command failed with code: " << rc; | |
66 return; | |
67 } | |
68 } | 50 } |
69 | 51 |
| 52 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 |
| 63 void 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; |
| 68 return; |
| 69 } |
70 if (HasOutputPipe()) { | 70 if (HasOutputPipe()) { |
71 SetOutputObject(install_plan); | 71 CHECK(HasInputObject()); |
| 72 SetOutputObject(GetInputObject()); |
72 } | 73 } |
73 completer.set_code(kActionCodeSuccess); | 74 completer.set_code(kActionCodeSuccess); |
74 } | 75 } |
75 | 76 |
| 77 void PostinstallRunnerAction::StaticCompletePostinstall(int return_code, |
| 78 const string& output, |
| 79 void* p) { |
| 80 reinterpret_cast<PostinstallRunnerAction*>(p)->CompletePostinstall( |
| 81 return_code); |
| 82 } |
| 83 |
76 } // namespace chromeos_update_engine | 84 } // namespace chromeos_update_engine |
OLD | NEW |