Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / pkgmgr_interface.cc
1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache 2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "common/pkgmgr_interface.h"
6
7 #include <tzplatform_config.h>
8
9 #include <memory>
10 #include <string>
11 #include <filesystem>
12 #include <fstream>
13 #include <optional>
14
15 #include "common/app_query_interface.h"
16 #include "common/utils/pkgmgr_query.h"
17 #include "common/pkgmgr_signal.h"
18 #include "common/pkgmgr_registration.h"
19 #include "common/utils/file_util.h"
20 #include "common/utils/manifest_util.h"
21 #include "common/utils/user_util.h"
22
23 namespace fs = std::filesystem;
24 namespace ci = common_installer;
25
26 namespace {
27
28 const char kDeltaFileExtension[] = ".delta";
29 const char kDeltaFileName[] = "delta_info.xml";
30 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
31
32 bool CheckIfAppFilesExists(const std::string& pkgid,
33                            uid_t uid,
34                            bool is_readonly) {
35   return fs::exists(ci::GetManifestLocation(pkgid,
36               uid, is_readonly));
37 }
38
39 bool IsDeltaPkg(const std::string& path) {
40   bool is_delta = false;
41   if (!ci::CheckPathInZipArchive(path.c_str(), kDeltaFileName, &is_delta)) {
42     LOG(ERROR) << "Failed to check delta package";
43     return false;
44   }
45
46   if (!is_delta) {
47     std::string extension = fs::path(path).extension().string();
48     if (extension == kDeltaFileExtension)
49       is_delta = true;
50   }
51
52   return is_delta;
53 }
54
55 }  // namespace
56
57 namespace common_installer {
58
59 bool PkgmgrInstaller::CreatePkgMgrInstaller(pkgmgr_installer** installer,
60                              InstallationMode* mode) {
61   *installer = pkgmgr_installer_new();
62   if (!*installer) {
63     LOG(WARNING) << "Cannot create pkgmgr_installer object. Will try offline";
64     // We assume offline mode if we cannot connect to pkgmgr-server
65     *installer = pkgmgr_installer_offline_new();
66     if (!*installer) {
67       return false;
68     }
69     *mode = InstallationMode::OFFLINE;
70   } else {
71     *mode = InstallationMode::ONLINE;
72   }
73   return true;
74 }
75
76 bool PkgmgrInstaller::ShouldCreateSignal() const {
77   return true;
78 }
79
80 PkgMgrPtr PkgMgrInterface::Create(int argc, char** argv,
81     PkgmgrInstallerInterface* pkgmgr_installer_interface,
82     std::shared_ptr<AppQueryInterface> interface) {
83   PkgMgrPtr instance(new PkgMgrInterface(pkgmgr_installer_interface,
84                                          interface));
85   int result = instance->InitInternal(argc, argv);
86   if (result != 0)
87     return nullptr;
88
89   return instance;
90 }
91
92 int PkgMgrInterface::InitInternal(int argc, char** argv) {
93   if (!pkgmgr_installer_interface_->CreatePkgMgrInstaller(&pi_,
94                                                           &install_mode_)) {
95     LOG(ERROR) << "Cannot create pkgmgr_installer object. Aborting.";
96     return -1;
97   }
98
99   int result = pkgmgr_installer_receive_request(pi_, argc, argv);
100   if (result) {
101     LOG(ERROR) << "Cannot receive request. Invalid arguments?";
102     // no need to free pkgmgr_installer here. it will be freed in DTOR.
103     return -1;
104   }
105
106   std::optional<bool> is_admin_user =
107       IsAdminUser(pkgmgr_installer_get_uid(pi_));
108   if (!is_admin_user) {
109     LOG(ERROR) << "Cannot get admin user info. Aborting.";
110     return -1;
111   }
112
113   // Set target uid as tizenglobalapp if admin user's request
114   if (*is_admin_user) {
115     result = pkgmgr_installer_set_uid(pi_, kGlobalUserUid);
116     if (result) {
117       LOG(ERROR) << "Failed to set global uid";
118       return -1;
119     }
120   }
121
122   return 0;
123 }
124
125 PkgMgrInterface::~PkgMgrInterface() {
126   if (pi_)
127     pkgmgr_installer_free(pi_);
128 }
129
130 // method name?
131 bool PkgMgrInterface::SetAppQueryInterface(int idx) {
132   // reset this flag to processing new package
133   is_app_installed_.reset();
134
135   auto it = query_interface_map_.find(idx);
136   if (it == query_interface_map_.end()) {
137     if (!query_interface_) {
138       LOG(ERROR) << "Cannot find query interface for index(" << idx << ")";
139       return false;
140     } else {
141       // using legacy query interface (for single pkg installer)
142       return true;
143     }
144   }
145   query_interface_ = it->second;
146   return true;
147 }
148
149 void PkgMgrInterface::AddAppQueryInterface(
150     int idx, std::shared_ptr<AppQueryInterface> interface) {
151   query_interface_map_.emplace(idx, interface);
152 }
153
154 std::shared_ptr<AppQueryInterface> PkgMgrInterface::GetAppQueryInterface() {
155   return query_interface_;
156 }
157
158 RequestType PkgMgrInterface::GetRequestType(int idx) const {
159   // These type could be determined even if there are no query_interface_.
160   switch (pkgmgr_installer_get_request_type(pi_)) {
161     case PKGMGR_REQ_DISABLE_PKG:
162       return RequestType::DisablePkg;
163     case PKGMGR_REQ_ENABLE_PKG:
164       return RequestType::EnablePkg;
165     case PKGMGR_REQ_MIGRATE_EXTIMG:
166       return RequestType::MigrateExtImg;
167     case PKGMGR_REQ_RECOVER_DB:
168       return RequestType::RecoverDB;
169     case PKGMGR_REQ_REINSTALL:
170       return RequestType::Reinstall;
171     case PKGMGR_REQ_RECOVER:
172       return RequestType::Recovery;
173     case PKGMGR_REQ_MOVE:
174       return RequestType::Move;
175   }
176
177   std::shared_ptr<AppQueryInterface> query_interface = query_interface_;
178   if (!query_interface) {
179     auto it = query_interface_map_.find(idx);
180     if (it == query_interface_map_.end())
181       return RequestType::Unknown;
182     query_interface = it->second;
183   }
184
185   if (!is_app_installed_) {
186     is_app_installed_ =
187         query_interface->IsPkgInstalled(GetRequestInfo(idx), GetUid());
188   }
189   switch (pkgmgr_installer_get_request_type(pi_)) {
190     case PKGMGR_REQ_UPGRADE :
191     case PKGMGR_REQ_INSTALL : {
192       auto request_info = GetRequestInfo(idx);
193       if (request_info.empty())
194         return RequestType::Unknown;
195       bool is_delta = IsDeltaPkg(request_info);
196       if (!is_app_installed_.value()) {
197         if (is_delta) {
198           LOG(ERROR) << "Package is not installed. "
199                         "Cannot update from delta package";
200           return RequestType::Unknown;
201         } else {
202           return RequestType::Install;
203         }
204       } else {
205         if (is_delta) {
206           return RequestType::Delta;
207         } else {
208           std::string pkgid = query_interface->GetPkgId(GetRequestInfo(idx));
209           uid_t uid = GetUid();
210           ci::PkgQueryInterface pkg_query(pkgid, uid);
211           if (!GetIsPreloadRequest() &&
212               pkg_query.IsReadonlyPackage() &&
213               !pkg_query.IsUpdatedPackage()) {
214             return RequestType::ReadonlyUpdateInstall;
215           } else if (CheckIfAppFilesExists(pkgid, uid,
216               pkg_query.IsReadonlyPackage())
217                   ) {
218             return RequestType::Update;
219           } else {
220             RequestMode request_mode = GetRequestMode(uid);
221             UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
222             return RequestType::Install;
223           }
224         }
225       }
226     }
227     case PKGMGR_REQ_UNINSTALL: {
228       std::string pkgid = GetRequestInfo(idx);
229       uid_t uid = GetUid();
230       ci::PkgQueryInterface pkg_query(pkgid, uid);
231       if (pkg_query.IsSystemPackage() &&
232           pkg_query.IsUpdatedPackage() &&
233           pkg_query.IsRemovablePackage())
234         return RequestType::ReadonlyUpdateUninstall;
235       else if (GetIsPreloadRequest() && GetIsPartialRW())
236         return RequestType::PartialUninstall;
237       else
238         return RequestType::Uninstall;
239     }
240     case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
241       if (!is_app_installed_.value()) {
242         if (GetIsPreloadRequest() && GetIsPartialRW())
243           return RequestType::ManifestPartialInstall;
244         else
245           return RequestType::ManifestDirectInstall;
246       } else {
247         if (GetIsPreloadRequest() && GetIsPartialRW())
248           return RequestType::ManifestPartialUpdate;
249         else
250           return RequestType::ManifestDirectUpdate;
251       }
252     case PKGMGR_REQ_MOUNT_INSTALL: {
253       if (!is_app_installed_.value()) {
254         return RequestType::MountInstall;
255       } else {
256         std::string pkgid = query_interface->GetPkgId(GetRequestInfo(idx));
257         uid_t uid = GetUid();
258         ci::PkgQueryInterface pkg_query(pkgid, uid);
259         if (CheckIfAppFilesExists(pkgid, uid, pkg_query.IsReadonlyPackage())) {
260           return RequestType::MountUpdate;
261         } else {
262           RequestMode request_mode = GetRequestMode(uid);
263           UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
264           return RequestType::MountInstall;
265         }
266       }
267     }
268     default:
269       return RequestType::Unknown;
270   }
271 }
272
273 uid_t PkgMgrInterface::GetUid() const {
274   return pkgmgr_installer_get_uid(pi_);
275 }
276
277 std::string PkgMgrInterface::GetRequestInfo(int idx) const {
278   const char* request_info = pkgmgr_installer_get_request_info_at(pi_, idx);
279   if (!request_info)
280     return {};
281   else
282     return request_info;
283 }
284
285 std::filesystem::path PkgMgrInterface::GetTepPath() const {
286   if (pkgmgr_installer_get_tep_path(pi_) == nullptr)
287     return std::filesystem::path("");
288   else
289     return std::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
290 }
291
292 bool PkgMgrInterface::GetIsTepMove() const {
293   return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
294 }
295
296 bool PkgMgrInterface::GetIsMoveToExternal() const {
297   return (pkgmgr_installer_get_move_type(pi_) == 1);
298 }
299
300 int PkgMgrInterface::GetMoveType() const {
301   return pkgmgr_installer_get_move_type(pi_);
302 }
303
304 bool PkgMgrInterface::GetIsPreloadRequest() const {
305   return (pkgmgr_installer_get_is_preload(pi_) == 1);
306 }
307
308 bool PkgMgrInterface::GetIsPreloadRWRequest() const {
309   return (pkgmgr_installer_get_is_preload_rw(pi_) == 1);
310 }
311
312 bool PkgMgrInterface::GetIsKeepRWData() const {
313   return (pkgmgr_installer_get_keep_rwdata(pi_) == 1);
314 }
315
316 bool PkgMgrInterface::GetIsPartialRW() const {
317   return (pkgmgr_installer_get_partial_rw(pi_) == 1);
318 }
319
320 std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
321   if (!pkgmgr_installer_interface_->ShouldCreateSignal())
322     return nullptr;
323   return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_));
324 }
325
326 bool PkgMgrInterface::GetIsForceRemoval() const {
327   return (pkgmgr_installer_get_force_removal(pi_) == 1);
328 }
329
330 bool PkgMgrInterface::GetIsNoRemoval() const {
331   return (pkgmgr_installer_get_no_removal(pi_) == 1);
332 }
333
334 bool PkgMgrInterface::GetDebugMode() const {
335   return (pkgmgr_installer_get_debug_mode(pi_) == 1);
336 }
337
338 bool PkgMgrInterface::GetIsSkipCheckReference() const {
339   return (pkgmgr_installer_get_skip_check_reference(pi_) == 1);
340 }
341
342 bool PkgMgrInterface::GetSkipOptimization() const {
343   return (pkgmgr_installer_get_skip_optimization(pi_) == 1);
344 }
345
346 int PkgMgrInterface::GetRequestInfoCount() const {
347   return pkgmgr_installer_get_request_info_count(pi_);
348 }
349
350 bool PkgMgrInterface::GetRecoveryCleanup() const {
351   return (pkgmgr_installer_get_recovery_cleanup(pi_) == 1);
352 }
353
354 }  // namespace common_installer