1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by a apache 2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/step/backup/step_copy_backup.h"
7 #include <boost/filesystem/operations.hpp>
8 #include <boost/system/error_code.hpp>
13 #include "common/backup_paths.h"
14 #include "common/utils/file_util.h"
18 const char kExternalMemoryMountPoint[] = ".mmc";
22 namespace common_installer {
25 namespace bf = boost::filesystem;
26 namespace bs = boost::system;
28 Step::Status StepCopyBackup::precheck() {
29 if (context_->pkgid.get().empty()) {
30 LOG(ERROR) << "pkgid attribute is empty";
31 return Step::Status::PACKAGE_NOT_FOUND;
33 if (context_->root_application_path.get().empty()) {
34 LOG(ERROR) << "root_application_path attribute is empty";
35 return Step::Status::INVALID_VALUE;
39 context_->pkg_path.set(
40 context_->root_application_path.get() / context_->pkgid.get());
41 install_path_ = context_->pkg_path.get();
42 backup_path_ = GetBackupPathForPackagePath(context_->pkg_path.get());
47 Step::Status StepCopyBackup::process() {
49 return Status::APP_DIR_ERROR;
52 return Status::APP_DIR_ERROR;
57 Step::Status StepCopyBackup::clean() {
58 if (!CleanBackupDirectory()) {
59 LOG(DEBUG) << "Cannot remove backup directory";
60 return Status::APP_DIR_ERROR;
62 LOG(DEBUG) << "Applications files backup directory removed";
64 if (context_->external_storage)
65 context_->external_storage->Commit();
70 Step::Status StepCopyBackup::undo() {
71 // TODO(t.iwanek): this should be done in StepUnzip
73 LOG(DEBUG) << "Remove tmp dir: " << context_->unpacked_dir_path.get();
74 bf::remove_all(context_->unpacked_dir_path.get(), error); // ignore error
76 if (context_->external_storage)
77 context_->external_storage->Abort();
79 // if backup was created then restore files
80 if (bf::exists(backup_path_)) {
81 if (!RollbackApplicationDirectory()) {
82 LOG(ERROR) << "Failed to revert package directory";
83 return Status::APP_DIR_ERROR;
85 LOG(DEBUG) << "Application files reverted from backup";
90 bool StepCopyBackup::Backup() {
91 // create backup directory
93 bf::create_directories(backup_path_, error);
95 // create copy of old package content skipping the external memory mount point
96 for (bf::directory_iterator iter(context_->pkg_path.get());
97 iter != bf::directory_iterator(); ++iter) {
98 if (iter->path().filename() == kExternalMemoryMountPoint)
101 // external storage directories are mounted
102 // therefore move only content
103 if (context_->external_storage) {
104 auto& ext_dirs = context_->external_storage->external_dirs();
105 auto found = std::find(ext_dirs.begin(), ext_dirs.end(),
106 iter->path().filename());
107 if (found != ext_dirs.end()) {
108 bool done = MoveMountPointContent(iter->path(),
109 backup_path_ / iter->path().filename());
111 LOG(ERROR) << "Failed to move: " << iter->path();
118 if (bf::is_directory(iter->path())) {
119 if (!MoveDir(iter->path(), backup_path_ / iter->path().filename())) {
120 LOG(ERROR) << "Fail to backup package directory of: " << iter->path();
124 if (!MoveFile(iter->path(), backup_path_ / iter->path().filename())) {
125 LOG(ERROR) << "Fail to backup package file: " << iter->path();
130 LOG(INFO) << "Old package context saved to: " << backup_path_;
135 bool StepCopyBackup::MoveMountPointContent(const boost::filesystem::path& from,
136 const boost::filesystem::path& to) {
137 bs::error_code error;
138 bf::create_directories(to, error);
140 for (bf::directory_iterator iter(from);
141 iter != bf::directory_iterator(); ++iter) {
142 if (bf::is_directory(iter->path())) {
143 if (!MoveDir(iter->path(), to / iter->path().filename())) {
144 LOG(ERROR) << "Fail to backup package directory of: " << iter->path();
147 } else if (bf::is_symlink(iter->path())) {
148 bs::error_code error;
149 bf::copy_symlink(iter->path(), to / iter->path().filename(), error);
151 LOG(ERROR) << "Failed to backup package symlink: " << iter->path();
155 if (!MoveFile(iter->path(), to / iter->path().filename())) {
156 LOG(ERROR) << "Fail to backup package file: " << iter->path();
164 bool StepCopyBackup::NewContent() {
165 bs::error_code error;
166 bf::create_directories(install_path_.parent_path(), error);
168 LOG(ERROR) << "Cannot create package directory";
171 if (!MoveDir(context_->unpacked_dir_path.get(), install_path_,
172 FSFlag::FS_MERGE_DIRECTORIES)) {
173 LOG(ERROR) << "Fail to copy tmp dir: " << context_->unpacked_dir_path.get()
174 << " to dst dir: " << install_path_;
178 LOG(INFO) << "Successfully move: " << context_->unpacked_dir_path.get()
179 << " to: " << install_path_ << " directory";
184 bool StepCopyBackup::CleanBackupDirectory() {
185 if (bf::exists(backup_path_)) {
186 bs::error_code error;
187 bf::remove_all(backup_path_, error);
194 bool StepCopyBackup::RollbackApplicationDirectory() {
195 bs::error_code error;
196 if (bf::exists(context_->pkg_path.get())) {
197 bf::remove_all(context_->pkg_path.get(), error);
203 if (!MoveDir(backup_path_, context_->pkg_path.get())) {
210 } // namespace backup
211 } // namespace common_installer