Support legacy image for backward-compatibility
[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
42   if (!SetupRootAppDirectory())
43     return Status::CONFIG_ERROR;
44
45   switch (pkgmgr_->GetRequestType()) {
46     case RequestType::Install:
47       context_->file_path.set(pkgmgr_->GetRequestInfo());
48       context_->pkgid.set(kStrEmpty);
49       if (!pkgmgr_->GetTepPath().empty()) {
50         context_->tep_path.set(pkgmgr_->GetTepPath());
51         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
52       }
53       break;
54     case RequestType::Update:
55       context_->file_path.set(pkgmgr_->GetRequestInfo());
56       context_->pkgid.set(kStrEmpty);
57       if (!pkgmgr_->GetTepPath().empty()) {
58         context_->tep_path.set(pkgmgr_->GetTepPath());
59         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
60       }
61       break;
62     case RequestType::PartialUninstall:
63       SetupIsPartialRW();
64     case RequestType::Uninstall:
65       if (context_->is_preload_rw_package.get())
66         SetupIsKeepRWData();
67       SetupIsForceRemoval();
68       context_->pkgid.set(pkgmgr_->GetRequestInfo());
69       context_->file_path.set(kStrEmpty);
70       break;
71     case RequestType::Reinstall:
72       context_->unpacked_dir_path.set(
73           context_->root_application_path.get() / "tmp" /
74           pkgmgr_->GetRequestInfo());
75       context_->pkgid.set(pkgmgr_->GetRequestInfo());
76       context_->file_path.set(kStrEmpty);
77       break;
78     case RequestType::Delta:
79       context_->unpacked_dir_path.set(kStrEmpty);
80       context_->pkgid.set(kStrEmpty);
81       context_->file_path.set(pkgmgr_->GetRequestInfo());
82       break;
83     case RequestType::Move:
84       context_->pkgid.set(pkgmgr_->GetRequestInfo());
85       context_->is_move_to_external.set(pkgmgr_->GetIsMoveToExternal());
86       break;
87     case RequestType::Recovery:
88       context_->file_path.set(pkgmgr_->GetRequestInfo());
89       context_->pkgid.set(kStrEmpty);
90       break;
91     case RequestType::MountInstall:
92     case RequestType::MountUpdate:
93       context_->file_path.set(pkgmgr_->GetRequestInfo());
94       context_->pkgid.set(kStrEmpty);
95       if (!pkgmgr_->GetTepPath().empty()) {
96         context_->tep_path.set(pkgmgr_->GetTepPath());
97         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
98       }
99       break;
100     case RequestType::ManifestPartialInstall:
101     case RequestType::ManifestPartialUpdate:
102       SetupIsPartialRW();
103     case RequestType::ManifestDirectInstall:
104     case RequestType::ManifestDirectUpdate: {
105       context_->pkgid.set(pkgmgr_->GetRequestInfo());
106       bf::path package_directory =
107           context_->root_application_path.get() / context_->pkgid.get();
108       bf::path xml_path =
109           bf::path(getUserManifestPath(context_->uid.get(),
110               context_->is_readonly_package.get()))
111           / bf::path(context_->pkgid.get());
112       xml_path += ".xml";
113       context_->unpacked_dir_path.set(package_directory);
114       context_->pkg_path.set(package_directory);
115       context_->xml_path.set(xml_path);
116       break;
117     }
118     case RequestType::ReadonlyUpdateInstall:
119       context_->file_path.set(pkgmgr_->GetRequestInfo());
120       context_->pkgid.set(kStrEmpty);
121       if (!pkgmgr_->GetTepPath().empty()) {
122         context_->tep_path.set(pkgmgr_->GetTepPath());
123         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
124       }
125       break;
126     case RequestType::ReadonlyUpdateUninstall: {
127       context_->pkgid.set(pkgmgr_->GetRequestInfo());
128       bf::path original_path =
129           bf::path(tzplatform_getenv(TZ_SYS_RO_APP)) / context_->pkgid.get();
130       context_->unpacked_dir_path.set(original_path);
131       context_->file_path.set(kStrEmpty);
132       break;
133     }
134     case RequestType::DisablePkg:
135     case RequestType::EnablePkg:
136       context_->pkgid.set(pkgmgr_->GetRequestInfo());
137       break;
138     case RequestType::MigrateExtImg: {
139       context_->pkgid.set(pkgmgr_->GetRequestInfo());
140       bf::path package_directory =
141           context_->root_application_path.get() / context_->pkgid.get();
142       context_->pkg_path.set(package_directory);
143       break;
144     }
145     default:
146       LOG(ERROR) <<
147           "Only installation, update and uninstallation is now supported";
148       return Status::CONFIG_ERROR;
149       break;
150   }
151
152   // Record recovery file
153   if (pkgmgr_->GetRequestType() == RequestType::Install ||
154       pkgmgr_->GetRequestType() == RequestType::Update ||
155       pkgmgr_->GetRequestType() == RequestType::Delta ||
156       pkgmgr_->GetRequestType() == RequestType::MountInstall ||
157       pkgmgr_->GetRequestType() == RequestType::MountUpdate) {
158     std::unique_ptr<recovery::RecoveryFile> recovery_file =
159         recovery::RecoveryFile::CreateRecoveryFileForPath(
160             GenerateTemporaryPath(
161                 context_->root_application_path.get() / "recovery"));
162     if (!recovery_file) {
163       LOG(ERROR) << "Failed to create recovery file";
164       return Status::CONFIG_ERROR;
165     }
166     recovery_file->set_type(pkgmgr_->GetRequestType());
167     if (!recovery_file->WriteAndCommitFileContent()) {
168       LOG(ERROR) << "Failed to write recovery file";
169       return Status::CONFIG_ERROR;
170     }
171     context_->recovery_info.set(RecoveryInfo(std::move(recovery_file)));
172   }
173
174   return Status::OK;
175 }
176
177 Step::Status StepConfigure::precheck() {
178   SetupIsPreloadRequest();
179   SetupIsPreloadRWRequest();
180   if (context_->is_readonly_package.get())
181     SetupIsNoRemoval();
182
183   bool is_readonly = context_->is_readonly_package.get();
184   bool is_preload_rw = context_->is_preload_rw_package.get();
185   if (is_readonly && is_preload_rw) {
186     LOG(ERROR) << "Conflict of preload request!";
187     return Status::ERROR;
188   }
189
190   uid_t uid = pkgmgr_->GetUid();
191   context_->uid.set(uid);
192   if (getuid() == 0)
193     return Status::OK;
194
195   boost::optional<uid_t> appfw_uid = GetUidByUserName(kAppFWUser);
196   if (!appfw_uid)
197     return Status::ERROR;
198
199   if (getuid() != *appfw_uid) {
200     LOG(ERROR) << "App-installer should not run with normal user!";
201     return Status::OPERATION_NOT_ALLOWED;
202   }
203
204   return Status::OK;
205 }
206
207 Step::Status StepConfigure::clean() {
208   // Clean up operations should not be covered by recovery
209   // as backup information is being lost during clean up
210   context_->recovery_info.get().recovery_file.reset();
211   return Status::OK;
212 }
213
214 bool StepConfigure::SetupRootAppDirectory() {
215   if (context_->root_application_path.get().empty()) {
216     std::string root_app_path =
217         GetRootAppPath(context_->is_readonly_package.get(),
218         context_->uid.get());
219     if (root_app_path.empty())
220       return false;
221
222     context_->root_application_path.set(root_app_path);
223   }
224   if (!boost::filesystem::exists(context_->root_application_path.get())) {
225     boost::system:: error_code error;
226     boost::filesystem::create_directories(
227         context_->root_application_path.get());
228     if (error) {
229       LOG(ERROR) << "Cannot create directory: "
230                  << context_->root_application_path.get();
231       return false;
232     }
233   }
234   LOG(INFO) << "AppDir(" << context_->root_application_path.get() << ")";
235   return true;
236 }
237
238 void StepConfigure::SetupRequestMode(uid_t uid) {
239   context_->request_mode.set(GetRequestMode(uid));
240 }
241
242 void StepConfigure::SetupRequestType() {
243   context_->request_type.set(pkgmgr_->GetRequestType());
244 }
245
246 void StepConfigure::SetupFileCreationMask() {
247   mode_t old_mask, new_mask;
248   old_mask = new_mask = 0;
249
250   switch (context_->request_mode.get()) {
251     case RequestMode::USER:
252       new_mask = 033;  // results in 744 privileges
253       break;
254     case RequestMode::GLOBAL:
255       new_mask = 022;  // results in 755 privileges
256       break;
257   }
258
259   old_mask = umask(new_mask);
260
261   LOG(INFO) << "Changed file creation mask from " << std::oct <<  old_mask
262       << " to " << std::oct <<  new_mask;
263 }
264
265 void StepConfigure::SetupIsPreloadRequest() {
266   context_->is_readonly_package.set(pkgmgr_->GetIsPreloadRequest());
267 }
268
269 void StepConfigure::SetupIsPreloadRWRequest() {
270   context_->is_preload_rw_package.set(pkgmgr_->GetIsPreloadRWRequest());
271 }
272
273 void StepConfigure::SetupIsForceRemoval() {
274   context_->force_remove.set(pkgmgr_->GetIsForceRemoval());
275 }
276
277 void StepConfigure::SetupIsNoRemoval() {
278   context_->no_remove.set(pkgmgr_->GetIsNoRemoval());
279 }
280
281 void StepConfigure::SetupIsKeepRWData() {
282   context_->keep_rwdata.set(pkgmgr_->GetIsKeepRWData());
283 }
284
285 void StepConfigure::SetupIsPartialRW() {
286   context_->partial_rw.set(pkgmgr_->GetIsPartialRW());
287 }
288
289 void StepConfigure::SetupDebugMode() {
290   context_->debug_mode.set(pkgmgr_->GetDebugMode());
291 }
292
293 }  // namespace configuration
294 }  // namespace common_installer