#include "common/pkgmgr_interface.h"
-#include <boost/filesystem/path.hpp>
-#include <boost/filesystem.hpp>
-
+#include <tzplatform_config.h>
#include <memory>
#include <string>
+#include <filesystem>
#include <fstream>
+#include <optional>
#include "common/app_query_interface.h"
+#include "common/utils/pkgmgr_query.h"
+#include "common/pkgmgr_signal.h"
+#include "common/pkgmgr_registration.h"
+#include "common/utils/file_util.h"
+#include "common/utils/manifest_util.h"
+#include "common/utils/user_util.h"
-namespace bf = boost::filesystem;
+namespace fs = std::filesystem;
+namespace ci = common_installer;
namespace {
const char kDeltaFileExtension[] = ".delta";
+const char kDeltaFileName[] = "delta_info.xml";
+const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+
+bool CheckIfAppFilesExists(const std::string& pkgid,
+ uid_t uid,
+ bool is_readonly) {
+ return fs::exists(ci::GetManifestLocation(pkgid,
+ uid, is_readonly));
+}
+
+bool IsDeltaPkg(const std::string& path) {
+ bool is_delta = false;
+ if (!ci::CheckPathInZipArchive(path.c_str(), kDeltaFileName, &is_delta)) {
+ LOG(ERROR) << "Failed to check delta package";
+ return false;
+ }
+
+ if (!is_delta) {
+ std::string extension = fs::path(path).extension().string();
+ if (extension == kDeltaFileExtension)
+ is_delta = true;
+ }
+ return is_delta;
}
+} // namespace
+
namespace common_installer {
+bool PkgmgrInstaller::CreatePkgMgrInstaller(pkgmgr_installer** installer,
+ InstallationMode* mode) {
+ *installer = pkgmgr_installer_new();
+ if (!*installer) {
+ LOG(WARNING) << "Cannot create pkgmgr_installer object. Will try offline";
+ // We assume offline mode if we cannot connect to pkgmgr-server
+ *installer = pkgmgr_installer_offline_new();
+ if (!*installer) {
+ return false;
+ }
+ *mode = InstallationMode::OFFLINE;
+ } else {
+ *mode = InstallationMode::ONLINE;
+ }
+ return true;
+}
+
+bool PkgmgrInstaller::ShouldCreateSignal() const {
+ return true;
+}
+
PkgMgrPtr PkgMgrInterface::Create(int argc, char** argv,
- AppQueryInterface* interface) {
- PkgMgrPtr instance(new PkgMgrInterface(interface));
+ PkgmgrInstallerInterface* pkgmgr_installer_interface,
+ std::shared_ptr<AppQueryInterface> interface) {
+ PkgMgrPtr instance(new PkgMgrInterface(pkgmgr_installer_interface,
+ interface));
int result = instance->InitInternal(argc, argv);
if (result != 0)
return nullptr;
}
int PkgMgrInterface::InitInternal(int argc, char** argv) {
- pi_ = pkgmgr_installer_new();
-
- if (!pi_) {
- LOG(WARNING) << "Cannot create pkgmgr_installer object. Will try offline";
- // TODO(t.iwanek): app-installer should recognize offline installation and
- // this information should be accesible in installation context
- pi_ = pkgmgr_installer_offline_new();
- if (!pi_) {
- LOG(ERROR) << "Cannot create pkgmgr_installer object. Aborting.";
- return ENOMEM;
- }
- install_mode_ = InstallationMode::OFFLINE;
- } else {
- install_mode_ = InstallationMode::ONLINE;
+ if (!pkgmgr_installer_interface_->CreatePkgMgrInstaller(&pi_,
+ &install_mode_)) {
+ LOG(ERROR) << "Cannot create pkgmgr_installer object. Aborting.";
+ return -1;
}
int result = pkgmgr_installer_receive_request(pi_, argc, argv);
if (result) {
LOG(ERROR) << "Cannot receive request. Invalid arguments?";
// no need to free pkgmgr_installer here. it will be freed in DTOR.
+ return -1;
+ }
+
+ std::optional<bool> is_admin_user =
+ IsAdminUser(pkgmgr_installer_get_uid(pi_));
+ if (!is_admin_user) {
+ LOG(ERROR) << "Cannot get admin user info. Aborting.";
+ return -1;
}
- is_app_installed_ = false;
- if (query_interface_)
- is_app_installed_ = query_interface_->IsAppInstalledByArgv(argc, argv);
+ // Set target uid as tizenglobalapp if admin user's request
+ if (*is_admin_user) {
+ result = pkgmgr_installer_set_uid(pi_, kGlobalUserUid);
+ if (result) {
+ LOG(ERROR) << "Failed to set global uid";
+ return -1;
+ }
+ }
- return result;
+ return 0;
}
PkgMgrInterface::~PkgMgrInterface() {
pkgmgr_installer_free(pi_);
}
-RequestType PkgMgrInterface::GetRequestType() const {
+// method name?
+bool PkgMgrInterface::SetAppQueryInterface(int idx) {
+ // reset this flag to processing new package
+ is_app_installed_.reset();
+
+ auto it = query_interface_map_.find(idx);
+ if (it == query_interface_map_.end()) {
+ if (!query_interface_) {
+ LOG(ERROR) << "Cannot find query interface for index(" << idx << ")";
+ return false;
+ } else {
+ // using legacy query interface (for single pkg installer)
+ return true;
+ }
+ }
+ query_interface_ = it->second;
+ return true;
+}
+
+void PkgMgrInterface::AddAppQueryInterface(
+ int idx, std::shared_ptr<AppQueryInterface> interface) {
+ query_interface_map_.emplace(idx, interface);
+}
+
+std::shared_ptr<AppQueryInterface> PkgMgrInterface::GetAppQueryInterface() {
+ return query_interface_;
+}
+
+RequestType PkgMgrInterface::GetRequestType(int idx) const {
+ // These type could be determined even if there are no query_interface_.
+ switch (pkgmgr_installer_get_request_type(pi_)) {
+ case PKGMGR_REQ_DISABLE_PKG:
+ return RequestType::DisablePkg;
+ case PKGMGR_REQ_ENABLE_PKG:
+ return RequestType::EnablePkg;
+ case PKGMGR_REQ_MIGRATE_EXTIMG:
+ return RequestType::MigrateExtImg;
+ case PKGMGR_REQ_RECOVER_DB:
+ return RequestType::RecoverDB;
+ case PKGMGR_REQ_REINSTALL:
+ return RequestType::Reinstall;
+ case PKGMGR_REQ_RECOVER:
+ return RequestType::Recovery;
+ case PKGMGR_REQ_MOVE:
+ return RequestType::Move;
+ }
+
+ std::shared_ptr<AppQueryInterface> query_interface = query_interface_;
+ if (!query_interface) {
+ auto it = query_interface_map_.find(idx);
+ if (it == query_interface_map_.end())
+ return RequestType::Unknown;
+ query_interface = it->second;
+ }
+
+ if (!is_app_installed_) {
+ is_app_installed_ =
+ query_interface->IsPkgInstalled(GetRequestInfo(idx), GetUid());
+ }
switch (pkgmgr_installer_get_request_type(pi_)) {
+ case PKGMGR_REQ_UPGRADE :
case PKGMGR_REQ_INSTALL : {
- auto request_info = GetRequestInfo();
- if (!request_info)
+ auto request_info = GetRequestInfo(idx);
+ if (request_info.empty())
return RequestType::Unknown;
- std::string extension = bf::path(request_info).extension().string();
- if (!is_app_installed_) {
- if (extension == kDeltaFileExtension) {
+ bool is_delta = IsDeltaPkg(request_info);
+ if (!is_app_installed_.value()) {
+ if (is_delta) {
LOG(ERROR) << "Package is not installed. "
"Cannot update from delta package";
return RequestType::Unknown;
return RequestType::Install;
}
} else {
- if (extension == kDeltaFileExtension)
+ if (is_delta) {
return RequestType::Delta;
- else
- return RequestType::Update;
+ } else {
+ std::string pkgid = query_interface->GetPkgId(GetRequestInfo(idx));
+ uid_t uid = GetUid();
+ ci::PkgQueryInterface pkg_query(pkgid, uid);
+ if (!GetIsPreloadRequest() &&
+ pkg_query.IsReadonlyPackage() &&
+ !pkg_query.IsUpdatedPackage()) {
+ return RequestType::ReadonlyUpdateInstall;
+ } else if (CheckIfAppFilesExists(pkgid, uid,
+ pkg_query.IsReadonlyPackage())
+ ) {
+ return RequestType::Update;
+ } else {
+ RequestMode request_mode = GetRequestMode(uid);
+ UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
+ return RequestType::Install;
+ }
+ }
}
}
- case PKGMGR_REQ_UNINSTALL:
- return RequestType::Uninstall;
- case PKGMGR_REQ_REINSTALL:
- return RequestType::Reinstall;
- case PKGMGR_REQ_RECOVER:
- return RequestType::Recovery;
- case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
- if (!is_app_installed_)
- return RequestType::ManifestDirectInstall;
+ case PKGMGR_REQ_UNINSTALL: {
+ std::string pkgid = GetRequestInfo(idx);
+ uid_t uid = GetUid();
+ ci::PkgQueryInterface pkg_query(pkgid, uid);
+ if (pkg_query.IsSystemPackage() &&
+ pkg_query.IsUpdatedPackage() &&
+ pkg_query.IsRemovablePackage())
+ return RequestType::ReadonlyUpdateUninstall;
+ else if (GetIsPreloadRequest() && GetIsPartialRW())
+ return RequestType::PartialUninstall;
else
- return RequestType::ManifestDirectUpdate;
+ return RequestType::Uninstall;
+ }
+ case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
+ if (!is_app_installed_.value()) {
+ if (GetIsPreloadRequest() && GetIsPartialRW())
+ return RequestType::ManifestPartialInstall;
+ else
+ return RequestType::ManifestDirectInstall;
+ } else {
+ if (GetIsPreloadRequest() && GetIsPartialRW())
+ return RequestType::ManifestPartialUpdate;
+ else
+ return RequestType::ManifestDirectUpdate;
+ }
+ case PKGMGR_REQ_MOUNT_INSTALL: {
+ if (!is_app_installed_.value()) {
+ return RequestType::MountInstall;
+ } else {
+ std::string pkgid = query_interface->GetPkgId(GetRequestInfo(idx));
+ uid_t uid = GetUid();
+ ci::PkgQueryInterface pkg_query(pkgid, uid);
+ if (CheckIfAppFilesExists(pkgid, uid, pkg_query.IsReadonlyPackage())) {
+ return RequestType::MountUpdate;
+ } else {
+ RequestMode request_mode = GetRequestMode(uid);
+ UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
+ return RequestType::MountInstall;
+ }
+ }
+ }
default:
return RequestType::Unknown;
}
}
-const char* PkgMgrInterface::GetRequestInfo() const {
- return pkgmgr_installer_get_request_info(pi_);
+uid_t PkgMgrInterface::GetUid() const {
+ return pkgmgr_installer_get_uid(pi_);
+}
+
+std::string PkgMgrInterface::GetRequestInfo(int idx) const {
+ const char* request_info = pkgmgr_installer_get_request_info_at(pi_, idx);
+ if (!request_info)
+ return {};
+ else
+ return request_info;
}
-boost::filesystem::path PkgMgrInterface::GetTepPath() const {
+std::filesystem::path PkgMgrInterface::GetTepPath() const {
if (pkgmgr_installer_get_tep_path(pi_) == nullptr)
- return boost::filesystem::path("");
+ return std::filesystem::path("");
else
- return boost::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
+ return std::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
+}
+
+bool PkgMgrInterface::GetIsTepMove() const {
+ return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetIsMoveToExternal() const {
+ return (pkgmgr_installer_get_move_type(pi_) == 1);
+}
+
+int PkgMgrInterface::GetMoveType() const {
+ return pkgmgr_installer_get_move_type(pi_);
+}
+
+bool PkgMgrInterface::GetIsPreloadRequest() const {
+ return (pkgmgr_installer_get_is_preload(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetIsPreloadRWRequest() const {
+ return (pkgmgr_installer_get_is_preload_rw(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetIsKeepRWData() const {
+ return (pkgmgr_installer_get_keep_rwdata(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetIsPartialRW() const {
+ return (pkgmgr_installer_get_partial_rw(pi_) == 1);
+}
+
+std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
+ if (!pkgmgr_installer_interface_->ShouldCreateSignal())
+ return nullptr;
+ return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_));
+}
+
+bool PkgMgrInterface::GetIsForceRemoval() const {
+ return (pkgmgr_installer_get_force_removal(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetIsNoRemoval() const {
+ return (pkgmgr_installer_get_no_removal(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetDebugMode() const {
+ return (pkgmgr_installer_get_debug_mode(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetIsSkipCheckReference() const {
+ return (pkgmgr_installer_get_skip_check_reference(pi_) == 1);
+}
+
+bool PkgMgrInterface::GetSkipOptimization() const {
+ return (pkgmgr_installer_get_skip_optimization(pi_) == 1);
+}
+
+int PkgMgrInterface::GetRequestInfoCount() const {
+ return pkgmgr_installer_get_request_info_count(pi_);
}
-bool PkgMgrInterface::GetIsTepMove() {
- return (pkgmgr_installer_get_tep_move_type(pi_) == 1)?true:false;
+bool PkgMgrInterface::GetRecoveryCleanup() const {
+ return (pkgmgr_installer_get_recovery_cleanup(pi_) == 1);
}
} // namespace common_installer