implement some new features 23/100323/20
authorjongmyeongko <jongmyeong.ko@samsung.com>
Sun, 27 Nov 2016 10:58:42 +0000 (19:58 +0900)
committerjongmyeong ko <jongmyeong.ko@samsung.com>
Wed, 30 Nov 2016 08:17:56 +0000 (00:17 -0800)
partial install/update feature.
keep-rwdata feature.
clean feature
- if manifest not exist but pkg exists in db.
pkg_initdb option added

Requires :
https://review.tizen.org/gerrit/#/c/100625/
https://review.tizen.org/gerrit/#/c/100891/

Usage:
#tpk-backend -y {pkgid} --preload --partial-rw
#tpk-backend -d {pkgid} --preload --force-remove --partial-rw
#tpk-backend -d {pkgid} --preload-rw --keep-rwdata
#tpk-backend -y {pkgid} --u {userid} --bg-operation
#pkg_initdb --partial-rw (for 2.4 -> 3.0 migration)
#pkg_initdb --ro (for MIC)

Change-Id: Ib6066332fd9e462a3b8afe446c15c94971745ca6
Signed-off-by: jongmyeongko <jongmyeong.ko@samsung.com>
23 files changed:
packaging/app-installers.spec
src/common/installer_context.cc
src/common/installer_context.h
src/common/pkgmgr_interface.cc
src/common/pkgmgr_interface.h
src/common/pkgmgr_query.cc
src/common/pkgmgr_query.h
src/common/pkgmgr_signal.cc
src/common/request.h
src/common/step/configuration/step_configure.cc
src/common/step/configuration/step_configure.h
src/common/step/configuration/step_parse_manifest.cc
src/common/step/filesystem/step_create_icons.cc
src/common/step/filesystem/step_remove_files.cc
src/common/step/filesystem/step_remove_per_user_storage_directories.cc
src/common/step/pkgmgr/step_check_force_clean.cc [new file with mode: 0644]
src/common/step/pkgmgr/step_check_force_clean.h [new file with mode: 0644]
src/common/step/pkgmgr/step_check_installable.h
src/common/step/pkgmgr/step_check_removable.cc
src/common/step/pkgmgr/step_check_removable.h
src/common/step/pkgmgr/step_run_parser_plugins.cc
src/common/step/pkgmgr/step_unregister_app.cc
src/pkg_initdb/pkg_initdb.cc

index b093ebe..352aa41 100644 (file)
@@ -1,6 +1,6 @@
 Name:           app-installers
 Summary:        Application installers
-Version:        1.10
+Version:        1.11
 Release:        1
 Group:          Application Framework/Package Management
 License:        Apache-2.0
index 1850bc5..ee269e6 100644 (file)
@@ -40,6 +40,9 @@ InstallerContext::InstallerContext()
       is_preload_rw_package(false),
       force_remove(false),
       no_remove(false),
