Handle skip-check-reference option
[platform/core/appfw/app-installers.git] / src / common / step / configuration / step_configure.cc
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.
4
5 #include "common/step/configuration/step_configure.h"
6
7 #include <boost/filesystem/path.hpp>
8
9 #include <pkgmgr-info.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 #include <tzplatform_config.h>
14
15 #include <memory>
16 #include <string>
17 #include <utility>
18
19 #include "common/request.h"
20 #include "common/utils/file_util.h"
21 #include "common/utils/user_util.h"
22
23 namespace bf = boost::filesystem;
24
25 namespace common_installer {
26 namespace configuration {
27
28 const char kStrEmpty[] = "";
29 const char kAppFWUser[] = "app_fw";
30
31 StepConfigure::StepConfigure(InstallerContext* context, PkgMgrPtr pkgmgr)
32     : Step(context),
33       pkgmgr_(pkgmgr) {
34 }
35
36 Step::Status StepConfigure::process() {
37   SetupRequestMode(pkgmgr_->GetUid());
38   SetupRequestType();
39   SetupFileCreationMask();
40   SetupDebugMode();
41   SetupSkipCheckReference();
42
43   if (!SetupRootAppDirectory())
44     return Status::CONFIG_ERROR;
45
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());
55       }
56       break;
57     case RequestType::PartialUninstall:
58       SetupIsPartialRW();
59     case RequestType::Uninstall:
60       if (context_->is_preload_rw_package.get())
61         SetupIsKeepRWData();
62       SetupIsForceRemoval();
63       context_->pkgid.set(pkgmgr_->GetRequestInfo());
64       context_->file_path.set(kStrEmpty);
65       break;
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);
72       break;
73     case RequestType::Delta:
74       context_->unpacked_dir_path.set(kStrEmpty);
75       context_->pkgid.set(kStrEmpty);
76       context_->file_path.set(pkgmgr_->GetRequestInfo());
77       break;
78     case RequestType::Move:
79       context_->pkgid.set(pkgmgr_->GetRequestInfo());
80       context_->is_move_to_external.set(pkgmgr_->GetIsMoveToExternal());
81       break;
82     case RequestType::Recovery:
83       context_->file_path.set(pkgmgr_->GetRequestInfo());
84       context_->pkgid.set(kStrEmpty);
85       break;
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());
93       }
94       break;
95     case RequestType::ManifestPartialInstall:
96     case RequestType::ManifestPartialUpdate:
97       SetupIsPartialRW();
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();
103       bf::path xml_path =
104           bf::path(getUserManifestPath(context_->uid.get(),
105               context_->is_readonly_package.get()))
106           / bf::path(context_->pkgid.get());
107       xml_path += ".xml";
108       context_->unpacked_dir_path.set(package_directory);
109       context_->pkg_path.set(package_directory);
110       context_->xml_path.set(xml_path);
111       break;
112     }
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());
119       }
120       break;
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);
127       break;
128     }
129     case RequestType::DisablePkg:
130     case RequestType::EnablePkg:
131       context_->pkgid.set(pkgmgr_->GetRequestInfo());
132       break;
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);
138       break;
139     }
140     default:
141       LOG(ERROR) <<
142           "Only installation, update and uninstallation is now supported";
143       return Status::CONFIG_ERROR;
144       break;
145   }
146
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;
161     }
162     recovery_file->set_type(requestType);
163
164     if (!recovery_file->WriteAndCommitFileContent()) {
165       LOG(ERROR) << "Failed to write recovery file";
166       return Status::CONFIG_ERROR;
167     }
168     context_->recovery_info.set(RecoveryInfo(std::move(recovery_file)));
169   }
170
171   return Status::OK;
172 }
173
174 Step::Status StepConfigure::precheck() {
175   SetupIsPreloadRequest();
176   SetupIsPreloadRWRequest();
177
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;
183   }
184
185   if (is_readonly || is_preload_rw)
186     SetupIsNoRemoval();
187
188   uid_t uid = pkgmgr_->GetUid();
189   context_->uid.set(uid);
190   if (getuid() == 0)
191     return Status::OK;
192
193   boost::optional<uid_t> appfw_uid = GetUidByUserName(kAppFWUser);
194   if (!appfw_uid)
195     return Status::ERROR;
196
197   if (getuid() != *appfw_uid) {
198     LOG(ERROR) << "App-installer should not run with normal user!";
199     return Status::OPERATION_NOT_ALLOWED;
200   }
201
202   return Status::OK;
203 }
204
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();
209   return Status::OK;
210 }
211
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())
218       return false;
219
220     context_->root_application_path.set(root_app_path);
221   }
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());
226     if (error) {
227       LOG(ERROR) << "Cannot create directory: "
228                  << context_->root_application_path.get();
229       return false;
230     }
231   }
232   LOG(INFO) << "AppDir(" << context_->root_application_path.get() << ")";
233   return true;
234 }
235
236 void StepConfigure::SetupRequestMode(uid_t uid) {
237   context_->request_mode.set(GetRequestMode(uid));
238 }
239
240 void StepConfigure::SetupRequestType() {
241   context_->request_type.set(pkgmgr_->GetRequestType());
242 }
243
244 void StepConfigure::SetupFileCreationMask() {
245   mode_t old_mask, new_mask;
246   old_mask = new_mask = 0;
247
248   switch (context_->request_mode.get()) {
249     case RequestMode::USER:
250       new_mask = 033;  // results in 744 privileges
251       break;
252     case RequestMode::GLOBAL:
253       new_mask = 022;  // results in 755 privileges
254       break;
255   }
256
257   old_mask = umask(new_mask);
258
259   LOG(INFO) << "Changed file creation mask from " << std::oct <<  old_mask
260       << " to " << std::oct <<  new_mask;
261 }
262
263 void StepConfigure::SetupIsPreloadRequest() {
264   context_->is_readonly_package.set(pkgmgr_->GetIsPreloadRequest());
265 }
266
267 void StepConfigure::SetupIsPreloadRWRequest() {
268   context_->is_preload_rw_package.set(pkgmgr_->GetIsPreloadRWRequest());
269 }
270
271 void StepConfigure::SetupIsForceRemoval() {
272   context_->force_remove.set(pkgmgr_->GetIsForceRemoval());
273 }
274
275 void StepConfigure::SetupIsNoRemoval() {
276   context_->no_remove.set(pkgmgr_->GetIsNoRemoval());
277 }
278
279 void StepConfigure::SetupIsKeepRWData() {
280   context_->keep_rwdata.set(pkgmgr_->GetIsKeepRWData());
281 }
282
283 void StepConfigure::SetupIsPartialRW() {
284   context_->partial_rw.set(pkgmgr_->GetIsPartialRW());
285 }
286
287 void StepConfigure::SetupDebugMode() {
288   context_->debug_mode.set(pkgmgr_->GetDebugMode());
289 }
290
291 void StepConfigure::SetupSkipCheckReference() {
292   context_->skip_check_reference.set(pkgmgr_->GetIsSkipCheckReference());
293 }
294
295 }  // namespace configuration
296 }  // namespace common_installer