Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / step / configuration / step_parse_preload.cc
1 // Copyright (c) 2016 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_parse_preload.h"
6
7 #include <pkgmgr-info.h>
8 #include <unistd.h>
9
10 #include <cstring>
11 #include <cstdio>
12 #include <string>
13
14 #include "common/pkgmgr_interface.h"
15 #include "common/utils/pkgmgr_query.h"
16 #include "common/utils/file_util.h"
17
18 namespace ci = common_installer;
19
20 namespace common_installer {
21 namespace configuration {
22
23 StepParsePreload::StepParsePreload(ci::InstallerContext* context)
24     : Step(context), req_type_(RequestType::Unknown), pkg_query_(nullptr) {
25 }
26
27 ci::Step::Status StepParsePreload::AdjustReadonly() {
28   if (context_->manifest_data.get()->readonly &&
29       strlen(context_->manifest_data.get()->readonly) != 0)
30     return Status::OK;
31
32   free(context_->manifest_data.get()->readonly);
33
34   if (context_->is_readonly_package.get()) {
35     context_->manifest_data.get()->readonly = strdup("true");
36     if (getuid() != 0 && req_type_ != RequestType::ReadonlyUpdateUninstall) {
37       LOG(ERROR) << "You're not authorized to install readonly app: "
38           << context_->pkgid.get().c_str();
39       return Status::OPERATION_NOT_ALLOWED;
40     }
41   } else {
42     context_->manifest_data.get()->readonly = strdup("false");
43   }
44
45   if (!context_->manifest_data.get()->readonly) {
46     LOG(ERROR) << "Out of memory";
47     return Status::ERROR;
48   }
49
50   return Status::OK;
51 }
52
53 ci::Step::Status StepParsePreload::AdjustPreload() {
54   if (context_->manifest_data.get()->preload &&
55       strlen(context_->manifest_data.get()->preload) != 0)
56     return Status::OK;
57
58   free(context_->manifest_data.get()->preload);
59   if (req_type_ == RequestType::Update ||
60       req_type_ == RequestType::Delta ||
61       req_type_ == RequestType::MountUpdate ||
62       req_type_ == RequestType::ReadonlyUpdateInstall) {
63     // In case of update, keep preload value
64     bool is_preload = pkg_query_->IsPreloadPackage();
65     context_->manifest_data.get()->preload =
66         strdup(is_preload ? "true" : "false");
67   } else if (req_type_ == RequestType::ManifestDirectUpdate &&
68       pkg_query_->IsPreloadPackage() &&
69       !context_->is_readonly_package.get()) {
70     context_->manifest_data.get()->preload = strdup("true");
71   } else {
72     if (context_->is_readonly_package.get() ||
73         context_->is_preload_rw_package.get())
74       context_->manifest_data.get()->preload = strdup("true");
75     else
76       context_->manifest_data.get()->preload = strdup("false");
77   }
78
79   if (!context_->manifest_data.get()->preload) {
80     LOG(ERROR) << "Out of memory";
81     return Status::ERROR;
82   }
83
84   return Status::OK;
85 }
86
87 ci::Step::Status StepParsePreload::AdjustRemovable() {
88   // In case of update, keep removable value
89   if (req_type_ == RequestType::Update ||
90       req_type_ == RequestType::Delta ||
91       req_type_ == RequestType::MountUpdate) {
92     bool is_removable = pkg_query_->IsRemovablePackage();
93     context_->manifest_data.get()->removable =
94         strdup(is_removable ? "true" : "false");
95     if (!context_->manifest_data.get()->removable) {
96       LOG(ERROR) << "Out of memoery";
97       return Status::ERROR;
98     }
99     return Status::OK;
100   }
101
102   const char* removable_val = context_->manifest_data.get()->removable;
103   if (removable_val && strlen(removable_val) != 0)
104     return Status::OK;
105
106   free(context_->manifest_data.get()->removable);
107   if (context_->no_remove.get() ||
108       context_->is_readonly_package.get())
109     context_->manifest_data.get()->removable = strdup("false");
110   else
111     context_->manifest_data.get()->removable = strdup("true");
112
113   if (!context_->manifest_data.get()->removable) {
114     LOG(ERROR) << "Out of memoery";
115     return Status::ERROR;
116   }
117
118   return Status::OK;
119 }
120
121 bool StepParsePreload::ValidateAttrs() {
122   bool is_readonly =
123       (strcmp(context_->manifest_data.get()->readonly, "true") == 0);
124   bool is_preload =
125       (strcmp(context_->manifest_data.get()->preload, "true") == 0);
126   bool is_removable =
127       (strcmp(context_->manifest_data.get()->removable, "true") == 0);
128
129   if (is_readonly && !is_preload) {
130     LOG(ERROR) << "invalid preload attribute, readonly but not preload!";
131     return false;
132   }
133
134   if (is_readonly && is_removable) {
135     LOG(ERROR) << "invalid preload attribute, readonly but removable!";
136     return false;
137   }
138
139   if (!is_preload && !is_removable) {
140     LOG(ERROR) << "invalid preload attribute, no preload but not removable!";
141     return false;
142   }
143
144   return true;
145 }
146
147 ci::Step::Status StepParsePreload::AdjustUpdate() {
148   manifest_x* manifest = context_->manifest_data.get();
149
150   free(manifest->update);
151   // set update false when ReadonlyUpdateUninstall
152   if (req_type_ == RequestType::ReadonlyUpdateUninstall)
153     manifest->update = strdup("false");
154   // set update true if package is updated preload package
155   else if (pkg_query_->IsUpdatedPackage())
156     manifest->update = strdup("true");
157   // set update true when update non-removable preload package
158   else if (pkg_query_->IsPreloadPackage() &&
159       (req_type_ == RequestType::Update ||
160        req_type_ == RequestType::Delta ||
161        req_type_ == RequestType::MountUpdate ||
162        req_type_ == RequestType::ReadonlyUpdateInstall ||
163        (req_type_ == RequestType::ManifestDirectUpdate &&
164            !context_->is_readonly_package.get())))
165     manifest->update = strdup("true");
166   else
167     manifest->update = strdup("false");
168
169   if (!manifest->update) {
170     LOG(ERROR) << "Out of memory";
171     return Status::ERROR;
172   }
173
174   return Status::OK;
175 }
176
177 ci::Step::Status StepParsePreload::AdjustSystem() {
178   manifest_x* manifest = context_->manifest_data.get();
179
180   free(manifest->system);
181   // set system true when install RO preload package
182   if (context_->is_readonly_package.get() ||
183       (manifest->readonly && !strcmp(manifest->readonly, "true")))
184     manifest->system = strdup("true");
185   // set system true when install non-removable RW preload package
186   else if (
187       (context_->is_preload_rw_package.get() ||
188           (manifest->preload && !strcmp(manifest->preload, "true"))) &&
189       (context_->no_remove.get() ||
190           (manifest->removable && !strcmp(manifest->removable, "false"))))
191     manifest->system = strdup("true");
192   // set system false when update non-removable RW preload package
193   else if (pkg_query_->IsSystemPackage() &&
194       !pkg_query_->IsReadonlyPackage() &&
195       !pkg_query_->IsUpdatedPackage())
196     manifest->system = strdup("false");
197   // set system true when update RO preload package
198   else if (req_type_ == RequestType::ReadonlyUpdateInstall ||
199       req_type_ == RequestType::ReadonlyUpdateUninstall ||
200       pkg_query_->IsSystemPackage())
201     manifest->system = strdup("true");
202   else
203     manifest->system = strdup("false");
204
205   if (!manifest->system) {
206     LOG(ERROR) << "Out of memory";
207     return Status::ERROR;
208   }
209
210   return Status::OK;
211 }
212
213 ci::Step::Status StepParsePreload::AdjustOldManifest() {
214   manifest_x* old_manifest = context_->old_manifest_data.get();
215   if (!old_manifest)
216     return Status::OK;
217
218   free(old_manifest->system);
219   // keep system value for undo operation
220   if (pkg_query_->IsSystemPackage())
221     old_manifest->system = strdup("true");
222   else
223     old_manifest->system = strdup("false");
224   if (!old_manifest->system) {
225     LOG(ERROR) << "Out of memory";
226     return Status::ERROR;
227   }
228
229   free(old_manifest->update);
230   // keep update value for undo operation
231   if (pkg_query_->IsUpdatedPackage())
232     old_manifest->update = strdup("true");
233   else
234     old_manifest->update = strdup("false");
235   if (!old_manifest->update) {
236     LOG(ERROR) << "Out of memory";
237     return Status::ERROR;
238   }
239
240   return Status::OK;
241 }
242
243 ci::Step::Status StepParsePreload::process() {
244   req_type_ = context_->request_type.get();
245   pkg_query_.reset(
246       new PkgQueryInterface(context_->pkgid.get(), context_->uid.get()));
247
248   Status ret = AdjustReadonly();
249   if (ret != Status::OK)
250     return ret;
251
252   ret = AdjustPreload();
253   if (ret != Status::OK)
254     return ret;
255
256   ret = AdjustRemovable();
257   if (ret != Status::OK)
258     return ret;
259
260   if (!ValidateAttrs())
261     return Status::MANIFEST_ERROR;
262
263   ret = AdjustUpdate();
264   if (ret != Status::OK)
265     return ret;
266
267   ret = AdjustSystem();
268   if (ret != Status::OK)
269     return ret;
270
271   ret = AdjustOldManifest();
272   if (ret != Status::OK)
273     return ret;
274
275   return Status::OK;
276 }
277
278 }  // namespace configuration
279 }  // namespace common_installer