Fix for readonly update mode
[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 = query_interface_->GetPkgId(GetRequestInfo());
113           if (!GetIsPreloadRequest() &&
114               QueryIsReadonlyPackage(pkgid, GetUid()) &&
115               !QueryIsUpdatedReadonlyPackage(pkgid, GetUid()))
116             return RequestType::ReadonlyUpdateInstall;
117           else
118             return RequestType::Update;
119         }
120       }
121     }
122     case PKGMGR_REQ_UNINSTALL: {
123       std::string pkgid = GetRequestInfo();
124       if (!GetIsPreloadRequest() &&
125           QueryIsUpdatedReadonlyPackage(pkgid, GetUid()))
126         return RequestType::ReadonlyUpdateUninstall;
127       else if (GetIsPreloadRequest() && GetIsPartialRW())
128         return RequestType::PartialUninstall;
129       else
130         return RequestType::Uninstall;
131     }
132     case PKGMGR_REQ_REINSTALL:
133       return RequestType::Reinstall;
134     case PKGMGR_REQ_CLEAR:
135       return RequestType::Clear;
136     case PKGMGR_REQ_RECOVER:
137       return RequestType::Recovery;
138     case PKGMGR_REQ_MOVE:
139       return RequestType::Move;
140     case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
141       if (!is_app_installed_.get()) {
142         if (GetIsPreloadRequest() && GetIsPartialRW())
143           return RequestType::ManifestPartialInstall;
144         else
145           return RequestType::ManifestDirectInstall;
146       } else {
147         if (GetIsPreloadRequest() && GetIsPartialRW())
148           return RequestType::ManifestPartialUpdate;
149         else
150           return RequestType::ManifestDirectUpdate;
151       }
152     case PKGMGR_REQ_MOUNT_INSTALL:
153       if (!is_app_installed_.get())
154         return RequestType::MountInstall;
155       else
156         return RequestType::MountUpdate;
157     case PKGMGR_REQ_DISABLE_PKG:
158       return RequestType::DisablePkg;
159     case PKGMGR_REQ_ENABLE_PKG:
160       return RequestType::EnablePkg;
161     default:
162       return RequestType::Unknown;
163   }
164 }
165
166 uid_t PkgMgrInterface::GetUid() const {
167   return pkgmgr_installer_get_uid(pi_);
168 }
169
170 std::string PkgMgrInterface::GetRequestInfo() const {
171   std::string info;
172   const char* raw_info = pkgmgr_installer_get_request_info(pi_);
173   if (raw_info == nullptr)
174     return {};
175   // to support legacy content directory path,
176   // if the requested path starts with "/opt/usr/media", return modified path.
177   // note that "/opt/usr/media" is a mount point for TZ_USER_CONTENT.
178   if (!strncmp(raw_info, kLegacyContentPath, strlen(kLegacyContentPath))) {
179     tzplatform_set_user(GetUid());
180     const char* content_path = tzplatform_getenv(TZ_USER_CONTENT);
181     tzplatform_reset_user();
182     info = std::string(content_path) +
183       std::string(raw_info + strlen(kLegacyContentPath));
184   } else {
185     info = std::string(raw_info);
186   }
187   return info;
188 }
189
190 boost::filesystem::path PkgMgrInterface::GetTepPath() const {
191   if (pkgmgr_installer_get_tep_path(pi_) == nullptr)
192     return boost::filesystem::path("");
193   else
194     return boost::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
195 }
196
197 bool PkgMgrInterface::GetIsTepMove() const {
198   return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
199 }
200
201 bool PkgMgrInterface::GetIsMoveToExternal() const {
202   return (pkgmgr_installer_get_move_type(pi_) == 1);
203 }
204
205 bool PkgMgrInterface::GetIsPreloadRequest() const {
206   return (pkgmgr_installer_get_is_preload(pi_) == 1);
207 }
208
209 bool PkgMgrInterface::GetIsPreloadRWRequest() const {
210   return (pkgmgr_installer_get_is_preload_rw(pi_) == 1);
211 }
212
213 bool PkgMgrInterface::GetIsKeepRWData() const {
214   return (pkgmgr_installer_get_keep_rwdata(pi_) == 1);
215 }
216
217 bool PkgMgrInterface::GetIsPartialRW() const {
218   return (pkgmgr_installer_get_partial_rw(pi_) == 1);
219 }
220
221 std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
222   if (!pkgmgr_installer_interface_->ShouldCreateSignal())
223     return nullptr;
224   return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_, GetRequestType()));
225 }
226
227 bool PkgMgrInterface::GetIsForceRemoval() const {
228   return (pkgmgr_installer_get_force_removal(pi_) == 1);
229 }
230
231 bool PkgMgrInterface::GetIsNoRemoval() const {
232   return (pkgmgr_installer_get_no_removal(pi_) == 1);
233 }
234
235 }  // namespace common_installer