1 // Copyright (c) 2014 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.
5 #include "common/step/filesystem/step_remove_files.h"
7 #include <boost/filesystem/operations.hpp>
8 #include <boost/system/error_code.hpp>
10 #include <sys/types.h>
11 #include <tzplatform_config.h>
17 #include "common/utils/pkgmgr_query.h"
18 #include "common/utils/file_util.h"
19 #include "common/utils/user_util.h"
20 #include "common/shared_dirs.h"
22 namespace bs = boost::system;
23 namespace bf = boost::filesystem;
27 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
28 const char kSubsesionDir[] = "subsession";
30 bool SkipRWDirectories(const bf::path& path) {
31 static const std::vector<std::string> dirs_to_ignore = {
38 return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
42 bool RemoveSignature(const std::string& pkgid, bool is_readonly) {
43 bf::path signature_path = bf::path(is_readonly ?
44 tzplatform_getenv(TZ_SYS_RO_SHARE) : tzplatform_getenv(TZ_SYS_SHARE)) /
46 signature_path /= std::string(pkgid + ".txt");
47 if (!common_installer::Remove(signature_path))
56 namespace common_installer {
57 namespace filesystem {
59 Step::Status StepRemoveFiles::precheck() {
60 if (!context_->manifest_data.get()) {
61 LOG(ERROR) << "manifest_data attribute is empty";
62 return Step::Status::MANIFEST_NOT_FOUND;
65 // Even though, the below checks can fail, StepRemoveFiles should still try
66 // to remove the files
67 if (context_->GetPkgPath().empty())
68 LOG(ERROR) << "pkg_path attribute is empty";
69 else if (!bf::exists(context_->GetPkgPath()))
70 LOG(ERROR) << "pkg_path ("
71 << context_->GetPkgPath()
72 << ") path does not exist";
74 return Step::Status::OK;
77 Step::Status StepRemoveFiles::process() {
78 // We need to unmount external storage before removing package directory
79 // because mount point is inside
80 if (context_->external_storage)
81 context_->external_storage->Commit();
83 bool is_keep_rwdata = false;
84 if (context_->request_mode.get() != RequestMode::GLOBAL) {
85 PkgQueryInterface pkg_query(context_->pkgid.get(), kGlobalUserUid);
86 if (pkg_query.IsPackageInstalled() ||
87 context_->keep_rwdata.get())
88 is_keep_rwdata = true;
91 bool is_error = false;
92 std::vector<bf::path> root_paths;
93 // Use RootAppPath + Pkgid because of ReadonlyUpdateUninstall
94 root_paths.push_back(context_->root_application_path.get());
96 for (auto& lw_user : GetLightUserList(context_->uid.get()))
97 root_paths.push_back(context_->root_application_path.get() / kSubsesionDir /
100 for (auto& root_path : root_paths) {
101 if (is_keep_rwdata) {
103 for (bf::directory_iterator itr(root_path / context_->pkgid.get());
104 itr != bf::directory_iterator(); ++itr) {
105 if (bf::is_directory(itr->status())) {
106 if (SkipRWDirectories(itr->path().leaf())) {
107 LOG(DEBUG) << "Skipping remove dir:" << itr->path().c_str();
110 ret = RemoveAll(itr->path());
112 ret = Remove(itr->path());
118 if (!RemoveAll(root_path / context_->pkgid.get()) ||
119 !common_installer::DeleteSharedDirectories(root_path,
120 context_->pkgid.get()))
125 return Status::ERROR;
128 // Remove package files at extended storage
129 if (context_->storage.get() == Storage::EXTENDED) {
130 bf::path extended_path =
131 bf::path(GetExtendedRootAppPath(context_->uid.get())) /
132 context_->pkgid.get();
133 if (!RemoveAll(extended_path))
134 return Status::APP_DIR_ERROR;
137 for (auto& lw_user : GetLightUserList(context_->uid.get())) {
138 if (context_->storage.get() == Storage::EXTENDED) {
139 bf::path extended_path =
140 bf::path(GetExtendedRootAppPath(context_->uid.get())) /
141 kSubsesionDir / lw_user / context_->pkgid.get();
142 if (!RemoveAll(extended_path))
143 return Status::APP_DIR_ERROR;
147 // Remove stored signature file
148 if (!RemoveSignature(context_->pkgid.get(),
149 context_->is_readonly_package.get()))
150 return Status::APP_DIR_ERROR;
155 } // namespace filesystem
156 } // namespace common_installer