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.
5 #include "common/step/filesystem/step_move_installed_storage.h"
7 #include <boost/filesystem/path.hpp>
8 #include <boost/system/error_code.hpp>
9 #include <tzplatform_config.h>
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"
21 namespace bf = boost::filesystem;
22 namespace bs = boost::system;
26 const char kInternalOnly[] = "internal-only";
28 bool MoveFileAndUpdateTepInfo(const boost::filesystem::path& src,
29 const boost::filesystem::path& dst,
30 const common_installer::InstallerContext* context) {
34 if (!common_installer::MoveFile(src, dst)) {
35 LOG(ERROR) << "Cannot move tep file from: " << src
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";
50 namespace common_installer {
51 namespace filesystem {
53 StepMoveInstalledStorage::StepMoveInstalledStorage(InstallerContext* context)
54 : Step(context), move_type_(MoveType::NONE) {
57 Step::Status StepMoveInstalledStorage::process() {
58 PkgQueryInterface pkg_query(context_->pkgid.get(),
60 std::string installed_storage = pkg_query.StorageForPkgId();
62 if ((move_type_ == MoveType::TO_INTERNAL &&
63 installed_storage == "installed_external") ||
64 (move_type_ == MoveType::TO_EXTERNAL &&
65 installed_storage == "installed_internal")) {
67 return Status::APP_DIR_ERROR;
69 (move_type_ == MoveType::TO_INTERNAL &&
70 installed_storage == "installed_extended") ||
71 (move_type_ == MoveType::TO_EXTENDED &&
72 installed_storage == "installed_internal")) {
74 return Status::APP_DIR_ERROR;
79 Step::Status StepMoveInstalledStorage::undo() {
80 if (context_->external_storage) {
81 if (new_tep_location_ != old_tep_location_)
83 return Status::APP_DIR_ERROR;
86 if (!MoveBackExtended())
87 return Status::APP_DIR_ERROR;
92 Step::Status StepMoveInstalledStorage::clean() {
93 if (context_->external_storage)
94 context_->external_storage->Commit();
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;
104 if (!strcmp(context_->manifest_data.get()->installlocation, kInternalOnly)) {
105 LOG(ERROR) << "This package is interanl-only";
106 return Status::OPERATION_NOT_ALLOWED;
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();
118 new_tep_location_ = GetInternalTepPath(context_->GetPkgPath()) /
119 old_tep_location_.filename();
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);
128 LOG(ERROR) << "Failed to destination path for new tep location";
133 return MoveFileAndUpdateTepInfo(old_tep_location_, new_tep_location_,
137 bool StepMoveInstalledStorage::MoveBackTep() {
138 return MoveFileAndUpdateTepInfo(new_tep_location_, old_tep_location_,
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(),
149 context_->is_move_to_external.get());
150 if (!context_->external_storage) {
151 LOG(ERROR) << "Cannot initialize external storage for move";
156 if (context_->manifest_data.get()->tep_name) {
159 if (new_tep_location_ != old_tep_location_)
166 bool StepMoveInstalledStorage::MoveBackExternal() {
167 context_->external_storage->Abort();
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);
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);
186 if (move_type_ == MoveType::TO_INTERNAL) {
187 // remove existing symlink
188 if (!Remove(new_pkg_location_))
192 if (!MoveDir(old_pkg_location_, new_pkg_location_))
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);
200 LOG(ERROR) << "Failed to create symlink for extended path: "
205 if (!SetPackageDirectoryOwnerAndPermissions(new_pkg_location_,
206 context_->uid.get())) {
207 LOG(ERROR) << "Failed to set directory ownership";
211 if (!UpdateInstalledStorageInPkgmgr(context_->storage.get(),
212 new_pkg_location_, context_->pkgid.get(), context_->uid.get()))
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";
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);
233 LOG(ERROR) << "Failed to create symlink for extended path: "
239 if (!SetPackageDirectoryOwnerAndPermissions(old_pkg_location_,
240 context_->uid.get())) {
241 LOG(ERROR) << "Failed to set directory ownership";
248 } // namespace filesystem
249 } // namespace common_installer