1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by a apache 2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/step/configuration/step_configure.h"
7 #include <boost/filesystem/path.hpp>
9 #include <pkgmgr-info.h>
11 #include <sys/types.h>
13 #include <tzplatform_config.h>
19 #include "common/request.h"
20 #include "common/utils/file_util.h"
21 #include "common/utils/user_util.h"
23 namespace bf = boost::filesystem;
25 namespace common_installer {
26 namespace configuration {
28 const char kStrEmpty[] = "";
29 const char kAppFWUser[] = "app_fw";
31 StepConfigure::StepConfigure(InstallerContext* context, PkgMgrPtr pkgmgr)
36 Step::Status StepConfigure::process() {
37 SetupRequestMode(pkgmgr_->GetUid());
39 SetupFileCreationMask();
41 SetupSkipCheckReference();
43 if (!SetupRootAppDirectory())
44 return Status::CONFIG_ERROR;
46 RequestType requestType = context_->request_type.get();
47 switch (requestType) {
48 case RequestType::Install:
49 case RequestType::Update:
50 context_->file_path.set(pkgmgr_->GetRequestInfo());
51 context_->pkgid.set(kStrEmpty);
52 if (!pkgmgr_->GetTepPath().empty()) {
53 context_->tep_path.set(pkgmgr_->GetTepPath());
54 context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
57 case RequestType::PartialUninstall:
59 case RequestType::Uninstall:
60 if (context_->is_preload_rw_package.get())
62 SetupIsForceRemoval();
63 context_->pkgid.set(pkgmgr_->GetRequestInfo());
64 context_->file_path.set(kStrEmpty);
66 case RequestType::Reinstall:
67 context_->unpacked_dir_path.set(
68 context_->root_application_path.get() / "tmp" /
69 pkgmgr_->GetRequestInfo());
70 context_->pkgid.set(pkgmgr_->GetRequestInfo());
71 context_->file_path.set(kStrEmpty);
73 case RequestType::Delta:
74 context_->unpacked_dir_path.set(kStrEmpty);
75 context_->pkgid.set(kStrEmpty);
76 context_->file_path.set(pkgmgr_->GetRequestInfo());
78 case RequestType::Move:
79 context_->pkgid.set(pkgmgr_->GetRequestInfo());
80 context_->is_move_to_external.set(pkgmgr_->GetIsMoveToExternal());
82 case RequestType::Recovery:
83 context_->file_path.set(pkgmgr_->GetRequestInfo());
84 context_->pkgid.set(kStrEmpty);
86 case RequestType::MountInstall:
87 case RequestType::MountUpdate:
88 context_->file_path.set(pkgmgr_->GetRequestInfo());
89 context_->pkgid.set(kStrEmpty);
90 if (!pkgmgr_->GetTepPath().empty()) {
91 context_->tep_path.set(pkgmgr_->GetTepPath());
92 context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
95 case RequestType::ManifestPartialInstall:
96 case RequestType::ManifestPartialUpdate:
98 case RequestType::ManifestDirectInstall:
99 case RequestType::ManifestDirectUpdate: {
100 context_->pkgid.set(pkgmgr_->GetRequestInfo());
101 bf::path package_directory =
102 context_->root_application_path.get() / context_->pkgid.get();
104 bf::path(getUserManifestPath(context_->uid.get(),
105 context_->is_readonly_package.get()))
106 / bf::path(context_->pkgid.get());
108 context_->unpacked_dir_path.set(package_directory);
109 context_->pkg_path.set(package_directory);
110 context_->xml_path.set(xml_path);
113 case RequestType::ReadonlyUpdateInstall:
114 context_->file_path.set(pkgmgr_->GetRequestInfo());
115 context_->pkgid.set(kStrEmpty);
116 if (!pkgmgr_->GetTepPath().empty()) {
117 context_->tep_path.set(pkgmgr_->GetTepPath());
118 context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
121 case RequestType::ReadonlyUpdateUninstall: {
122 context_->pkgid.set(pkgmgr_->GetRequestInfo());
123 bf::path original_path =
124 bf::path(tzplatform_getenv(TZ_SYS_RO_APP)) / context_->pkgid.get();
125 context_->unpacked_dir_path.set(original_path);
126 context_->file_path.set(kStrEmpty);
129 case RequestType::DisablePkg:
130 case RequestType::EnablePkg:
131 context_->pkgid.set(pkgmgr_->GetRequestInfo());
133 case RequestType::MigrateExtImg: {
134 context_->pkgid.set(pkgmgr_->GetRequestInfo());
135 bf::path package_directory =
136 context_->root_application_path.get() / context_->pkgid.get();
137 context_->pkg_path.set(package_directory);
142 "Only installation, update and uninstallation is now supported";
143 return Status::CONFIG_ERROR;
147 // Record recovery file
148 if (requestType == RequestType::Install ||
149 requestType == RequestType::Update ||
150 requestType == RequestType::Delta ||
151 requestType == RequestType::MountInstall ||
152 requestType == RequestType::MountUpdate) {
153 std::unique_ptr<recovery::RecoveryFile> recovery_file =
154 recovery::RecoveryFile::CreateRecoveryFileForPath(
155 GenerateTemporaryPath(
156 context_->root_application_path.get() /
157 (context_->pkg_type.get() + "-recovery")));
158 if (!recovery_file) {
159 LOG(ERROR) << "Failed to create recovery file";
160 return Status::CONFIG_ERROR;
162 recovery_file->set_type(requestType);
164 if (!recovery_file->WriteAndCommitFileContent()) {
165 LOG(ERROR) << "Failed to write recovery file";
166 return Status::CONFIG_ERROR;
168 context_->recovery_info.set(RecoveryInfo(std::move(recovery_file)));
174 Step::Status StepConfigure::precheck() {
175 SetupIsPreloadRequest();
176 SetupIsPreloadRWRequest();
178 bool is_readonly = context_->is_readonly_package.get();
179 bool is_preload_rw = context_->is_preload_rw_package.get();
180 if (is_readonly && is_preload_rw) {
181 LOG(ERROR) << "Conflict of preload request!";
182 return Status::ERROR;
185 if (is_readonly || is_preload_rw)
188 uid_t uid = pkgmgr_->GetUid();
189 context_->uid.set(uid);
193 boost::optional<uid_t> appfw_uid = GetUidByUserName(kAppFWUser);
195 return Status::ERROR;
197 if (getuid() != *appfw_uid) {
198 LOG(ERROR) << "App-installer should not run with normal user!";
199 return Status::OPERATION_NOT_ALLOWED;
205 Step::Status StepConfigure::clean() {
206 // Clean up operations should not be covered by recovery
207 // as backup information is being lost during clean up
208 context_->recovery_info.get().recovery_file.reset();
212 bool StepConfigure::SetupRootAppDirectory() {
213 if (context_->root_application_path.get().empty()) {
214 std::string root_app_path =
215 GetRootAppPath(context_->is_readonly_package.get(),
216 context_->uid.get());
217 if (root_app_path.empty())
220 context_->root_application_path.set(root_app_path);
222 if (!boost::filesystem::exists(context_->root_application_path.get())) {
223 boost::system:: error_code error;
224 boost::filesystem::create_directories(
225 context_->root_application_path.get());
227 LOG(ERROR) << "Cannot create directory: "
228 << context_->root_application_path.get();
232 LOG(INFO) << "AppDir(" << context_->root_application_path.get() << ")";
236 void StepConfigure::SetupRequestMode(uid_t uid) {
237 context_->request_mode.set(GetRequestMode(uid));
240 void StepConfigure::SetupRequestType() {
241 context_->request_type.set(pkgmgr_->GetRequestType());
244 void StepConfigure::SetupFileCreationMask() {
245 mode_t old_mask, new_mask;
246 old_mask = new_mask = 0;
248 switch (context_->request_mode.get()) {
249 case RequestMode::USER:
250 new_mask = 033; // results in 744 privileges
252 case RequestMode::GLOBAL:
253 new_mask = 022; // results in 755 privileges
257 old_mask = umask(new_mask);
259 LOG(INFO) << "Changed file creation mask from " << std::oct << old_mask
260 << " to " << std::oct << new_mask;
263 void StepConfigure::SetupIsPreloadRequest() {
264 context_->is_readonly_package.set(pkgmgr_->GetIsPreloadRequest());
267 void StepConfigure::SetupIsPreloadRWRequest() {
268 context_->is_preload_rw_package.set(pkgmgr_->GetIsPreloadRWRequest());
271 void StepConfigure::SetupIsForceRemoval() {
272 context_->force_remove.set(pkgmgr_->GetIsForceRemoval());
275 void StepConfigure::SetupIsNoRemoval() {
276 context_->no_remove.set(pkgmgr_->GetIsNoRemoval());
279 void StepConfigure::SetupIsKeepRWData() {
280 context_->keep_rwdata.set(pkgmgr_->GetIsKeepRWData());
283 void StepConfigure::SetupIsPartialRW() {
284 context_->partial_rw.set(pkgmgr_->GetIsPartialRW());
287 void StepConfigure::SetupDebugMode() {
288 context_->debug_mode.set(pkgmgr_->GetDebugMode());
291 void StepConfigure::SetupSkipCheckReference() {
292 context_->skip_check_reference.set(pkgmgr_->GetIsSkipCheckReference());
295 } // namespace configuration
296 } // namespace common_installer