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