Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / step / filesystem / step_recover_files.cc
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.
4
5 #include "common/step/filesystem/step_recover_files.h"
6
7 #include <filesystem>
8
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"
13
14 namespace fs = std::filesystem;
15
16 namespace {
17
18 const char kExternalMemoryMountPoint[] = ".mmc";
19
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;
26       return false;
27     }
28   } else {
29     if (!common_installer::MoveFile(from, to / from.filename())) {
30       LOG(ERROR) << "Fail to move file: " << from;
31       return false;
32     }
33   }
34
35   return true;
36 }
37
38 }  // namespace
39
40 namespace common_installer {
41 namespace filesystem {
42
43 Step::Status StepRecoverFiles::RecoveryNew() {
44   if (!ClearPath(context_->GetPkgPath()))
45     return Status::RECOVERY_ERROR;
46
47   LOG(INFO) << "Package files recovery done";
48   return Status::OK;
49 }
50
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.
58     if (backup_done) {
59       for (fs::directory_iterator iter(context_->GetPkgPath());
60            iter != fs::directory_iterator(); ++iter) {
61         if (iter->path().filename() == kExternalMemoryMountPoint)
62           continue;
63
64         if (!ClearPath(iter->path())) {
65           LOG(ERROR) << "Cannot restore widget files to its correct location";
66           return Status::RECOVERY_ERROR;
67         }
68       }
69       // it may fail during recovery.
70       recovery_file->set_backup_done(false);
71       recovery_file->WriteAndCommitFileContent();
72     }
73
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;
79     }
80
81     ClearPath(backup_path);
82   }
83   LOG(INFO) << "Package files recovery done";
84   return Status::OK;
85 }
86
87 Step::Status StepRecoverFiles::RecoveryMountNew() {
88   fs::path zip_location = GetZipPackageLocation(
89         context_->GetPkgPath(), context_->pkgid.get());
90   Remove(zip_location);
91   ClearPath(context_->GetPkgPath());
92   LOG(INFO) << "Package files recovery done";
93   return Status::OK;
94 }
95
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 "
104           << zip_location;
105   }
106
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;
121       }
122     }
123     ClearPath(backup_path);
124   }
125
126   LOG(INFO) << "Package files recovery done";
127   return Status::OK;
128 }
129
130 Step::Status StepRecoverFiles::RecoveryReadonlyUpdateInstall() {
131   // Remove package directory at RW area
132   fs::path pkg_path =
133       fs::path(GetRootAppPath(false, context_->uid.get())) /
134       context_->pkgid.get();
135   if (!ClearPath(pkg_path))
136     return Status::RECOVERY_ERROR;
137
138   LOG(INFO) << "Package files recovery done";
139   return Status::OK;
140 }
141
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))
150     return Status::OK;
151
152   if (!ClearPath(backup_path)) {
153     LOG(ERROR) << "Failed to remove backup path";
154     return Status::RECOVERY_ERROR;
155   }
156
157   return Status::OK;
158 }
159
160 bool StepRecoverFiles::ClearPath(const fs::path& path) {
161   return RemoveAll(path);
162 }
163
164 }  // namespace filesystem
165 }  // namespace common_installer