Move GetLightUserList() to user_util.h
[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 <boost/filesystem/operations.hpp>
8 #include <boost/system/error_code.hpp>
9
10 #include <sys/types.h>
11 #include <tzplatform_config.h>
12
13 #include <algorithm>
14 #include <string>
15 #include <vector>
16
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"
21
22 namespace bs = boost::system;
23 namespace bf = boost::filesystem;
24
25 namespace {
26
27 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
28 const char kSubsesionDir[] = "subsession";
29
30 bool SkipRWDirectories(const bf::path& path) {
31   static const std::vector<std::string> dirs_to_ignore = {
32     {"cache"},
33     {"data"},
34     {"shared/data"},
35     {"shared/cache"},
36     {"shared/trusted"},
37   };
38   return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
39       dirs_to_ignore.end();
40 }
41
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)) /
45           "signatures";
46   signature_path /= std::string(pkgid + ".txt");
47   if (!common_installer::Remove(signature_path))
48     return false;
49
50   return true;
51 }
52
53 }  // namespace
54
55
56 namespace common_installer {
57 namespace filesystem {
58
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;
63   }
64
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";
73
74   return Step::Status::OK;
75 }
76
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();
82
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;
89   }
90
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());
95
96   for (auto& lw_user : GetLightUserList(context_->uid.get()))
97     root_paths.push_back(context_->root_application_path.get() / kSubsesionDir /
98                         lw_user);
99
100   for (auto& root_path : root_paths) {
101     if (is_keep_rwdata) {
102       bool ret;
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();
108             continue;
109           }
110           ret = RemoveAll(itr->path());
111         } else {
112           ret = Remove(itr->path());
113         }
114         if (!ret)
115           is_error = true;
116       }
117     } else {
118       if (!RemoveAll(root_path / context_->pkgid.get()) ||
119           !common_installer::DeleteSharedDirectories(root_path,
120               context_->pkgid.get()))
121         is_error = true;
122     }
123
124     if (is_error)
125       return Status::ERROR;
126   }
127
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;
135   }
136
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;
144     }
145   }
146
147   // Remove stored signature file
148   if (!RemoveSignature(context_->pkgid.get(),
149                         context_->is_readonly_package.get()))
150     return Status::APP_DIR_ERROR;
151
152   return Status::OK;
153 }
154
155 }  // namespace filesystem
156 }  // namespace common_installer