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"
9 #include "common/utils/paths.h"
10 #include "common/recovery_file.h"
11 #include "common/utils/file_util.h"
12 #include "common/utils/request.h"
14 namespace fs = std::filesystem;
18 const char kExternalMemoryMountPoint[] = ".mmc";
20 bool Move(const std::filesystem::path& from,
21 const std::filesystem::path& to,
22 common_installer::FSFlag flag = common_installer::FSFlag::FS_NONE) {
23 if (fs::is_directory(from)) {
24 if (!common_installer::MoveDir(from, to / from.filename(), flag)) {
25 LOG(ERROR) << "Failed to move directory: " << from;
29 if (!common_installer::MoveFile(from, to / from.filename())) {
30 LOG(ERROR) << "Fail to move file: " << from;
40 namespace common_installer {
41 namespace filesystem {
43 Step::Status StepRecoverFiles::RecoveryNew() {
44 if (!ClearPath(context_->GetPkgPath()))
45 return Status::RECOVERY_ERROR;
47 LOG(INFO) << "Package files recovery done";
51 Step::Status StepRecoverFiles::RecoveryUpdate() {
52 recovery::RecoveryFile* recovery_file =
53 context_->recovery_info.get().recovery_file.get();
54 bool backup_done = recovery_file->backup_done();
55 fs::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
56 if (fs::exists(backup_path)) {
57 // Remove pkgdir only if backup original contents is completely done.
59 for (fs::directory_iterator iter(context_->GetPkgPath());
60 iter != fs::directory_iterator(); ++iter) {
61 if (iter->path().filename() == kExternalMemoryMountPoint)
64 if (!ClearPath(iter->path())) {
65 LOG(ERROR) << "Cannot restore widget files to its correct location";
66 return Status::RECOVERY_ERROR;
69 // it may fail during recovery.
70 recovery_file->set_backup_done(false);
71 recovery_file->WriteAndCommitFileContent();
74 // create copy of old package content skipping the external memory mount point
75 for (fs::directory_iterator iter(backup_path);
76 iter != fs::directory_iterator(); ++iter) {
77 if (!Move(iter->path(), context_->GetPkgPath()))
78 return Status::RECOVERY_ERROR;
81 ClearPath(backup_path);
83 LOG(INFO) << "Package files recovery done";
87 Step::Status StepRecoverFiles::RecoveryMountNew() {
88 fs::path zip_location = GetZipPackageLocation(
89 context_->GetPkgPath(), context_->pkgid.get());
91 ClearPath(context_->GetPkgPath());
92 LOG(INFO) << "Package files recovery done";
96 Step::Status StepRecoverFiles::RecoveryMountUpdate() {
97 fs::path zip_location = GetZipPackageLocation(
98 context_->GetPkgPath(), context_->pkgid.get());
99 fs::path backup_zip_location = GetBackupPathForZipFile(zip_location);
100 if (fs::exists(backup_zip_location)) {
101 Remove(zip_location);
102 if (!MoveFile(backup_zip_location, zip_location))
103 LOG(ERROR) << "Failed to move " << backup_zip_location << " to "
107 // During mount update some files are still backed up separately from zip
108 // package file. This is because of the fact that we need to access bin/, lib/
109 // directories without mounting zip package file. In other words in mount
110 // install or mount update mode we don't mount everything - some files are
111 // still unpacked due to necessity.
112 fs::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
113 if (fs::exists(backup_path)) {
114 for (fs::directory_iterator iter(backup_path);
115 iter != fs::directory_iterator(); ++iter) {
116 ClearPath(context_->GetPkgPath() / iter->path().filename());
117 if (!Move(iter->path(), context_->GetPkgPath())) {
118 LOG(ERROR) << "Failed to recovery backup file(" << iter->path()
119 << ") in recovery of mount update";
120 return Status::RECOVERY_ERROR;
123 ClearPath(backup_path);
126 LOG(INFO) << "Package files recovery done";
130 Step::Status StepRecoverFiles::RecoveryReadonlyUpdateInstall() {
131 // Remove package directory at RW area
133 fs::path(GetRootAppPath(false, context_->uid.get())) /
134 context_->pkgid.get();
135 if (!ClearPath(pkg_path))
136 return Status::RECOVERY_ERROR;
138 LOG(INFO) << "Package files recovery done";
142 Step::Status StepRecoverFiles::Cleanup() {
143 recovery::RecoveryFile* recovery_file =
144 context_->recovery_info.get().recovery_file.get();
145 fs::path root_path(GetRootAppPath(
146 context_->is_readonly_package.get(), context_->uid.get()));
147 fs::path backup_path = GetBackupPathForPackagePath(
148 root_path / recovery_file->pkgid());
149 if (!fs::exists(backup_path))
152 if (!ClearPath(backup_path)) {
153 LOG(ERROR) << "Failed to remove backup path";
154 return Status::RECOVERY_ERROR;
160 bool StepRecoverFiles::ClearPath(const fs::path& path) {
161 return RemoveAll(path);
164 } // namespace filesystem
165 } // namespace common_installer