Refine sending pkgmgr signal for recovery
[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     default:
212       return RequestType::Unknown;
213   }
214 }
215
216 uid_t PkgMgrInterface::GetUid() const {
217   return pkgmgr_installer_get_uid(pi_);
218 }
219
220 std::string PkgMgrInterface::GetRequestInfo() const {
221   const char* request_info = pkgmgr_installer_get_request_info(pi_);
222   if (!request_info)
223     return {};
224   else
225     return request_info;
226 }
227
228 boost::filesystem::path PkgMgrInterface::GetTepPath() const {
229   if (pkgmgr_installer_get_tep_path(pi_) == nullptr)
230     return boost::filesystem::path("");
231   else
232     return boost::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
233 }
234
235 bool PkgMgrInterface::GetIsTepMove() const {
236   return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
237 }
238
239 bool PkgMgrInterface::GetIsMoveToExternal() const {
240   return (pkgmgr_installer_get_move_type(pi_) == 1);
241 }
242
243 int PkgMgrInterface::GetMoveType() const {
244   return pkgmgr_installer_get_move_type(pi_);
245 }
246
247 bool PkgMgrInterface::GetIsPreloadRequest() const {
248   return (pkgmgr_installer_get_is_preload(pi_) == 1);
249 }
250
251 bool PkgMgrInterface::GetIsPreloadRWRequest() const {
252   return (pkgmgr_installer_get_is_preload_rw(pi_) == 1);
253 }
254
255 bool PkgMgrInterface::GetIsKeepRWData() const {
256   return (pkgmgr_installer_get_keep_rwdata(pi_) == 1);
257 }
258
259 bool PkgMgrInterface::GetIsPartialRW() const {
260   return (pkgmgr_installer_get_partial_rw(pi_) == 1);
261 }
262
263 std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
264   if (!pkgmgr_installer_interface_->ShouldCreateSignal())
265     return nullptr;
266   return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_));
267 }
268
269 bool PkgMgrInterface::GetIsForceRemoval() const {
270   return (pkgmgr_installer_get_force_removal(pi_) == 1);
271 }
272
273 bool PkgMgrInterface::GetIsNoRemoval() const {
274   return (pkgmgr_installer_get_no_removal(pi_) == 1);
275 }
276
277 bool PkgMgrInterface::GetDebugMode() const {
278   return (pkgmgr_installer_get_debug_mode(pi_) == 1);
279 }
280
281 bool PkgMgrInterface::GetIsSkipCheckReference() const {
282   return (pkgmgr_installer_get_skip_check_reference(pi_) == 1);
283 }
284
285 }  // namespace common_installer