f8ffe9779d270ce448eda96b6354344b5a37f6fb
[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/shared_dirs.h"
20
21 namespace bs = boost::system;
22 namespace bf = boost::filesystem;
23
24 namespace {
25
26 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
27 const char kSubsesionDir[] = "subsession";
28
29 bool SkipRWDirectories(const bf::path& path) {
30   static const std::vector<std::string> dirs_to_ignore = {
31     {"cache"},
32     {"data"},
33     {"shared/data"},
34     {"shared/cache"},
35     {"shared/trusted"},
36   };
37   return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
38       dirs_to_ignore.end();
39 }
40
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)) /
44           "signatures";
45   signature_path /= std::string(pkgid + ".txt");
46   if (!common_installer::Remove(signature_path))
47     return false;
48
49   return true;
50 }
51
52 }  // namespace
53
54
55 namespace common_installer {
56 namespace filesystem {
57
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;
62   }
63
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";
72
73   return Step::Status::OK;
74 }
75
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();
81
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;
88   }
89
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());
94
95   for (auto& lw_user : GetLightUserList(context_->uid.get()))
96     root_paths.push_back(context_->root_application_path.get() / kSubsesionDir /
97                         lw_user);
98
99   for (auto& root_path : root_paths) {
100     if (is_keep_rwdata) {
101       bool ret;
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();
107             continue;
108           }
109           ret = RemoveAll(itr->path());
110         } else {
111           ret = Remove(itr->path());
112         }
113         if (!ret)
114           is_error = true;
115       }
116     } else {
117       if (!RemoveAll(root_path / context_->pkgid.get()) ||
118           !common_installer::DeleteSharedDirectories(root_path,
119               context_->pkgid.get()))
120         is_error = true;
121     }
122
123     if (is_error)
124       return Status::ERROR;
125   }
126
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;
134   }
135
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;
143     }
144   }
145
146   // Remove stored signature file
147   if (!RemoveSignature(context_->pkgid.get(),
148                         context_->is_readonly_package.get()))
149     return Status::APP_DIR_ERROR;
150
151   return Status::OK;
152 }
153
154 }  // namespace filesystem
155 }  // namespace common_installer