affb09d986be0098274c7fc5f1d24928e1312195
[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/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     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   // Set target uid as tizenglobalapp if admin user's request
108   if (IsAdminUser(pkgmgr_installer_get_uid(pi_))) {
109     result = pkgmgr_installer_set_uid(pi_, kGlobalUserUid);
110     if (result) {
111       LOG(ERROR) << "Failed to set global uid";
112       return -1;
113     }
114   }
115
116   return 0;
117 }
118
119 PkgMgrInterface::~PkgMgrInterface() {
120   if (pi_)
121     pkgmgr_installer_free(pi_);
122 }
123
124 RequestType PkgMgrInterface::GetRequestType() const {
125   if (!query_interface_)
126     return RequestType::Unknown;
127
128   if (!is_app_installed_) {
129     is_app_installed_ =
130         query_interface_->IsPkgInstalled(GetRequestInfo(), GetUid());
131   }
132   switch (pkgmgr_installer_get_request_type(pi_)) {
133     case PKGMGR_REQ_INSTALL : {
134       auto request_info = GetRequestInfo();
135       if (request_info.empty())
136         return RequestType::Unknown;
137       bool is_delta = IsDeltaPkg(request_info);
138       if (!is_app_installed_.get()) {
139         if (is_delta) {
140           LOG(ERROR) << "Package is not installed. "
141                         "Cannot update from delta package";
142           return RequestType::Unknown;
143         } else {
144           return RequestType::Install;
145         }
146       } else {
147         if (is_delta) {
148           return RequestType::Delta;
149         } else {
150           std::string pkgid = query_interface_->GetPkgId(GetRequestInfo());
151           uid_t uid = GetUid();
152           ci::PkgQueryInterface pkg_query(pkgid, uid);
153           if (!GetIsPreloadRequest() &&
154               pkg_query.IsReadonlyPackage() &&
155               !pkg_query.IsUpdatedPackage()) {
156             return RequestType::ReadonlyUpdateInstall;
157           } else if (CheckIfAppFilesExists(pkgid, uid,
158               pkg_query.IsReadonlyPackage())
159                   ) {
160             return RequestType::Update;
161           } else {
162             RequestMode request_mode = GetRequestMode(uid);
163             UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
164             return RequestType::Install;
165           }
166         }
167       }
168     }
169     case PKGMGR_REQ_UNINSTALL: {
170       std::string pkgid = GetRequestInfo();
171       uid_t uid = GetUid();
172       ci::PkgQueryInterface pkg_query(pkgid, uid);
173       if (pkg_query.IsSystemPackage() &&
174           pkg_query.IsUpdatedPackage() &&
175           pkg_query.IsRemovablePackage())
176         return RequestType::ReadonlyUpdateUninstall;
177       else if (GetIsPreloadRequest() && GetIsPartialRW())
178         return RequestType::PartialUninstall;
179       else
180         return RequestType::Uninstall;
181     }
182     case PKGMGR_REQ_REINSTALL:
183       return RequestType::Reinstall;
184     case PKGMGR_REQ_RECOVER:
185       return RequestType::Recovery;
186     case PKGMGR_REQ_MOVE:
187       return RequestType::Move;
188     case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
189       if (!is_app_installed_.get()) {
190         if (GetIsPreloadRequest() && GetIsPartialRW())
191           return RequestType::ManifestPartialInstall;
192         else
193           return RequestType::ManifestDirectInstall;
194       } else {
195         if (GetIsPreloadRequest() && GetIsPartialRW())
196           return RequestType::ManifestPartialUpdate;
197         else
198           return RequestType::ManifestDirectUpdate;
199       }
200     case PKGMGR_REQ_MOUNT_INSTALL:
201       if (!is_app_installed_.get())
202         return RequestType::MountInstall;
203       else
204         return RequestType::MountUpdate;
205     case PKGMGR_REQ_DISABLE_PKG:
206       return RequestType::DisablePkg;
207     case PKGMGR_REQ_ENABLE_PKG:
208       return RequestType::EnablePkg;
209     case PKGMGR_REQ_MIGRATE_EXTIMG:
210       return RequestType::MigrateExtImg;
211     case PKGMGR_REQ_RECOVER_DB:
212       return RequestType::RecoverDB;
213     default:
214       return RequestType::Unknown;
215   }
216 }
217
218 uid_t PkgMgrInterface::GetUid() const {
219   return pkgmgr_installer_get_uid(pi_);
220 }
221
222 std::string PkgMgrInterface::GetRequestInfo() const {
223   const char* request_info = pkgmgr_installer_get_request_info(pi_);
224   if (!request_info)
225     return {};
226   else
227     return request_info;
228 }
229
230 boost::filesystem::path PkgMgrInterface::GetTepPath() const {
231   if (pkgmgr_installer_get_tep_path(pi_) == nullptr)
232     return boost::filesystem::path("");
233   else
234     return boost::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
235 }
236
237 bool PkgMgrInterface::GetIsTepMove() const {
238   return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
239 }
240
241 bool PkgMgrInterface::GetIsMoveToExternal() const {
242   return (pkgmgr_installer_get_move_type(pi_) == 1);
243 }
244
245 int PkgMgrInterface::GetMoveType() const {
246   return pkgmgr_installer_get_move_type(pi_);
247 }
248
249 bool PkgMgrInterface::GetIsPreloadRequest() const {
250   return (pkgmgr_installer_get_is_preload(pi_) == 1);
251 }
252
253 bool PkgMgrInterface::GetIsPreloadRWRequest() const {
254   return (pkgmgr_installer_get_is_preload_rw(pi_) == 1);
255 }
256
257 bool PkgMgrInterface::GetIsKeepRWData() const {
258   return (pkgmgr_installer_get_keep_rwdata(pi_) == 1);
259 }
260
261 bool PkgMgrInterface::GetIsPartialRW() const {
262   return (pkgmgr_installer_get_partial_rw(pi_) == 1);
263 }
264
265 std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
266   if (!pkgmgr_installer_interface_->ShouldCreateSignal())
267     return nullptr;
268   return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_));
269 }
270
271 bool PkgMgrInterface::GetIsForceRemoval() const {
272   return (pkgmgr_installer_get_force_removal(pi_) == 1);
273 }
274
275 bool PkgMgrInterface::GetIsNoRemoval() const {
276   return (pkgmgr_installer_get_no_removal(pi_) == 1);
277 }
278
279 bool PkgMgrInterface::GetDebugMode() const {
280   return (pkgmgr_installer_get_debug_mode(pi_) == 1);
281 }
282
283 bool PkgMgrInterface::GetIsSkipCheckReference() const {
284   return (pkgmgr_installer_get_skip_check_reference(pi_) == 1);
285 }
286
287 bool PkgMgrInterface::GetSkipOptimization() const {
288   return (pkgmgr_installer_get_skip_optimization(pi_) == 1);
289 }
290
291 }  // namespace common_installer