Fix possible nullpointer issue
[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 <cstring>
13 #include <memory>
14 #include <string>
15 #include <fstream>
16
17 #include "common/app_query_interface.h"
18 #include "common/pkgmgr_query.h"
19 #include "common/pkgmgr_signal.h"
20
21 namespace bf = boost::filesystem;
22
23 namespace {
24
25 const char kDeltaFileExtension[] = ".delta";
26 const char kLegacyContentPath[] = "/opt/usr/media";
27
28 }
29
30 namespace common_installer {
31
32 bool PkgmgrInstaller::CreatePkgMgrInstaller(pkgmgr_installer** installer,
33                              InstallationMode* mode) {
34   *installer = pkgmgr_installer_new();
35   if (!*installer) {
36     LOG(WARNING) << "Cannot create pkgmgr_installer object. Will try offline";
37     // We assume offline mode if we cannot connect to pkgmgr-server
38     *installer = pkgmgr_installer_offline_new();
39     if (!*installer) {
40       return false;
41     }
42     *mode = InstallationMode::OFFLINE;
43   } else {
44     *mode = InstallationMode::ONLINE;
45   }
46   return true;
47 }
48
49 bool PkgmgrInstaller::ShouldCreateSignal() const {
50   return true;
51 }
52
53 PkgMgrPtr PkgMgrInterface::Create(int argc, char** argv,
54     PkgmgrInstallerInterface* pkgmgr_installer_interface,
55     AppQueryInterface* interface) {
56   PkgMgrPtr instance(new PkgMgrInterface(pkgmgr_installer_interface,
57                                          interface));
58   int result = instance->InitInternal(argc, argv);
59   if (result != 0)
60     return nullptr;
61
62   return instance;
63 }
64
65 int PkgMgrInterface::InitInternal(int argc, char** argv) {
66   if (!pkgmgr_installer_interface_->CreatePkgMgrInstaller(&pi_,
67                                                           &install_mode_)) {
68     LOG(ERROR) << "Cannot create pkgmgr_installer object. Aborting.";
69     return false;
70   }
71
72   int result = pkgmgr_installer_receive_request(pi_, argc, argv);
73   if (result) {
74     LOG(ERROR) << "Cannot receive request. Invalid arguments?";
75     // no need to free pkgmgr_installer here. it will be freed in DTOR.
76   }
77
78   return result;
79 }
80
81 PkgMgrInterface::~PkgMgrInterface() {
82   if (pi_)
83     pkgmgr_installer_free(pi_);
84 }
85
86 RequestType PkgMgrInterface::GetRequestType() const {
87   if (!is_app_installed_) {
88     if (query_interface_)
89       is_app_installed_ =
90           query_interface_->IsPkgInstalled(GetRequestInfo(), GetUid());
91     else
92       is_app_installed_ = false;
93   }
94   switch (pkgmgr_installer_get_request_type(pi_)) {
95     case PKGMGR_REQ_INSTALL : {
96       auto request_info = GetRequestInfo();
97       if (request_info.empty())
98         return RequestType::Unknown;
99       std::string extension = bf::path(request_info).extension().string();
100       if (!is_app_installed_.get()) {
101         if (extension == kDeltaFileExtension) {
102           LOG(ERROR) << "Package is not installed. "
103                         "Cannot update from delta package";
104           return RequestType::Unknown;
105         } else {
106           return RequestType::Install;
107         }
108       } else {
109         if (extension == kDeltaFileExtension) {
110           return RequestType::Delta;
111         } else {
112           std::string pkgid = nullptr;
113           if (query_interface_)
114             pkgid = query_interface_->GetPkgId(GetRequestInfo());
115           if (!GetIsPreloadRequest() &&
116               QueryIsReadonlyPackage(pkgid, GetUid()) &&
117               !QueryIsUpdatedReadonlyPackage(pkgid, GetUid()))
118             return RequestType::ReadonlyUpdateInstall;
119           else
120             return RequestType::Update;
121         }
122       }
123     }
124     case PKGMGR_REQ_UNINSTALL: {
125       std::string pkgid = GetRequestInfo();
126       if (!GetIsPreloadRequest() &&
127           QueryIsUpdatedReadonlyPackage(pkgid, GetUid()))
128         return RequestType::ReadonlyUpdateUninstall;
129       else if (GetIsPreloadRequest() && GetIsPartialRW())
130         return RequestType::PartialUninstall;
131       else
132         return RequestType::Uninstall;
133     }
134     case PKGMGR_REQ_REINSTALL:
135       return RequestType::Reinstall;
136     case PKGMGR_REQ_CLEAR:
137       return RequestType::Clear;
138     case PKGMGR_REQ_RECOVER:
139       return RequestType::Recovery;
140     case PKGMGR_REQ_MOVE:
141       return RequestType::Move;
142     case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
143       if (!is_app_installed_.get()) {
144         if (GetIsPreloadRequest() && GetIsPartialRW())
145           return RequestType::ManifestPartialInstall;
146         else
147           return RequestType::ManifestDirectInstall;
148       } else {
149         if (GetIsPreloadRequest() && GetIsPartialRW())
150           return RequestType::ManifestPartialUpdate;
151         else
152           return RequestType::ManifestDirectUpdate;
153       }
154     case PKGMGR_REQ_MOUNT_INSTALL:
155       if (!is_app_installed_.get())
156         return RequestType::MountInstall;
157       else
158         return RequestType::MountUpdate;
159     case PKGMGR_REQ_DISABLE_PKG:
160       return RequestType::DisablePkg;
161     case PKGMGR_REQ_ENABLE_PKG:
162       return RequestType::EnablePkg;
163     default:
164       return RequestType::Unknown;
165   }
166 }
167
168 uid_t PkgMgrInterface::GetUid() const {
169   return pkgmgr_installer_get_uid(pi_);
170 }
171
172 std::string PkgMgrInterface::GetRequestInfo() const {
173   std::string info;
174   const char* raw_info = pkgmgr_installer_get_request_info(pi_);
175   if (raw_info == nullptr)
176     return {};
177   // to support legacy content directory path,
178   // if the requested path starts with "/opt/usr/media", return modified path.
179   // note that "/opt/usr/media" is a mount point for TZ_USER_CONTENT.
180   if (!strncmp(raw_info, kLegacyContentPath, strlen(kLegacyContentPath))) {
181     tzplatform_set_user(GetUid());
182     const char* content_path = tzplatform_getenv(TZ_USER_CONTENT);
183     tzplatform_reset_user();
184     info = std::string(content_path) +
185       std::string(raw_info + strlen(kLegacyContentPath));
186   } else {
187     info = std::string(raw_info);
188   }
189   return info;
190 }
191
192 boost::filesystem::path PkgMgrInterface::GetTepPath() const {
193   if (pkgmgr_installer_get_tep_path(pi_) == nullptr)
194     return boost::filesystem::path("");
195   else
196     return boost::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
197 }
198
199 bool PkgMgrInterface::GetIsTepMove() const {
200   return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
201 }
202
203 bool PkgMgrInterface::GetIsMoveToExternal() const {
204   return (pkgmgr_installer_get_move_type(pi_) == 1);
205 }
206
207 bool PkgMgrInterface::GetIsPreloadRequest() const {
208   return (pkgmgr_installer_get_is_preload(pi_) == 1);
209 }
210
211 bool PkgMgrInterface::GetIsPreloadRWRequest() const {
212   return (pkgmgr_installer_get_is_preload_rw(pi_) == 1);
213 }
214
215 bool PkgMgrInterface::GetIsKeepRWData() const {
216   return (pkgmgr_installer_get_keep_rwdata(pi_) == 1);
217 }
218
219 bool PkgMgrInterface::GetIsPartialRW() const {
220   return (pkgmgr_installer_get_partial_rw(pi_) == 1);
221 }
222
223 std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
224   if (!pkgmgr_installer_interface_->ShouldCreateSignal())
225     return nullptr;
226   return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_, GetRequestType()));
227 }
228
229 bool PkgMgrInterface::GetIsForceRemoval() const {
230   return (pkgmgr_installer_get_force_removal(pi_) == 1);
231 }
232
233 bool PkgMgrInterface::GetIsNoRemoval() const {
234   return (pkgmgr_installer_get_no_removal(pi_) == 1);
235 }
236
237 }  // namespace common_installer