Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / step / filesystem / step_remove_files.cc
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.
4
5 #include "common/step/filesystem/step_remove_files.h"
6
7 #include <sys/types.h>
8 #include <tzplatform_config.h>
9
10 #include <algorithm>
11 #include <filesystem>
12 #include <string>
13 #include <vector>
14
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"
19
20 namespace fs = std::filesystem;
21
22 namespace {
23
24 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
25 const char kSubsesionDir[] = "subsession";
26
27 bool SkipRWDirectories(const fs::path& path) {
28   static const std::vector<std::string> dirs_to_ignore = {
29     {"cache"},
30     {"data"},
31     {"shared/data"},
32     {"shared/cache"},
33     {"shared/trusted"},
34   };
35   return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
36       dirs_to_ignore.end();
37 }
38
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)) /
42           "signatures";
43   signature_path /= std::string(pkgid + ".txt");
44   if (!common_installer::Remove(signature_path))
45     return false;
46
47   return true;
48 }
49
50 }  // namespace
51
52
53 namespace common_installer {
54 namespace filesystem {
55
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;
60   }
61
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";
70
71   return Step::Status::OK;
72 }
73
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();
79
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;
86   }
87
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());
92
93   for (auto& lw_user : GetLightUserList(context_->uid.get()))
94     root_paths.push_back(context_->root_application_path.get() / kSubsesionDir /
95                         lw_user);
96
97   for (auto& root_path : root_paths) {
98     if (is_keep_rwdata) {
99       bool ret;
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();
105             continue;
106           }
107           ret = RemoveAll(itr->path());
108         } else {
109           ret = Remove(itr->path());
110         }
111         if (!ret)
112           is_error = true;
113       }
114     } else {
115       if (!RemoveAll(root_path / context_->pkgid.get()) ||
116           !common_installer::DeleteSharedDirectories(root_path,
117               context_->pkgid.get()))
118         is_error = true;
119     }
120
121     if (is_error)
122       return Status::ERROR;
123   }
124
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;
132   }
133
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;
141     }
142   }
143
144   // Remove stored signature file
145   if (!RemoveSignature(context_->pkgid.get(),
146                         context_->is_readonly_package.get()))
147     return Status::APP_DIR_ERROR;
148
149   return Status::OK;
150 }
151
152 }  // namespace filesystem
153 }  // namespace common_installer