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"
8 #include <tzplatform_config.h>
15 #include "common/utils/pkgmgr_query.h"
16 #include "common/utils/file_util.h"
17 #include "common/utils/user_util.h"
18 #include "common/shared_dirs.h"
20 namespace fs = std::filesystem;
24 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
25 const char kSubsesionDir[] = "subsession";
27 bool SkipRWDirectories(const fs::path& path) {
28 static const std::vector<std::string> dirs_to_ignore = {
35 return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
39 bool RemoveSignature(const std::string& pkgid, bool is_readonly) {
40 fs::path signature_path = fs::path(is_readonly ?
41 tzplatform_getenv(TZ_SYS_RO_SHARE) : tzplatform_getenv(TZ_SYS_SHARE)) /
43 signature_path /= std::string(pkgid + ".txt");
44 if (!common_installer::Remove(signature_path))
53 namespace common_installer {
54 namespace filesystem {
56 Step::Status StepRemoveFiles::precheck() {
57 if (!context_->manifest_data.get()) {
58 LOG(ERROR) << "manifest_data attribute is empty";
59 return Step::Status::MANIFEST_NOT_FOUND;
62 // Even though, the below checks can fail, StepRemoveFiles should still try
63 // to remove the files
64 if (context_->GetPkgPath().empty())
65 LOG(ERROR) << "pkg_path attribute is empty";
66 else if (!fs::exists(context_->GetPkgPath()))
67 LOG(ERROR) << "pkg_path ("
68 << context_->GetPkgPath()
69 << ") path does not exist";
71 return Step::Status::OK;
74 Step::Status StepRemoveFiles::process() {
75 // We need to unmount external storage before removing package directory
76 // because mount point is inside
77 if (context_->external_storage)
78 context_->external_storage->Commit();
80 bool is_keep_rwdata = false;
81 if (context_->request_mode.get() != RequestMode::GLOBAL) {
82 PkgQueryInterface pkg_query(context_->pkgid.get(), kGlobalUserUid);
83 if (pkg_query.IsPackageInstalled() ||
84 context_->keep_rwdata.get())
85 is_keep_rwdata = true;
88 bool is_error = false;
89 std::vector<fs::path> root_paths;
90 // Use RootAppPath + Pkgid because of ReadonlyUpdateUninstall
91 root_paths.push_back(context_->root_application_path.get());
93 for (auto& lw_user : GetLightUserList(context_->uid.get()))
94 root_paths.push_back(context_->root_application_path.get() / kSubsesionDir /
97 for (auto& root_path : root_paths) {
100 for (fs::directory_iterator itr(root_path / context_->pkgid.get());
101 itr != fs::directory_iterator(); ++itr) {
102 if (fs::is_directory(itr->status())) {
103 if (SkipRWDirectories(itr->path().filename())) {
104 LOG(DEBUG) << "Skipping remove dir:" << itr->path().c_str();
107 ret = RemoveAll(itr->path());
109 ret = Remove(itr->path());
115 if (!RemoveAll(root_path / context_->pkgid.get()) ||
116 !common_installer::DeleteSharedDirectories(root_path,
117 context_->pkgid.get()))
122 return Status::ERROR;
125 // Remove package files at extended storage
126 if (context_->storage.get() == Storage::EXTENDED) {
127 fs::path extended_path =
128 fs::path(GetExtendedRootAppPath(context_->uid.get())) /
129 context_->pkgid.get();
130 if (!RemoveAll(extended_path))
131 return Status::APP_DIR_ERROR;
134 for (auto& lw_user : GetLightUserList(context_->uid.get())) {
135 if (context_->storage.get() == Storage::EXTENDED) {
136 fs::path extended_path =
137 fs::path(GetExtendedRootAppPath(context_->uid.get())) /
138 kSubsesionDir / lw_user / context_->pkgid.get();
139 if (!RemoveAll(extended_path))
140 return Status::APP_DIR_ERROR;
144 // Remove stored signature file
145 if (!RemoveSignature(context_->pkgid.get(),
146 context_->is_readonly_package.get()))
147 return Status::APP_DIR_ERROR;
152 } // namespace filesystem
153 } // namespace common_installer