Block different type installation with same pkgid
[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/utils/pkgmgr_query.h"
20 #include "common/utils/file_util.h"
21 #include "common/utils/user_util.h"
22 #include "common/utils/request.h"
23
24 namespace bf = boost::filesystem;
25
26 namespace common_installer {
27 namespace configuration {
28
29 const char kStrEmpty[] = "";
30 const char kAppFWUser[] = "app_fw";
31 const char kRpmPkgType[] = "rpm";
32 const char kRpmInstaller[] = "tpk";
33
34 StepConfigure::StepConfigure(InstallerContext* context, PkgMgrPtr pkgmgr)
35     : Step(context),
36       pkgmgr_(pkgmgr) {
37 }
38
39 Step::Status StepConfigure::process() {
40   SetupRequestMode(pkgmgr_->GetUid());
41   SetupRequestType();
42   SetupFileCreationMask();
43   SetupDebugMode();
44   SetupSkipCheckReference();
45   SetupSkipOptimization();
46
47   if (!SetupRootAppDirectory())
48     return Status::CONFIG_ERROR;
49
50   RequestType request_type = context_->request_type.get();
51   switch (request_type) {
52     case RequestType::Install:
53     case RequestType::Update: {
54       context_->file_path.set(pkgmgr_->GetRequestInfo(context_->index.get()));
55       if (!pkgmgr_->GetTepPath().empty()) {
56         context_->tep_path.set(pkgmgr_->GetTepPath());
57         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
58       }
59       context_->pkgid.set(GetPkgIdFromFile());
60       break;
61     }
62     case RequestType::PartialUninstall:
63     case RequestType::Uninstall:
64       if (request_type == RequestType::PartialUninstall)
65         SetupIsPartialRW();
66       SetupIsKeepRWData();
67       SetupIsForceRemoval();
68       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
69       context_->file_path.set(kStrEmpty);
70       break;
71     case RequestType::Reinstall:
72       context_->unpacked_dir_path.set(
73           bf::path(tzplatform_getenv(TZ_SDK_TOOLS)) / "tmp" /
74           pkgmgr_->GetRequestInfo(context_->index.get()));
75       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
76       context_->file_path.set(kStrEmpty);
77       break;
78     case RequestType::Delta:
79       context_->unpacked_dir_path.set(kStrEmpty);
80       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
81       context_->file_path.set(pkgmgr_->GetRequestInfo(context_->index.get()));
82       break;
83     case RequestType::Move:
84       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
85       context_->is_move_to_external.set(pkgmgr_->GetIsMoveToExternal());
86       SetupMoveType();
87       break;
88     case RequestType::Recovery:
89       context_->file_path.set(pkgmgr_->GetRequestInfo(context_->index.get()));
90       context_->recovery_info.set(
91           RecoveryInfo(context_->file_path.get(),
92               pkgmgr_->GetRecoveryCleanup()));
93       break;
94     case RequestType::MountInstall:
95     case RequestType::MountUpdate: {
96       context_->file_path.set(pkgmgr_->GetRequestInfo(context_->index.get()));
97       if (!pkgmgr_->GetTepPath().empty()) {
98         context_->tep_path.set(pkgmgr_->GetTepPath());
99         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
100       }
101       context_->pkgid.set(GetPkgIdFromFile());
102       break;
103     }
104     case RequestType::ManifestPartialInstall:
105     case RequestType::ManifestPartialUpdate:
106     case RequestType::ManifestDirectInstall:
107     case RequestType::ManifestDirectUpdate: {
108       if (request_type == RequestType::ManifestPartialInstall ||
109           request_type == RequestType::ManifestPartialUpdate)
110         SetupIsPartialRW();
111       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
112       bf::path xml_path =
113           bf::path(getUserManifestPath(context_->uid.get(),
114               context_->is_readonly_package.get()))
115           / bf::path(context_->pkgid.get());
116       xml_path += ".xml";
117       context_->unpacked_dir_path.set(context_->GetPkgPath());
118       context_->xml_path.set(xml_path);
119       break;
120     }
121     case RequestType::ReadonlyUpdateInstall: {
122       context_->file_path.set(pkgmgr_->GetRequestInfo(context_->index.get()));
123       if (!pkgmgr_->GetTepPath().empty()) {
124         context_->tep_path.set(pkgmgr_->GetTepPath());
125         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
126       }
127       context_->pkgid.set(GetPkgIdFromFile());
128       break;
129     }
130     case RequestType::ReadonlyUpdateUninstall: {
131       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
132       bf::path original_path =
133           bf::path(tzplatform_getenv(TZ_SYS_RO_APP)) / context_->pkgid.get();
134       context_->unpacked_dir_path.set(original_path);
135       context_->file_path.set(kStrEmpty);
136       SetupIsKeepRWData();
137       break;
138     }
139     case RequestType::DisablePkg:
140     case RequestType::EnablePkg:
141       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
142       break;
143     case RequestType::MigrateExtImg: {
144       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
145       break;
146     }
147     case RequestType::RecoverDB: {
148       context_->pkgid.set(pkgmgr_->GetRequestInfo(context_->index.get()));
149       break;
150     }
151     default:
152       LOG(ERROR) << "Unknown request type";
153       return Status::CONFIG_ERROR;
154   }
155
156   if (!CheckInvalidBackendUsage())
157     return Status::OPERATION_NOT_ALLOWED;
158
159   LOG(INFO) << "Request Type: " << GetRequestTypeString(request_type);
160
161   return Status::OK;
162 }
163
164 Step::Status StepConfigure::precheck() {
165   SetupIsPreloadRequest();
166   SetupIsPreloadRWRequest();
167
168   bool is_readonly = context_->is_readonly_package.get();
169   bool is_preload_rw = context_->is_preload_rw_package.get();
170   if (is_readonly && is_preload_rw) {
171     LOG(ERROR) << "Conflict of preload request!";
172     return Status::ERROR;
173   }
174
175   if (is_readonly || is_preload_rw)
176     SetupIsNoRemoval();
177
178   uid_t uid = pkgmgr_->GetUid();
179   context_->uid.set(uid);
180   if (getuid() == 0)
181     return Status::OK;
182
183   boost::optional<uid_t> appfw_uid = GetUidByUserName(kAppFWUser);
184   if (!appfw_uid)
185     return Status::ERROR;
186
187   if (getuid() != *appfw_uid) {
188     LOG(ERROR) << "App-installer should not run with normal user!";
189     return Status::OPERATION_NOT_ALLOWED;
190   }
191
192   return Status::OK;
193 }
194
195 bool StepConfigure::SetupRootAppDirectory() {
196   if (context_->root_application_path.get().empty()) {
197     std::string root_app_path =
198         GetRootAppPath(context_->is_readonly_package.get(),
199         context_->uid.get());
200     if (root_app_path.empty())
201       return false;
202
203     context_->root_application_path.set(root_app_path);
204   }
205   if (!boost::filesystem::exists(context_->root_application_path.get())) {
206     boost::system::error_code error;
207     boost::filesystem::create_directories(
208         context_->root_application_path.get());
209     if (error) {
210       LOG(ERROR) << "Cannot create directory: "
211                  << context_->root_application_path.get();
212       return false;
213     }
214   }
215   LOG(INFO) << "AppDir(" << context_->root_application_path.get() << ")";
216   return true;
217 }
218
219 void StepConfigure::SetupRequestMode(uid_t uid) {
220   context_->request_mode.set(GetRequestMode(uid));
221 }
222
223 void StepConfigure::SetupRequestType() {
224   context_->request_type.set(pkgmgr_->GetRequestType(context_->index.get()));
225 }
226
227 void StepConfigure::SetupFileCreationMask() {
228   mode_t old_mask, new_mask;
229   old_mask = new_mask = 0;
230
231   switch (context_->request_mode.get()) {
232     case RequestMode::USER:
233       new_mask = 033;  // results in 744 privileges
234       break;
235     case RequestMode::GLOBAL:
236       new_mask = 022;  // results in 755 privileges
237       break;
238   }
239
240   old_mask = umask(new_mask);
241
242   LOG(INFO) << "Changed file creation mask from " << std::oct <<  old_mask
243       << " to " << std::oct <<  new_mask;
244 }
245
246 void StepConfigure::SetupIsPreloadRequest() {
247   context_->is_readonly_package.set(pkgmgr_->GetIsPreloadRequest());
248 }
249
250 void StepConfigure::SetupIsPreloadRWRequest() {
251   context_->is_preload_rw_package.set(pkgmgr_->GetIsPreloadRWRequest());
252 }
253
254 void StepConfigure::SetupIsForceRemoval() {
255   context_->force_remove.set(pkgmgr_->GetIsForceRemoval());
256 }
257
258 void StepConfigure::SetupIsNoRemoval() {
259   context_->no_remove.set(pkgmgr_->GetIsNoRemoval());
260 }
261
262 void StepConfigure::SetupIsKeepRWData() {
263   context_->keep_rwdata.set(pkgmgr_->GetIsKeepRWData());
264 }
265
266 void StepConfigure::SetupIsPartialRW() {
267   context_->partial_rw.set(pkgmgr_->GetIsPartialRW());
268 }
269
270 void StepConfigure::SetupDebugMode() {
271   context_->debug_mode.set(pkgmgr_->GetDebugMode());
272 }
273
274 void StepConfigure::SetupSkipCheckReference() {
275   context_->skip_check_reference.set(pkgmgr_->GetIsSkipCheckReference());
276 }
277
278 void StepConfigure::SetupSkipOptimization() {
279   context_->skip_optimization.set(pkgmgr_->GetSkipOptimization());
280 }
281
282 void StepConfigure::SetupMoveType() {
283   int move_type = pkgmgr_->GetMoveType();
284   switch (move_type) {
285     case 0:
286       context_->move_type.set(MoveType::TO_INTERNAL);
287       break;
288     case 1:
289       context_->move_type.set(MoveType::TO_EXTERNAL);
290       break;
291     case 2:
292       context_->move_type.set(MoveType::TO_EXTENDED);
293       break;
294     default:
295       context_->move_type.set(MoveType::TO_INTERNAL);
296       break;
297   }
298 }
299
300 std::string StepConfigure::GetPkgIdFromFile() {
301   auto app_query_interface = pkgmgr_->GetAppQueryInterface();
302   if (!app_query_interface)
303     return "";
304
305   return app_query_interface->GetPkgId(
306       pkgmgr_->GetRequestInfo(context_->index.get()));
307 }
308
309 bool StepConfigure::CheckInvalidBackendUsage() {
310   if (context_->pkgid.get().empty())
311     return true;
312
313   PkgQueryInterface pkg_query(context_->pkgid.get().c_str(),
314       context_->uid.get());
315   if (!pkg_query.IsValid()) {
316     LOG(INFO) << "pkg[" << context_->pkgid.get()
317         << "] is not installed, skip checking backend with installed pkg";
318     return true;
319   }
320
321   const std::string& backend_type = context_->pkg_type.get();
322   std::string installed_pkg_type = pkg_query.Type();
323   if (installed_pkg_type == kRpmPkgType)
324     installed_pkg_type = kRpmInstaller;
325
326   if (installed_pkg_type != backend_type) {
327     LOG(ERROR) << "Wrong use of backend : package's type [" << pkg_query.Type()
328         << "] mismatched backend [" << backend_type << "]";
329     return false;
330   }
331
332   return true;
333 }
334
335 }  // namespace configuration
336 }  // namespace common_installer