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/shared_dirs.h"
21 namespace bs = boost::system;
22 namespace bf = boost::filesystem;
26 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
27 const char kSubsesionDir[] = "subsession";
29 bool SkipRWDirectories(const bf::path& path) {
30 static const std::vector<std::string> dirs_to_ignore = {
37 return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
41 bool RemoveSignature(const std::string& pkgid, bool is_readonly) {
42 bf::path signature_path = bf::path(is_readonly ?
43 tzplatform_getenv(TZ_SYS_RO_SHARE) : tzplatform_getenv(TZ_SYS_SHARE)) /
45 signature_path /= std::string(pkgid + ".txt");
46 if (!common_installer::Remove(signature_path))
55 namespace common_installer {
56 namespace filesystem {
58 Step::Status StepRemoveFiles::precheck() {
59 if (!context_->manifest_data.get()) {
60 LOG(ERROR) << "manifest_data attribute is empty";
61 return Step::Status::MANIFEST_NOT_FOUND;
64 // Even though, the below checks can fail, StepRemoveFiles should still try
65 // to remove the files
66 if (context_->GetPkgPath().empty())
67 LOG(ERROR) << "pkg_path attribute is empty";
68 else if (!bf::exists(context_->GetPkgPath()))
69 LOG(ERROR) << "pkg_path ("
70 << context_->GetPkgPath()
71 << ") path does not exist";
73 return Step::Status::OK;
76 Step::Status StepRemoveFiles::process() {
77 // We need to unmount external storage before removing package directory
78 // because mount point is inside
79 if (context_->external_storage)
80 context_->external_storage->Commit();
82 bool is_keep_rwdata = false;
83 if (context_->request_mode.get() != RequestMode::GLOBAL) {
84 PkgQueryInterface pkg_query(context_->pkgid.get(), kGlobalUserUid);
85 if (pkg_query.IsPackageInstalled() ||
86 context_->keep_rwdata.get())
87 is_keep_rwdata = true;
90 bool is_error = false;
91 std::vector<bf::path> root_paths;
92 // Use RootAppPath + Pkgid because of ReadonlyUpdateUninstall
93 root_paths.push_back(context_->root_application_path.get());
95 for (auto& lw_user : GetLightUserList(context_->uid.get()))
96 root_paths.push_back(context_->root_application_path.get() / kSubsesionDir /
99 for (auto& root_path : root_paths) {
100 if (is_keep_rwdata) {
102 for (bf::directory_iterator itr(root_path / context_->pkgid.get());
103 itr != bf::directory_iterator(); ++itr) {
104 if (bf::is_directory(itr->status())) {
105 if (SkipRWDirectories(itr->path().leaf())) {
106 LOG(DEBUG) << "Skipping remove dir:" << itr->path().c_str();
109 ret = RemoveAll(itr->path());
111 ret = Remove(itr->path());
117 if (!RemoveAll(root_path / context_->pkgid.get()) ||
118 !common_installer::DeleteSharedDirectories(root_path,
119 context_->pkgid.get()))
124 return Status::ERROR;
127 // Remove package files at extended storage
128 if (context_->storage.get() == Storage::EXTENDED) {
129 bf::path extended_path =
130 bf::path(GetExtendedRootAppPath(context_->uid.get())) /
131 context_->pkgid.get();
132 if (!RemoveAll(extended_path))
133 return Status::APP_DIR_ERROR;
136 for (auto& lw_user : GetLightUserList(context_->uid.get())) {
137 if (context_->storage.get() == Storage::EXTENDED) {
138 bf::path extended_path =
139 bf::path(GetExtendedRootAppPath(context_->uid.get())) /
140 kSubsesionDir / lw_user / context_->pkgid.get();
141 if (!RemoveAll(extended_path))
142 return Status::APP_DIR_ERROR;
146 // Remove stored signature file
147 if (!RemoveSignature(context_->pkgid.get(),
148 context_->is_readonly_package.get()))
149 return Status::APP_DIR_ERROR;
154 } // namespace filesystem
155 } // namespace common_installer