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