1 // Copyright (c) 2015 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_recover_files.h"
7 #include <boost/filesystem/operations.hpp>
8 #include <boost/filesystem/path.hpp>
9 #include <boost/system/error_code.hpp>
11 #include "common/utils/paths.h"
12 #include "common/recovery_file.h"
13 #include "common/utils/file_util.h"
14 #include "common/utils/request.h"
16 namespace bf = boost::filesystem;
17 namespace bs = boost::system;
21 const char kExternalMemoryMountPoint[] = ".mmc";
23 bool Move(const boost::filesystem::path& from,
24 const boost::filesystem::path& to,
25 common_installer::FSFlag flag = common_installer::FSFlag::FS_NONE) {
26 if (bf::is_directory(from)) {
27 if (!common_installer::MoveDir(from, to / from.filename(), flag)) {
28 LOG(ERROR) << "Failed to move directory: " << from;
32 if (!common_installer::MoveFile(from, to / from.filename())) {
33 LOG(ERROR) << "Fail to move file: " << from;
43 namespace common_installer {
44 namespace filesystem {
46 Step::Status StepRecoverFiles::RecoveryNew() {
47 if (!ClearPath(context_->GetPkgPath()))
48 return Status::RECOVERY_ERROR;
50 LOG(INFO) << "Package files recovery done";
54 Step::Status StepRecoverFiles::RecoveryUpdate() {
55 recovery::RecoveryFile* recovery_file =
56 context_->recovery_info.get().recovery_file.get();
57 bool backup_done = recovery_file->backup_done();
58 bf::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
59 if (bf::exists(backup_path)) {
60 // Remove pkgdir only if backup original contents is completely done.
62 for (bf::directory_iterator iter(context_->GetPkgPath());
63 iter != bf::directory_iterator(); ++iter) {
64 if (iter->path().filename() == kExternalMemoryMountPoint)
67 if (!ClearPath(iter->path())) {
68 LOG(ERROR) << "Cannot restore widget files to its correct location";
69 return Status::RECOVERY_ERROR;
72 // it may fail during recovery.
73 recovery_file->set_backup_done(false);
74 recovery_file->WriteAndCommitFileContent();
77 // create copy of old package content skipping the external memory mount point
78 for (bf::directory_iterator iter(backup_path);
79 iter != bf::directory_iterator(); ++iter) {
80 if (!Move(iter->path(), context_->GetPkgPath()))
81 return Status::RECOVERY_ERROR;
84 ClearPath(backup_path);
86 LOG(INFO) << "Package files recovery done";
90 Step::Status StepRecoverFiles::RecoveryMountNew() {
91 bf::path zip_location = GetZipPackageLocation(
92 context_->GetPkgPath(), context_->pkgid.get());
94 ClearPath(context_->GetPkgPath());
95 LOG(INFO) << "Package files recovery done";
99 Step::Status StepRecoverFiles::RecoveryMountUpdate() {
100 bf::path zip_location = GetZipPackageLocation(
101 context_->GetPkgPath(), context_->pkgid.get());
102 bf::path backup_zip_location = GetBackupPathForZipFile(zip_location);
103 if (bf::exists(backup_zip_location)) {
104 Remove(zip_location);
105 if (!MoveFile(backup_zip_location, zip_location))
106 LOG(ERROR) << "Failed to move " << backup_zip_location << " to "
110 // During mount update some files are still backed up separately from zip
111 // package file. This is because of the fact that we need to access bin/, lib/
112 // directories without mounting zip package file. In other words in mount
113 // install or mount update mode we don't mount everything - some files are
114 // still unpacked due to necessity.
115 bf::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
116 if (bf::exists(backup_path)) {
117 for (bf::directory_iterator iter(backup_path);
118 iter != bf::directory_iterator(); ++iter) {
119 ClearPath(context_->GetPkgPath() / iter->path().filename());
120 if (!Move(iter->path(), context_->GetPkgPath())) {
121 LOG(ERROR) << "Failed to recovery backup file(" << iter->path()
122 << ") in recovery of mount update";
123 return Status::RECOVERY_ERROR;
126 ClearPath(backup_path);
129 LOG(INFO) << "Package files recovery done";
133 Step::Status StepRecoverFiles::RecoveryReadonlyUpdateInstall() {
134 // Remove package directory at RW area
136 bf::path(GetRootAppPath(false, context_->uid.get())) /
137 context_->pkgid.get();
138 if (!ClearPath(pkg_path))
139 return Status::RECOVERY_ERROR;
141 LOG(INFO) << "Package files recovery done";
145 Step::Status StepRecoverFiles::Cleanup() {
146 recovery::RecoveryFile* recovery_file =
147 context_->recovery_info.get().recovery_file.get();
148 bf::path root_path(GetRootAppPath(
149 context_->is_readonly_package.get(), context_->uid.get()));
150 bf::path backup_path = GetBackupPathForPackagePath(
151 root_path / recovery_file->pkgid());
152 if (!bf::exists(backup_path))
155 if (!ClearPath(backup_path)) {
156 LOG(ERROR) << "Failed to remove backup path";
157 return Status::RECOVERY_ERROR;
163 bool StepRecoverFiles::ClearPath(const bf::path& path) {
164 return RemoveAll(path);
167 } // namespace filesystem
168 } // namespace common_installer