Fix static analysis issues
[platform/core/appfw/app-installers.git] / src / common / step / filesystem / step_move_installed_storage.cc
1 // Copyright (c) 2016 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_move_installed_storage.h"
6
7 #include <boost/filesystem/path.hpp>
8 #include <boost/system/error_code.hpp>
9 #include <tzplatform_config.h>
10
11 #include <string>
12 #include <cstring>
13
14 #include "common/external_storage.h"
15 #include "common/shared_dirs.h"
16 #include "common/utils/file_util.h"
17 #include "common/utils/paths.h"
18 #include "common/pkgmgr_registration.h"
19 #include "common/utils/pkgmgr_query.h"
20
21 namespace bf = boost::filesystem;
22 namespace bs = boost::system;
23
24 namespace {
25
26 const char kInternalOnly[] = "internal-only";
27
28 bool MoveFileAndUpdateTepInfo(const boost::filesystem::path& src,
29     const boost::filesystem::path& dst,
30     const common_installer::InstallerContext* context) {
31   if (!bf::exists(src))
32     return true;
33
34   if (!common_installer::MoveFile(src, dst)) {
35     LOG(ERROR) << "Cannot move tep file from: " << src
36                << " to " << dst;
37     return false;
38   }
39
40   if (!common_installer::UpdateTepInfoInPkgmgr(dst, context->pkgid.get(),
41       context->uid.get(), context->request_mode.get())) {
42     LOG(ERROR) << "Failed to update tep package location in pkgmgr";
43     return false;
44   }
45   return true;
46 }
47
48 }  // namespace
49
50 namespace common_installer {
51 namespace filesystem {
52
53 StepMoveInstalledStorage::StepMoveInstalledStorage(InstallerContext* context)
54     : Step(context), move_type_(MoveType::NONE) {
55 }
56
57 Step::Status StepMoveInstalledStorage::process() {
58   PkgQueryInterface pkg_query(context_->pkgid.get(),
59       context_->uid.get());
60   std::string installed_storage = pkg_query.StorageForPkgId();
61
62   if ((move_type_ == MoveType::TO_INTERNAL &&
63           installed_storage == "installed_external") ||
64       (move_type_ == MoveType::TO_EXTERNAL &&
65           installed_storage == "installed_internal")) {
66     if (!MoveExternal())
67       return Status::APP_DIR_ERROR;
68   } else if (
69       (move_type_ == MoveType::TO_INTERNAL &&
70           installed_storage == "installed_extended") ||
71       (move_type_ == MoveType::TO_EXTENDED &&
72           installed_storage == "installed_internal")) {
73     if (!MoveExtended())
74       return Status::APP_DIR_ERROR;
75   }
76   return Status::OK;
77 }
78
79 Step::Status StepMoveInstalledStorage::undo() {
80   if (context_->external_storage) {
81     if (new_tep_location_ != old_tep_location_)
82       if (!MoveBackTep())
83         return Status::APP_DIR_ERROR;
84     MoveBackExternal();
85   } else {
86     if (!MoveBackExtended())
87       return Status::APP_DIR_ERROR;
88   }
89   return Status::OK;
90 }
91
92 Step::Status StepMoveInstalledStorage::clean() {
93   if (context_->external_storage)
94     context_->external_storage->Commit();
95   return Status::OK;
96 }
97
98 Step::Status StepMoveInstalledStorage::precheck() {
99   move_type_ = context_->move_type.get();
100   if (context_->manifest_data.get()->installlocation == nullptr) {
101     LOG(ERROR) << "Cannot get installlocation value";
102     return Status::INVALID_VALUE;
103   }
104   if (!strcmp(context_->manifest_data.get()->installlocation, kInternalOnly)) {
105     LOG(ERROR) << "This package is interanl-only";
106     return Status::OPERATION_NOT_ALLOWED;
107   }
108   return Status::OK;
109 }
110
111 void StepMoveInstalledStorage::SetTepPaths() {
112   old_tep_location_ = context_->manifest_data.get()->tep_name;
113   if (context_->is_move_to_external.get()) {
114     new_tep_location_ = GetExternalTepPath(context_->request_mode.get(),
115                                        context_->uid.get());
116     new_tep_location_ /= old_tep_location_.filename();
117   } else {
118     new_tep_location_ = GetInternalTepPath(context_->GetPkgPath()) /
119         old_tep_location_.filename();
120   }
121 }
122
123 bool StepMoveInstalledStorage::MoveTep() {
124   if (!bf::exists(new_tep_location_.parent_path())) {
125     bs::error_code error;
126     bf::create_directory(new_tep_location_.parent_path(), error);
127     if (error) {
128       LOG(ERROR) << "Failed to destination path for new tep location";
129       return false;
130     }
131   }
132
133   return MoveFileAndUpdateTepInfo(old_tep_location_, new_tep_location_,
134       context_);
135 }
136
137 bool StepMoveInstalledStorage::MoveBackTep() {
138   return MoveFileAndUpdateTepInfo(new_tep_location_, old_tep_location_,
139       context_);
140 }
141
142 bool StepMoveInstalledStorage::MoveExternal() {
143   context_->external_storage =
144       ExternalStorage::MoveInstalledStorage(context_->request_type.get(),
145           context_->root_application_path.get(),
146           context_->pkgid.get(),
147           context_->pkg_type.get(),
148           context_->uid.get(),
149           context_->is_move_to_external.get());
150   if (!context_->external_storage) {
151     LOG(ERROR) << "Cannot initialize external storage for move";
152     return false;
153   }
154
155   // move tep
156   if (context_->manifest_data.get()->tep_name) {
157     SetTepPaths();
158
159     if (new_tep_location_ != old_tep_location_)
160       if (!MoveTep())
161         return false;
162   }
163   return true;
164 }
165
166 bool StepMoveInstalledStorage::MoveBackExternal() {
167   context_->external_storage->Abort();
168   return true;
169 }
170
171 bool StepMoveInstalledStorage::MoveExtended() {
172   if (move_type_ == MoveType::TO_EXTENDED) {
173     old_pkg_location_ = context_->GetPkgPath();
174     new_pkg_location_ = bf::path(GetExtendedRootAppPath(context_->uid.get())) /
175         context_->pkgid.get();
176     context_->storage.set(Storage::EXTENDED);
177   } else {
178     old_pkg_location_ = bf::path(GetExtendedRootAppPath(context_->uid.get())) /
179         context_->pkgid.get();
180     new_pkg_location_ = bf::path(GetRootAppPath(
181         context_->is_readonly_package.get(), context_->uid.get())) /
182         context_->pkgid.get();
183     context_->storage.set(Storage::INTERNAL);
184   }
185
186   if (move_type_ == MoveType::TO_INTERNAL) {
187     // remove existing symlink
188     if (!Remove(new_pkg_location_))
189       return false;
190   }
191
192   if (!MoveDir(old_pkg_location_, new_pkg_location_))
193     return false;
194
195   // create symlink for extended path
196   if (move_type_ == MoveType::TO_EXTENDED) {
197     bs::error_code error;
198     bf::create_symlink(new_pkg_location_, old_pkg_location_, error);
199     if (error) {
200       LOG(ERROR) << "Failed to create symlink for extended path: "
201                  << error.message();
202     }
203   }
204
205   if (!SetPackageDirectoryOwnerAndPermissions(new_pkg_location_,
206       context_->uid.get())) {
207     LOG(ERROR) << "Failed to set directory ownership";
208     return false;
209   }
210
211   if (!UpdateInstalledStorageInPkgmgr(context_->storage.get(),
212       new_pkg_location_, context_->pkgid.get(), context_->uid.get()))
213     return false;
214   return true;
215 }
216
217 bool StepMoveInstalledStorage::MoveBackExtended() {
218   if (move_type_ == MoveType::TO_EXTENDED) {
219     // Remove symlink if exist
220     if (bf::exists(old_pkg_location_) &&
221         bf::is_symlink(symlink_status(old_pkg_location_))) {
222       if (!Remove(old_pkg_location_)) {
223         LOG(ERROR) << "Failed to remove symlink for extended path";
224         return false;
225       }
226     }
227   }
228   MoveDir(new_pkg_location_, old_pkg_location_);
229   if (move_type_ == MoveType::TO_INTERNAL) {
230     bs::error_code error;
231     bf::create_symlink(old_pkg_location_, new_pkg_location_, error);
232     if (error) {
233       LOG(ERROR) << "Failed to create symlink for extended path: "
234                  << error.message();
235       return false;
236     }
237   }
238
239   if (!SetPackageDirectoryOwnerAndPermissions(old_pkg_location_,
240       context_->uid.get())) {
241     LOG(ERROR) << "Failed to set directory ownership";
242     return false;
243   }
244
245   return true;
246 }
247
248 }  // namespace filesystem
249 }  // namespace common_installer
250