Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / pkgmgr_interface.cc
index 61f8aaf..b7d3ccd 100644 (file)
@@ -4,28 +4,84 @@
 
 #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;
@@ -34,60 +90,36 @@ PkgMgrPtr PkgMgrInterface::Create(int argc, char** argv,
 }
 
 int PkgMgrInterface::InitInternal(int argc, char** argv) {
-  pi_ = pkgmgr_installer_new();
-
-  if (!pi_) {
-    LOG(ERROR) << "Cannot create pkgmgr_installer object";
-    return ENOMEM;
+  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;
   }
 
-  if (pkgmgr_installer_get_request_type(pi_) == PKGMGR_REQ_MANIFEST_DIRECT_INSTALL) {
-    /* Add restrictions for manifest direct install
-      * - Directory should be located under /usr/apps/
-      * - XML path should be located under /usr/share/packages/
-      * - Directory name and xml name should be same */
-    bf::path directory_path = pkgmgr_installer_get_directory_path(pi_);
-    bf::path xml_path = pkgmgr_installer_get_xml_path(pi_);
-
-    if (directory_path.empty() ||
-        !bf::is_directory(directory_path) ||
-        xml_path.empty() ||
-        !bf::is_regular_file(xml_path)) {
-      LOG(ERROR) << "invalid parameter";
-      return EINVAL;
-    }
-
-    if (directory_path.parent_path().compare("/usr/apps") != 0) {
-      LOG(ERROR) << "invalid directory path";
-      return EINVAL;
-    }
-
-    if (xml_path.parent_path().compare("/usr/share/packages") != 0) {
-      LOG(ERROR) << "invalid xml path";
-      return EINVAL;
-    }
+  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;
+  }
 
-    if (directory_path.filename().string().compare(xml_path.stem().string()) != 0) {
-      LOG(ERROR) << "invalid parameter: directory path "
-          << directory_path
-          << "xml path"
-          << xml_path;
-      return EINVAL;
+  // 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;
     }
-
   }
 
-  is_app_installed_ = false;
-  if (query_interface_)
-    is_app_installed_ = query_interface_->IsAppInstalledByArgv(argc, argv);
-
-  return result;
+  return 0;
 }
 
 PkgMgrInterface::~PkgMgrInterface() {
@@ -95,15 +127,74 @@ 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;
@@ -111,49 +202,153 @@ RequestType PkgMgrInterface::GetRequestType() const {
           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_);
 }
 
-boost::filesystem::path PkgMgrInterface::GetTepPath() const {
+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;
+}
+
+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::GetIsTepMove() {
-  return (pkgmgr_installer_get_tep_move_type(pi_) == 1)?true:false;
+bool PkgMgrInterface::GetSkipOptimization() const {
+  return (pkgmgr_installer_get_skip_optimization(pi_) == 1);
 }
 
-boost::filesystem::path PkgMgrInterface::GetXMLPath() {
-  return boost::filesystem::path(pkgmgr_installer_get_xml_path(pi_));
+int PkgMgrInterface::GetRequestInfoCount() const {
+  return pkgmgr_installer_get_request_info_count(pi_);
 }
 
-boost::filesystem::path PkgMgrInterface::GetDirectoryPath() {
-  return boost::filesystem::path(pkgmgr_installer_get_directory_path(pi_));
+bool PkgMgrInterface::GetRecoveryCleanup() const {
+  return (pkgmgr_installer_get_recovery_cleanup(pi_) == 1);
 }
 
 }  // namespace common_installer