+      keep_rwdata(false),
+      partial_rw(false),
+      force_clean_from_db(false),
       cross_app_rules(false) {}
 
 InstallerContext::~InstallerContext() {
index 6b537bc..4774ede 100644 (file)
@@ -296,16 +296,32 @@ class InstallerContext {
   Property<bool> is_preload_rw_package;
 
   /**
-   * \brief force-remove request received from pkgmgr_installer
+   * \brief force-remove flag received from pkgmgr_installer
    */
   Property<bool> force_remove;
 
   /**
-   * \brief no-remove request received from pkgmgr_installer
+   * \brief no-remove flag received from pkgmgr_installer
    */
   Property<bool> no_remove;
 
   /**
+   * \brief keep-rwdata flag received from pkgmgr_installer
+   */
+  Property<bool> keep_rwdata;
+
+  /**
+   * \brief partial-rw flag received from pkgmgr_installer
+   */
+  Property<bool> partial_rw;
+
+  /**
+   * \brief Describes force clean behaviour from db data. It set to ture,
+   *        the uninstallation will be done to the end of steps.
+   */
+  Property<bool> force_clean_from_db;
+
+  /**
    * \brief Describes behaviour for security manager. It set to true, this will
    *        force to generates n-to-n rules for package's apps.
    *        This will be used for hybrid apps.
index 8eebb54..46db034 100644 (file)
@@ -112,7 +112,10 @@ RequestType PkgMgrInterface::GetRequestType() const {
       }
     }
     case PKGMGR_REQ_UNINSTALL:
-      return RequestType::Uninstall;
+      if (GetIsPreloadRequest() && GetIsPartialRW())
+        return RequestType::PartialUninstall;
+      else
+        return RequestType::Uninstall;
     case PKGMGR_REQ_REINSTALL:
       return RequestType::Reinstall;
     case PKGMGR_REQ_CLEAR:
@@ -122,10 +125,17 @@ RequestType PkgMgrInterface::GetRequestType() const {
     case PKGMGR_REQ_MOVE:
       return RequestType::Move;
     case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
-      if (!is_app_installed_.get())
-        return RequestType::ManifestDirectInstall;
-      else
-        return RequestType::ManifestDirectUpdate;
+      if (!is_app_installed_.get()) {
+        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_.get())
         return RequestType::MountInstall;
@@ -171,33 +181,41 @@ boost::filesystem::path PkgMgrInterface::GetTepPath() const {
     return boost::filesystem::path(pkgmgr_installer_get_tep_path(pi_));
 }
 
-bool PkgMgrInterface::GetIsTepMove() {
+bool PkgMgrInterface::GetIsTepMove() const {
   return (pkgmgr_installer_get_tep_move_type(pi_) == 1);
 }
 
-bool PkgMgrInterface::GetIsMoveToExternal() {
+bool PkgMgrInterface::GetIsMoveToExternal() const {
   return (pkgmgr_installer_get_move_type(pi_) == 1);
 }
 
-bool PkgMgrInterface::GetIsPreloadRequest() {
+bool PkgMgrInterface::GetIsPreloadRequest() const {
   return (pkgmgr_installer_get_is_preload(pi_) == 1);
 }
 
-bool PkgMgrInterface::GetIsPreloadRWRequest() {
+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_, GetRequestType()));
 }
 
-bool PkgMgrInterface::GetIsForceRemoval() {
+bool PkgMgrInterface::GetIsForceRemoval() const {
   return (pkgmgr_installer_get_force_removal(pi_) == 1);
 }
 
-bool PkgMgrInterface::GetIsNoRemoval() {
+bool PkgMgrInterface::GetIsNoRemoval() const {
   return (pkgmgr_installer_get_no_removal(pi_) == 1);
 }
 
index 4ad2828..0ab1aba 100644 (file)
@@ -111,42 +111,56 @@ class PkgMgrInterface {
   *
   * \return True if TEP file should be moved. Otherwise, return false
   */
-  bool GetIsTepMove();
+  bool GetIsTepMove() const;
 
   /**
   * Returns True if move request is to external. Otherwise, return false
   *
   * \return True if move request is to external. Otherwise, return false
   */
-  bool GetIsMoveToExternal();
+  bool GetIsMoveToExternal() const;
 
   /**
   * Returns True if the request is for preload. Otherwise, return false
   *
   * \return True if the request is for preload. Otherwise, return false
   */
-  bool GetIsPreloadRequest();
+  bool GetIsPreloadRequest() const;
 
   /**
   * Returns True if the request is for preload-rw. Otherwise, return false
   *
   * \return True if the request is for preload-rw. Otherwise, return false
   */
-  bool GetIsPreloadRWRequest();
+  bool GetIsPreloadRWRequest() const;
 
   /**
-  * Returns True if the request is for force-remove. Otherwise, return false
+  * Returns True if the request has force-remove flag. Otherwise, return false
   *
-  * \return True if the request is for force-remove. Otherwise, return false
+  * \return True if the request has force-remove flag. Otherwise, return false
   */
-  bool GetIsForceRemoval();
+  bool GetIsForceRemoval() const;
 
   /**
-  * Returns True if the request is for no-remove. Otherwise, return false
+  * Returns True if the request has no-remove flag. Otherwise, return false
   *
-  * \return True if the request is for no-remove. Otherwise, return false
+  * \return True if the request has no-remove flag. Otherwise, return false
   */
-  bool GetIsNoRemoval();
+  bool GetIsNoRemoval() const;
+
+  /**
+  * Returns True if the request has keep-rwdata flag. Otherwise, return false
+  *
+  * \return True if the request has keep-rwdata flag. Otherwise, return false
+  */
+  bool GetIsKeepRWData() const;
+
+  /**
+  * Returns True if the request has partial-rw flag. Otherwise, return false
+  *
+  * \return True if the request has partial-rw flag. Otherwise, return false
+  */
+  bool GetIsPartialRW() const;
 
   /**
    * Get Raw pointer to pkgmgr_installer object
index cf7b345..a65ad7f 100644 (file)
@@ -187,7 +187,8 @@ bool QueryIsPackageInstalled(const std::string& pkg_id,
 
 bool QueryIsPackageInstalled(const std::string& pkg_id, uid_t uid) {
   pkgmgrinfo_pkginfo_h handle;
-  int ret = pkgmgrinfo_pkginfo_get_usr_all_pkginfo(pkg_id.c_str(), uid, &handle);
+  int ret = pkgmgrinfo_pkginfo_get_usr_all_pkginfo(pkg_id.c_str(),
+              uid, &handle);
   if (ret != PMINFO_R_OK) {
     if (ret != PMINFO_R_ENOENT)
       LOG(ERROR) << "Failed to call pkgmgrinfo_pkginfo_get_usr_all_pkginfo";
@@ -217,7 +218,8 @@ bool QueryIsPackageInstalled(const std::string& pkg_id, uid_t uid) {
 
 bool QueryIsGlobalPackage(const std::string& pkg_id, uid_t uid) {
   pkgmgrinfo_pkginfo_h handle;
-  int ret = pkgmgrinfo_pkginfo_get_usr_all_pkginfo(pkg_id.c_str(), uid, &handle);
+  int ret = pkgmgrinfo_pkginfo_get_usr_all_pkginfo(pkg_id.c_str(),
+              uid, &handle);
   if (ret != PMINFO_R_OK) {
     if (ret != PMINFO_R_ENOENT)
       LOG(ERROR) << "Failed to call pkgmgrinfo_pkginfo_get_usr_all_pkginfo";
@@ -237,7 +239,8 @@ bool QueryIsGlobalPackage(const std::string& pkg_id, uid_t uid) {
 
 bool QueryIsReadonlyPackage(const std::string& pkg_id, uid_t uid) {
   pkgmgrinfo_pkginfo_h handle;
-  int ret = pkgmgrinfo_pkginfo_get_usr_all_pkginfo(pkg_id.c_str(), uid, &handle);
+  int ret = pkgmgrinfo_pkginfo_get_usr_all_pkginfo(pkg_id.c_str(),
+              uid, &handle);
   if (ret != PMINFO_R_OK) {
     if (ret != PMINFO_R_ENOENT)
       LOG(ERROR) << "Failed to call pkgmgrinfo_pkginfo_get_usr_all_pkginfo";
@@ -255,4 +258,19 @@ bool QueryIsReadonlyPackage(const std::string& pkg_id, uid_t uid) {
   return is_readonly;
 }
 
+bool QueryIsDisabledPackage(const std::string& pkg_id, uid_t uid) {
+  pkgmgrinfo_pkginfo_h handle;
+  int ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(pkg_id.c_str(),
+              uid, &handle);
+  if (ret != PMINFO_R_OK) {
+    if (ret != PMINFO_R_ENOENT)
+      LOG(ERROR) <<
+          "Failed to call pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo";
+    return false;
+  }
+
+  pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+  return true;
+}
+
 }  // namespace common_installer
index a08a0de..27f2770 100644 (file)
@@ -129,6 +129,17 @@ bool QueryIsGlobalPackage(const std::string& pkg_id, uid_t uid);
  */
 bool QueryIsReadonlyPackage(const std::string& pkg_id, uid_t uid);
 
+/**
+ * \brief Adapter interface for external PkgMgr module used for checking
+ *        if given package is disabled package
+ *
+ * \param pkg_id package id
+ * \param uid user id
+ *
+ * \return true if package is disable.
+ */
+bool QueryIsDisabledPackage(const std::string& pkg_id, uid_t uid);
+
 }  // namespace common_installer
 
 #endif  // COMMON_PKGMGR_QUERY_H_
index 2c9d27d..8e5408c 100644 (file)
@@ -28,6 +28,7 @@ const std::map<ci::RequestType, const char*> kEventStr = {
   {ci::RequestType::Reinstall, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::Clear, PKGMGR_INSTALLER_CLEAR_EVENT_STR},
   {ci::RequestType::Uninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
+  {ci::RequestType::PartialUninstall, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
   {ci::RequestType::Update, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::Delta, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::Move, PKGMGR_INSTALLER_MOVE_EVENT_STR},
@@ -35,6 +36,8 @@ const std::map<ci::RequestType, const char*> kEventStr = {
   {ci::RequestType::MountUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::ManifestDirectInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
   {ci::RequestType::ManifestDirectUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
+  {ci::RequestType::ManifestPartialInstall, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+  {ci::RequestType::ManifestPartialUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::DisablePkg, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
   {ci::RequestType::EnablePkg, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
   {ci::RequestType::Unknown, PKGMGR_INSTALLER_UNKNOWN_EVENT_STR}
index 2a49c07..0d53f96 100644 (file)
@@ -26,6 +26,9 @@ enum class RequestType : int {
   MountUpdate,
   ManifestDirectInstall,
   ManifestDirectUpdate,
+  ManifestPartialInstall,
+  ManifestPartialUpdate,
+  PartialUninstall,
   DisablePkg,
   EnablePkg
 };
index 4eb7e05..eeb65fa 100644 (file)
@@ -58,7 +58,11 @@ Step::Status StepConfigure::process() {
         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
       }
       break;
+    case RequestType::PartialUninstall:
+      SetupIsPartialRW();
     case RequestType::Uninstall:
+      if (context_->is_preload_rw_package.get())
+        SetupIsKeepRWData();
       SetupIsForceRemoval();
       context_->pkgid.set(pkgmgr_->GetRequestInfo());
       context_->file_path.set(kStrEmpty);
@@ -95,6 +99,9 @@ Step::Status StepConfigure::process() {
         context_->is_tep_move.set(pkgmgr_->GetIsTepMove());
       }
       break;
+    case RequestType::ManifestPartialInstall:
+    case RequestType::ManifestPartialUpdate:
+      SetupIsPartialRW();
     case RequestType::ManifestDirectInstall:
     case RequestType::ManifestDirectUpdate: {
       context_->pkgid.set(pkgmgr_->GetRequestInfo());
@@ -149,7 +156,8 @@ Step::Status StepConfigure::process() {
 Step::Status StepConfigure::precheck() {
   SetupIsPreloadRequest();
   SetupIsPreloadRWRequest();
-  SetupIsNoRemoval();
+  if (context_->is_readonly_package.get())
+    SetupIsNoRemoval();
 
   bool is_readonly = context_->is_readonly_package.get();
   bool is_preload_rw = context_->is_preload_rw_package.get();
@@ -248,5 +256,13 @@ void StepConfigure::SetupIsNoRemoval() {
   context_->no_remove.set(pkgmgr_->GetIsNoRemoval());
 }
 
+void StepConfigure::SetupIsKeepRWData() {
+  context_->keep_rwdata.set(pkgmgr_->GetIsKeepRWData());
+}
+
+void StepConfigure::SetupIsPartialRW() {
+  context_->partial_rw.set(pkgmgr_->GetIsPartialRW());
+}
+
 }  // namespace configuration
 }  // namespace common_installer
index 8eaf122..f7caa25 100644 (file)
@@ -63,6 +63,8 @@ class StepConfigure : public Step {
   void SetupIsPreloadRWRequest();
   void SetupIsForceRemoval();
   void SetupIsNoRemoval();
+  void SetupIsKeepRWData();
+  void SetupIsPartialRW();
 
   PkgMgrPtr pkgmgr_;
 
index 65c90d8..a8df469 100644 (file)
@@ -874,6 +874,8 @@ bool StepParseManifest::FillManifestX(manifest_x* manifest) {
 }
 
 Step::Status StepParseManifest::process() {
+  if (context_->force_clean_from_db.get())
+    return Step::Status::OK;
   if (!LocateConfigFile()) {
     // continue if this is recovery, manifest file may never been created
     if (manifest_location_ == ManifestLocation::RECOVERY) {
index 2c5bdc2..ea39f5f 100644 (file)
@@ -54,7 +54,8 @@ Step::Status StepCreateIcons::process() {
           destination_path += source.extension();
         else
           destination_path += ".png";
-        bf::copy_file(source, destination_path, error);
+        bf::copy_file(source, destination_path,
+                        bf::copy_option::overwrite_if_exists, error);
         if (error) {
           LOG(ERROR) << "Cannot create package icon: " << destination_path
                      << " , error: " << error;
index 2616d19..8274995 100644 (file)
@@ -23,7 +23,7 @@ namespace {
 
 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
 
-bool SkipDirectoryIfGlobal(const bf::path& path) {
+bool SkipRWDirectories(const bf::path& path) {
   static const std::vector<std::string> dirs_to_ignore = {
     {"cache"},
     {"data"},
@@ -66,36 +66,29 @@ Step::Status StepRemoveFiles::process() {
   if (context_->external_storage)
     context_->external_storage->Commit();
 
-  if (QueryIsPackageInstalled(context_->pkgid.get(), kGlobalUserUid)) {
+  if (QueryIsPackageInstalled(context_->pkgid.get(), kGlobalUserUid) ||
+      context_->keep_rwdata.get()) {
     for (bf::directory_iterator itr(pkg_path); itr != bf::directory_iterator();
         ++itr) {
-      if (bf::is_symlink(symlink_status(itr->path()))) {
-        // for removing symlink to .mmc/bin,lib,res
-        bf::remove_all(itr->path(), error);
-      } else if (bf::is_directory(itr->status())) {
-        if (SkipDirectoryIfGlobal(itr->path().leaf())) {
+      if (bf::is_directory(itr->status())) {
+        if (SkipRWDirectories(itr->path().leaf())) {
           LOG(DEBUG) << "Skipping remove dir:" << itr->path().c_str();
           continue;
         }
         bf::remove_all(itr->path(), error);
-        if (error) {
-          LOG(ERROR) << "Can't remove dir:" << context_->pkg_path.get().c_str();
-        }
-      } else if (bf::is_regular_file(itr->status())) {
+      } else {
         bf::remove_all(itr->path(), error);
       }
+      if (error)
+        LOG(ERROR) << "Can't remove path:" << itr->path().c_str();
     }
   } else {
     bf::remove_all(pkg_path, error);
-    if (error) {
+    if (error)
       LOG(ERROR) << "Can't remove directory:" <<
           context_->pkg_path.get().c_str();
-    } else {
-      LOG(DEBUG) << "Removed directory: " << context_->pkg_path.get();
-    }
   }
 
-
   return Status::OK;
 }
 
index 1e1a92e..203475e 100644 (file)
@@ -14,7 +14,8 @@ namespace common_installer {
 namespace filesystem {
 
 Step::Status StepRemovePerUserStorageDirectories::process() {
-  if (context_->request_mode.get() != RequestMode::GLOBAL)
+  if (context_->request_mode.get() != RequestMode::GLOBAL ||
+      context_->keep_rwdata.get())
     return Step::Status::OK;
 
   std::string package_id = context_->pkgid.get();
diff --git a/src/common/step/pkgmgr/step_check_force_clean.cc b/src/common/step/pkgmgr/step_check_force_clean.cc
new file mode 100644 (file)
index 0000000..b4dcf97
--- /dev/null
@@ -0,0 +1,122 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/step/pkgmgr/step_check_force_clean.h"
+
+#include <pkgmgr/pkgmgr_parser.h>
+#include <pkgmgr-info.h>
+#include <tzplatform_config.h>
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/path.hpp>
+
+#include "common/pkgmgr_query.h"
+#include "common/installer_context.h"
+
+namespace bf = boost::filesystem;
+
+namespace {
+
+int PkgmgrAppInfoCallback(const pkgmgrinfo_appinfo_h handle,
+                              void *user_data) {
+  manifest_x *mfx = static_cast<manifest_x*>(user_data);
+  application_x* application =
+          static_cast<application_x*>(calloc(1, sizeof(application_x)));
+  if (!application)
+    return PMINFO_R_ERROR;
+
+  char* app_id = nullptr;
+  if (pkgmgrinfo_appinfo_get_appid(handle, &app_id))
+    return PMINFO_R_ERROR;
+
+  icon_x* icon = static_cast<icon_x*>(calloc(1, sizeof(icon_x)));
+  if (!icon)
+    return PMINFO_R_ERROR;
+
+  char* icon_text = nullptr;
+  if (pkgmgrinfo_appinfo_get_icon(handle, &icon_text))
+    return PMINFO_R_ERROR;
+
+  if (!mfx->root_path) {
+    char *root_path = nullptr;
+    if (pkgmgrinfo_appinfo_get_root_path(handle, &root_path))
+      return PMINFO_R_ERROR;
+    mfx->root_path = strdup(root_path);
+  }
+
+  application->appid = strdup(app_id);
+  icon->text = strdup(icon_text);
+  application->icon = g_list_append(application->icon, icon);
+  mfx->application = g_list_append(mfx->application, application);
+
+  return PMINFO_R_OK;
+}
+
+int PkgmgrGenerateManifestInfoFromDB(manifest_x *mfx,
+                                     const char *pkgid, uid_t uid) {
+  pkgmgrinfo_appinfo_filter_h filter;
+  mfx->package = strdup(pkgid);
+
+  if (pkgmgrinfo_appinfo_filter_create(&filter))
+    return PMINFO_R_ERROR;
+
+  if (pkgmgrinfo_appinfo_filter_add_string(filter,
+                          PMINFO_APPINFO_PROP_APP_PACKAGE, pkgid)) {
+    pkgmgrinfo_appinfo_filter_destroy(filter);
+    return PMINFO_R_ERROR;
+  }
+
+  if (pkgmgrinfo_appinfo_usr_filter_foreach_appinfo(filter,
+                          PkgmgrAppInfoCallback, mfx, uid)) {
+    pkgmgrinfo_appinfo_filter_destroy(filter);
+    return PMINFO_R_ERROR;
+  }
+
+  pkgmgrinfo_appinfo_filter_destroy(filter);
+
+  return PMINFO_R_OK;
+}
+
+}  // namespace
+
+namespace common_installer {
+namespace pkgmgr {
+
+Step::Status StepCheckForceClean::process() {
+  if (context_->request_type.get() != RequestType::Uninstall)
+    return Status::OK;
+
+  uid_t uid;
+  bool is_readonly;
+  if (QueryIsGlobalPackage(context_->pkgid.get(), context_->uid.get())) {
+    uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+    is_readonly = QueryIsReadonlyPackage(context_->pkgid.get(),
+                                        context_->uid.get());
+  } else {
+    uid = context_->uid.get();
+    is_readonly = context_->is_readonly_package.get();
+  }
+  bf::path xml_path = bf::path(getUserManifestPath(uid, is_readonly))
+                      / bf::path(context_->pkgid.get());
+  xml_path += ".xml";
+
+  // if manifeset not found but pkg exist in db for target uid, do clean
+  if (!bf::exists(xml_path) &&
+      QueryIsPackageInstalled(context_->pkgid.get(), context_->uid.get())) {
+    context_->force_clean_from_db.set(true);
+    manifest_x* manifest =
+        static_cast<manifest_x*>(calloc(1, sizeof(manifest_x)));
+    if (!PkgmgrGenerateManifestInfoFromDB(manifest,
+            reinterpret_cast<const char*>(context_->pkgid.get().c_str()),
+            context_->uid.get())) {
+      context_->manifest_data.set(manifest);
+      context_->pkg_path.set(manifest->root_path);
+    }
+  }
+
+  return Status::OK;
+}
+
+}  // namespace pkgmgr
+}  // namespace common_installer
diff --git a/src/common/step/pkgmgr/step_check_force_clean.h b/src/common/step/pkgmgr/step_check_force_clean.h
new file mode 100644 (file)
index 0000000..f49fe35
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_STEP_PKGMGR_STEP_CHECK_FORCE_CLEAN_H_
+#define COMMON_STEP_PKGMGR_STEP_CHECK_FORCE_CLEAN_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace pkgmgr {
+
+class StepCheckForceClean : public Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status clean() override { return Status::OK; }
+  Status undo() override { return Status::OK; }
+  Status precheck() override { return Status::OK; }
+
+  STEP_NAME(CheckForceClean)
+};
+
+}  // namespace pkgmgr
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_PKGMGR_STEP_CHECK_FORCE_CLEAN_H_
index fa1453b..9965191 100644 (file)
@@ -16,12 +16,13 @@ namespace pkgmgr {
 class StepCheckInstallable : public Step {
  public:
   using Step::Step;
+
   Status process() override;
   Status clean() override { return Status::OK; }
   Status undo() override { return Status::OK; }
   Status precheck() override;
 
-  STEP_NAME(StepCheckInstallable)
+  STEP_NAME(CheckInstallable)
 };
 
 }  // namespace pkgmgr
index 58cbef3..7dd0bc8 100644 (file)
@@ -7,7 +7,6 @@
 #include <pkgmgr-info.h>
 
 #include "common/app_installer.h"
-#include "common/step/step.h"
 
 namespace common_installer {
 namespace pkgmgr {
@@ -17,8 +16,9 @@ Step::Status StepCheckRemovable::process() {
       return Status::OK;
 
   pkgmgrinfo_pkginfo_h handle;
-  int ret = pkgmgrinfo_pkginfo_get_usr_all_pkginfo(context_->pkgid.get().c_str(),
-      context_->uid.get(), &handle);
+  int ret =
+      pkgmgrinfo_pkginfo_get_usr_all_pkginfo(context_->pkgid.get().c_str(),
+          context_->uid.get(), &handle);
   if (ret != PMINFO_R_OK) {
     LOG(ERROR) << "This package is not installed";
     return Status::INVALID_VALUE;
index 59b190f..cca9ee3 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef COMMON_STEP_PKGMGR_STEP_CHECK_REMOVABLE_H_
 #define COMMON_STEP_PKGMGR_STEP_CHECK_REMOVABLE_H_
 
+#include <manifest_parser/utils/logging.h>
+
 #include "common/step/step.h"
 
 namespace common_installer {
index c5b330c..7213803 100644 (file)
@@ -34,6 +34,8 @@ Step::Status StepRunParserPlugin::ProcessPlugins(
 }
 
 Step::Status StepRunParserPlugin::process() {
+  if (context_->force_clean_from_db.get())
+      return Status::OK;
   return ProcessPlugins(context_->xml_path.get(), context_->manifest_data.get(),
                         action_type_);
 }
index 3313e18..b6c9cbf 100644 (file)
@@ -30,10 +30,14 @@ Step::Status StepUnregisterApplication::precheck() {
     return Status::PACKAGE_NOT_FOUND;
   }
   if (context_->xml_path.get().empty()) {
+    if (context_->force_clean_from_db.get())
+      return Step::Status::OK;
     LOG(ERROR) << "xml_path attribute is empty";
     return Status::MANIFEST_NOT_FOUND;
   }
   if (!boost::filesystem::exists(context_->xml_path.get())) {
+    if (context_->force_clean_from_db.get())
+      return Step::Status::OK;
     LOG(ERROR) << "xml_path ("
                << context_->xml_path.get()
                << ") path does not exist";
@@ -77,9 +81,11 @@ Step::Status StepUnregisterApplication::process() {
     LOG(ERROR) << "Failed to unregister package into database";
   }
 
-  // remove manifest file
-  bs::error_code error;
-  bf::remove(context_->xml_path.get(), error);
+  if (!context_->partial_rw.get()) {
+    // remove manifest file
+    bs::error_code error;
+    bf::remove(context_->xml_path.get(), error);
+  }
 
   LOG(DEBUG) << "Successfully unregister the application";
 
index 1bedda5..400c1f2 100644 (file)
@@ -34,8 +34,8 @@ const char kBackendDirectoryPath[] = "/etc/package-manager/backend/";
 
 int InstallManifestOffline(const std::string& pkgid,
                            const std::string& type,
-                           uid_t uid,
-                           bool preload) {
+                           uid_t uid, bool preload,
+                           bool rw_only) {
   bf::path backend_path(kBackendDirectoryPath);
   backend_path /= type;
   ci::Subprocess backend(backend_path.string());
@@ -44,7 +44,10 @@ int InstallManifestOffline(const std::string& pkgid,
       std::cerr << "Preload request for non-root user" << std::endl;
       return -1;
     }
-    backend.Run("-y", pkgid.c_str(), "--preload");
+    if (rw_only)
+      backend.Run("-y", pkgid.c_str(), "--preload");
+    else
+      backend.Run("-y", pkgid.c_str(), "--preload", "--partial-rw");
   } else {
     std::string str_uid = std::to_string(uid);
     backend.Run("-y", pkgid.c_str(), "-u", str_uid.c_str());
@@ -56,14 +59,16 @@ bool IsGlobal(uid_t uid) {
   return uid == kRootUserUid || uid == kGlobalUserUid;
 }
 
-void InitdbLoadDirectory(uid_t uid, const bf::path& directory, bool preload) {
+void InitdbLoadDirectory(uid_t uid, const bf::path& directory,
+                         bool preload, bool rw_only) {
   std::cerr << "Loading manifest files from " << directory << std::endl;
   for (bf::directory_iterator iter(directory); iter != bf::directory_iterator();
        ++iter) {
     if (!bf::is_regular_file(iter->path()))
       continue;
 
-    std::cerr << "Manifest : " << iter->path() << std::endl;
+    std::cerr << "Manifest : " << iter->path() <<
+        (rw_only? " (rw-only)":" (all)") << std::endl;
 
     tpk::parse::TPKConfigParser parser;
     if (!parser.ParseManifest(iter->path())) {
@@ -81,7 +86,8 @@ void InitdbLoadDirectory(uid_t uid, const bf::path& directory, bool preload) {
     if (type.empty())
       type = "tpk";
 
-    InstallManifestOffline(package_info->package(), type, uid, preload);
+    InstallManifestOffline(package_info->package(), type, uid,
+                           preload, rw_only);
   }
 }
 
@@ -130,15 +136,23 @@ int main(int argc, char *argv[]) {
   bpo::options_description options("Allowed options");
   bpo::variables_map opt_map;
   uid_t uid;
+  bool rw_only = false;
+  bool initial = false;
   try {
     options.add_options()
         ("uid,u", bpo::value<int>()->default_value(kRootUserUid), "user id")
+        ("partial-rw", "rw-partition only")
+        ("ro", "readonly package only")
         ("help,h", "display this help message");
     bpo::store(bpo::parse_command_line(argc, argv, options), opt_map);
     if (opt_map.count("help")) {
       std::cerr << options << std::endl;
       return -1;
     }
+    if (opt_map.count("partial-rw"))
+      rw_only = true;
+    if (opt_map.count("ro"))
+      initial = true;
     bpo::notify(opt_map);
     uid = opt_map["uid"].as<int>();
   } catch (const bpo::error& error) {
@@ -163,16 +177,19 @@ int main(int argc, char *argv[]) {
   if (IsGlobal(uid)) {
     // RO location
     bf::path ro_dir(tzplatform_getenv(TZ_SYS_RO_PACKAGES));
-    InitdbLoadDirectory(uid, ro_dir, true);
+    InitdbLoadDirectory(uid, ro_dir, true, rw_only);
+
+    if (initial)
+      return ret;
 
     // RW location
     bf::path rw_dir(tzplatform_getenv(TZ_SYS_RW_PACKAGES));
-    InitdbLoadDirectory(uid, rw_dir, false);
+    InitdbLoadDirectory(uid, rw_dir, false, false);
   } else {
     // Specified user location
     tzplatform_set_user(uid);
     bf::path dir(tzplatform_getenv(TZ_USER_PACKAGES));
-    InitdbLoadDirectory(uid, dir, false);
+    InitdbLoadDirectory(uid, dir, false, false);
     tzplatform_reset_user();
   }