Block different type installation with same pkgid
[platform/core/appfw/app-installers.git] / src / common / pkgmgr_interface.cc
index 1d838c2..a754585 100644 (file)
 #include <fstream>
 
 #include "common/app_query_interface.h"
-#include "common/pkgmgr_query.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"
 
@@ -26,6 +27,7 @@ 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,
@@ -35,13 +37,20 @@ bool CheckIfAppFilesExists(const std::string& pkgid,
               uid, is_readonly));
 }
 
-void ForceRemovePkgFromDB(const std::string& pkgid,
-                          uid_t uid,
-                          ci::RequestMode request_mode) {
-  manifest_x* manifest =
-     static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
-  ci::PkgmgrGenerateManifestInfoFromDB(manifest, pkgid, uid);
-  ci::UnregisterAppInPkgmgr(manifest, pkgid, uid, request_mode);
+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 = bf::path(path).extension().string();
+    if (extension == kDeltaFileExtension)
+      is_delta = true;
+  }
+
+  return is_delta;
 }
 
 }  // namespace
@@ -71,7 +80,7 @@ bool PkgmgrInstaller::ShouldCreateSignal() const {
 
 PkgMgrPtr PkgMgrInterface::Create(int argc, char** argv,
     PkgmgrInstallerInterface* pkgmgr_installer_interface,
-    AppQueryInterface* interface) {
+    std::shared_ptr<AppQueryInterface> interface) {
   PkgMgrPtr instance(new PkgMgrInterface(pkgmgr_installer_interface,
                                          interface));
   int result = instance->InitInternal(argc, argv);
@@ -95,8 +104,15 @@ int PkgMgrInterface::InitInternal(int argc, char** argv) {
     return -1;
   }
 
+  boost::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;
+  }
+
   // Set target uid as tizenglobalapp if admin user's request
-  if (IsAdminUser(pkgmgr_installer_get_uid(pi_))) {
+  if (*is_admin_user) {
     result = pkgmgr_installer_set_uid(pi_, kGlobalUserUid);
     if (result) {
       LOG(ERROR) << "Failed to set global uid";
@@ -112,22 +128,74 @@ PkgMgrInterface::~PkgMgrInterface() {
     pkgmgr_installer_free(pi_);
 }
 
-RequestType PkgMgrInterface::GetRequestType() const {
-  if (!query_interface_)
-    return RequestType::Unknown;
+// method name?
+bool PkgMgrInterface::SetAppQueryInterface(int idx) {
+  // reset this flag to processing new package
+  is_app_installed_ = boost::none;
+
+  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(), GetUid());
+        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();
+      bool is_delta = IsDeltaPkg(request_info);
       if (!is_app_installed_.get()) {
-        if (extension == kDeltaFileExtension) {
+        if (is_delta) {
           LOG(ERROR) << "Package is not installed. "
                         "Cannot update from delta package";
           return RequestType::Unknown;
@@ -135,43 +203,41 @@ RequestType PkgMgrInterface::GetRequestType() const {
           return RequestType::Install;
         }
       } else {
-        if (extension == kDeltaFileExtension) {
+        if (is_delta) {
           return RequestType::Delta;
         } else {
-          std::string pkgid = query_interface_->GetPkgId(GetRequestInfo());
+          std::string pkgid = query_interface->GetPkgId(GetRequestInfo(idx));
           uid_t uid = GetUid();
+          ci::PkgQueryInterface pkg_query(pkgid, uid);
           if (!GetIsPreloadRequest() &&
-              QueryIsReadonlyPackage(pkgid, uid) &&
-              !QueryIsUpdatedReadonlyPackage(pkgid, uid)) {
+              pkg_query.IsReadonlyPackage() &&
+              !pkg_query.IsUpdatedPackage()) {
             return RequestType::ReadonlyUpdateInstall;
           } else if (CheckIfAppFilesExists(pkgid, uid,
-                                           QueryIsReadonlyPackage(pkgid, uid)
-                                           )) {
+              pkg_query.IsReadonlyPackage())
+                  ) {
             return RequestType::Update;
           } else {
             RequestMode request_mode = GetRequestMode(uid);
-            ForceRemovePkgFromDB(pkgid, uid, request_mode);
+            UnregisterAppInPkgmgrForPkgId(pkgid, uid, request_mode);
             return RequestType::Install;
           }
         }
       }
     }
     case PKGMGR_REQ_UNINSTALL: {
-      std::string pkgid = GetRequestInfo();
-      if (!GetIsPreloadRequest() &&
-          QueryIsUpdatedReadonlyPackage(pkgid, GetUid()))
+      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::Uninstall;
     }
-    case PKGMGR_REQ_REINSTALL:
-      return RequestType::Reinstall;
-    case PKGMGR_REQ_RECOVER:
-      return RequestType::Recovery;
-    case PKGMGR_REQ_MOVE:
-      return RequestType::Move;
     case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
       if (!is_app_installed_.get()) {
         if (GetIsPreloadRequest() && GetIsPartialRW())
@@ -184,17 +250,22 @@ RequestType PkgMgrInterface::GetRequestType() const {
         else
           return RequestType::ManifestDirectUpdate;
       }
-    case PKGMGR_REQ_MOUNT_INSTALL:
-      if (!is_app_installed_.get())
+    case PKGMGR_REQ_MOUNT_INSTALL: {
+      if (!is_app_installed_.get()) {
         return RequestType::MountInstall;
-      else
-        return RequestType::MountUpdate;
-    case PKGMGR_REQ_DISABLE_PKG:
-      return RequestType::DisablePkg;
-    case PKGMGR_REQ_ENABLE_PKG:
-      return RequestType::EnablePkg;
-    case PKGMGR_REQ_MIGRATE_EXTIMG:
-      return RequestType::MigrateExtImg;
+      } 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;
   }
@@ -204,8 +275,12 @@ uid_t PkgMgrInterface::GetUid() const {
   return pkgmgr_installer_get_uid(pi_);
 }
 
-const char* PkgMgrInterface::GetRequestInfo() const {
-  return pkgmgr_installer_get_request_info(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 {
@@ -223,6 +298,10 @@ 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);
 }
@@ -242,7 +321,7 @@ bool PkgMgrInterface::GetIsPartialRW() const {
 std::unique_ptr<PkgmgrSignal> PkgMgrInterface::CreatePkgmgrSignal() const {
   if (!pkgmgr_installer_interface_->ShouldCreateSignal())
     return nullptr;
-  return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_, GetRequestType()));
+  return std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi_));
 }
 
 bool PkgMgrInterface::GetIsForceRemoval() const {
@@ -257,4 +336,20 @@ 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::GetRecoveryCleanup() const {
+  return (pkgmgr_installer_get_recovery_cleanup(pi_) == 1);
+}
+
 }  // namespace common_installer