Block different type installation with same pkgid
[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 std::shared_ptr<AppQueryInterface> PkgMgrInterface::GetAppQueryInterface() {
156   return query_interface_;
157 }
158
159 RequestType PkgMgrInterface::GetRequestType(int idx) const {
160   // These type could be determined even if there are no query_interface_.
161   switch (pkgmgr_installer_get_request_type(pi_)) {
162     case PKGMGR_REQ_DISABLE_PKG:
163       return RequestType::DisablePkg;
164     case PKGMGR_REQ_ENABLE_PKG:
165       return RequestType::EnablePkg;
166     case PKGMGR_REQ_MIGRATE_EXTIMG:
167       return RequestType::MigrateExtImg;
168     case PKGMGR_REQ_RECOVER_DB:
169       return RequestType::RecoverDB;
170     case PKGMGR_REQ_REINSTALL:
171       return RequestType::Reinstall;
172     case PKGMGR_REQ_RECOVER:
173       return RequestType::Recovery;
174     case PKGMGR_REQ_MOVE:
175       return RequestType::Move;
176   }
177
178   std::shared_ptr<AppQueryInterface> query_interface = query_interface_;
179   if (!query_interface) {
180     auto it = query_interface_map_.find(idx);
181     if (it == query_interface_map_.end())
182       return RequestType::Unknown;
183     query_interface = it->second;
184   }
185
186   if (!is_app_installed_) {
187     is_app_installed_ =
188         query_interface->IsPkgInstalled(GetRequestInfo(idx), GetUid());
189   }
190   switch (pkgmgr_installer_get_request_type(pi_)) {
191     case PKGMGR_REQ_UPGRADE :
192     case PKGMGR_REQ_INSTALL : {
193       auto request_info = GetRequestInfo(idx);
194       if (request_info.empty())
195         return RequestType::Unknown;
196       bool is_delta = IsDeltaPkg(request_info);
197       if (!is_app_installed_.get()) {
198         if (is_delta) {
199           LOG(ERROR) << "Package is not installed. "
200                         "Cannot update from delta package";
201           return RequestType::Unknown;
202         } else {
203           return RequestType::Install;
204         }
205       } else {
206         if (is_delta) {
207           return RequestType::Delta;
208         } else {
209           std::string pkgid = query_interface->GetPkgId(GetRequestInfo(idx));
210           uid_t uid = GetUid();
211           ci::PkgQueryInterface pkg_query(pkgid, uid);
212           if (!GetIsPreloadRequest() &&
213               pkg_query.IsReadonlyPackage() &&
214               !pkg_query.IsUpdatedPackage()) {
215             return RequestType::ReadonlyUpdateInstall;
216           } else if (CheckIfAppFilesExists(pkgid, uid,
217               pkg_query.IsReadonlyPackage())
218                   ) {
219             return RequestType::Update;
220           } else {
221             RequestMode request_mode = GetRequestMode(uid);
222             UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
223             return RequestType::Install;
224           }
225         }
226       }
227     }
228     case PKGMGR_REQ_UNINSTALL: {
229       std::string pkgid = GetRequestInfo(idx);
230       uid_t uid = GetUid();
231       ci::PkgQueryInterface pkg_query(pkgid, uid);
232       if (pkg_query.IsSystemPackage() &&
233           pkg_query.IsUpdatedPackage() &&
234           pkg_query.IsRemovablePackage())
235         return RequestType::ReadonlyUpdateUninstall;
236       else if (GetIsPreloadRequest() && GetIsPartialRW())
237         return RequestType::PartialUninstall;
238       else
239         return RequestType::Uninstall;
240     }
241     case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
242       if (!is_app_installed_.get()) {
243         if (GetIsPreloadRequest() && GetIsPartialRW())
244           return RequestType::ManifestPartialInstall;
245         else
246           return RequestType::ManifestDirectInstall;
247       } else {
248         if (GetIsPreloadRequest() && GetIsPartialRW())
249           return RequestType::ManifestPartialUpdate;
250         else
251           return RequestType::ManifestDirectUpdate;
252       }
253     case PKGMGR_REQ_MOUNT_INSTALL: {
254       if (!is_app_installed_.get()) {
255         return RequestType::MountInstall;
256       } else {
257         std::string pkgid = query_interface->GetPkgId(GetRequestInfo(idx));
258         uid_t uid = GetUid();
259         ci::PkgQueryInterface pkg_query(pkgid, uid);
260         if (CheckIfAppFilesExists(pkgid, uid, pkg_query.IsReadonlyPackage())) {
261           return RequestType::MountUpdate;
262         } else {
263           RequestMode request_mode = GetRequestMode(uid);
264           UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
265           return RequestType::MountInstall;
266         }
267       }
268     }
269     default:
270       return RequestType::Unknown;
271   }
272 }
273
274 uid_t PkgMgrInterface::GetUid() const {
275   return pkgmgr_installer_get_uid(pi_);
276 }
277
278 std::string PkgMgrInterface::GetRequestInfo(int idx) const {
279   const char* request_info = pkgmgr_installer_get_request_info_at(pi_, idx);
280   if (!request_info)
281     return {};
282   else
283     return request_info;
284 }
285
286 boost::filesystem::path PkgMgrInterface::GetTepPath() const {
287   if (pkgmgr_installer_get_tep_path(pi_) == nullptr)
288     return boost::filesystem::path("");
289   else
290     return boost::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
291 }
292
293 bool PkgMgrInterface::GetIsTepMove() const {
294   return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
295 }
296
297 bool PkgMgrInterface::GetIsMoveToExternal() const {
298   return (pkgmgr_installer_get_move_type(pi_) == 1);
299 }
300
301 int PkgMgrInterface::GetMoveType() const {
302   return pkgmgr_installer_get_move_type(pi_);
303 }
304
305 bool PkgMgrInterface::GetIsPreloadRequest() const {
306   return (pkgmgr_installer_get_is_preload(pi_) == 1);
307 }
308
309 bool PkgMgrInterface::GetIsPreloadRWRequest() const {
310   return (pkgmgr_installer_get_is_preload_rw(pi_) == 1);
311 }
312
313 bool PkgMgrInterface::GetIsKeepRWData() const {
314   return (pkgmgr_installer_get_keep_rwdata(pi_) == 1);
315 }
316
317 bool PkgMgrInterface::GetIsPartialRW() const {
318   return (pkgmgr_installer_get_partial_rw(pi_) == 1);
319 }
320
321 std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
322   if (!pkgmgr_installer_interface_->ShouldCreateSignal())
323     return nullptr;
324   return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_));
325 }
326
327 bool PkgMgrInterface::GetIsForceRemoval() const {
328   return (pkgmgr_installer_get_force_removal(pi_) == 1);
329 }
330
331 bool PkgMgrInterface::GetIsNoRemoval() const {
332   return (pkgmgr_installer_get_no_removal(pi_) == 1);
333 }
334
335 bool PkgMgrInterface::GetDebugMode() const {
336   return (pkgmgr_installer_get_debug_mode(pi_) == 1);
337 }
338
339 bool PkgMgrInterface::GetIsSkipCheckReference() const {
340   return (pkgmgr_installer_get_skip_check_reference(pi_) == 1);
341 }
342
343 bool PkgMgrInterface::GetSkipOptimization() const {
344   return (pkgmgr_installer_get_skip_optimization(pi_) == 1);
345 }
346
347 int PkgMgrInterface::GetRequestInfoCount() const {
348   return pkgmgr_installer_get_request_info_count(pi_);
349 }
350
351 bool PkgMgrInterface::GetRecoveryCleanup() const {
352   return (pkgmgr_installer_get_recovery_cleanup(pi_) == 1);
353 }
354
355 }  // namespace common_installer