Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / step / rds / step_rds_modify.cc
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.
4
5 #include "common/step/rds/step_rds_modify.h"
6
7 #include <manifest_parser/utils/logging.h>
8
9 #include <filesystem>
10
11 #include "common/utils/file_util.h"
12
13 namespace ci = common_installer;
14 namespace fs = std::filesystem;
15
16 namespace common_installer {
17 namespace rds {
18
19
20 StepRDSModify::StepRDSModify(InstallerContext* context)
21     : Step(context) {}
22
23 Step::Status StepRDSModify::precheck() {
24   if (context_->unpacked_dir_path.get().empty()) {
25     LOG(ERROR) << "unpacked dir path is not set";
26     return common_installer::Step::Status::INVALID_VALUE;
27   }
28   if (!fs::exists(context_->unpacked_dir_path.get())) {
29     LOG(ERROR) << "unpacked_dir_path ("
30                << context_->unpacked_dir_path.get()
31                << ") path does not exist";
32     return Step::Status::INVALID_VALUE;
33   }
34   if (context_->root_application_path.get().empty()) {
35     LOG(ERROR) << "pkgid is not set";
36     return Step::Status::PACKAGE_NOT_FOUND;
37   }
38   if (context_->pkgid.get().empty()) {
39     LOG(ERROR) << "pkgid is not set";
40     return Step::Status::PACKAGE_NOT_FOUND;
41   }
42   if (!context_->manifest_data.get()) {
43     LOG(ERROR) << "no manifest info available";
44     return Step::Status::INVALID_VALUE;
45   }
46   return Step::Status::OK;
47 }
48
49 Step::Status StepRDSModify::process() {
50   LOG(INFO) << "entered process of step modify";
51   if (!SetUpTempBackupDir()) {
52     LOG(ERROR) << "unable to setup temp directory";
53     return Step::Status::ERROR;
54   }
55   fs::path install_path = context_->GetPkgPath();
56   fs::path unzip_path = context_->unpacked_dir_path.get();
57   if (!AddFiles(unzip_path, install_path) ||
58      !ModifyFiles(unzip_path, install_path) ||
59      !DeleteFiles(install_path)) {
60     LOG(ERROR) << "error during file operation";
61     return Step::Status::ERROR;
62   }
63   return Step::Status::OK;
64 }
65
66 Step::Status StepRDSModify::undo() {
67   RestoreFiles();
68   return Step::Status::OK;
69 }
70
71 Step::Status StepRDSModify::clean() {
72   RemoveAll(backup_temp_dir_);
73   return Step::Status::OK;
74 }
75
76 bool StepRDSModify::AddFiles(fs::path unzip_path, fs::path install_path) {
77   LOG(INFO) << "about to add files";
78   std::error_code error;
79   for (const auto& file : context_->files_to_add.get()) {
80     if (!PerformBackup(file, Operation::ADD)) {
81       LOG(ERROR) << "unable to perform backup of added file";
82       return false;
83     }
84     fs::path temp_install_path(install_path / file);
85     if (fs::is_directory(temp_install_path)) {
86       if (!fs::exists(temp_install_path) &&
87          (!CreateDir(temp_install_path))) {
88         LOG(ERROR) << "unable to create dir for temp backup data";
89         return false;
90       }
91     } else {
92       if (!fs::exists(temp_install_path.parent_path()) &&
93           !CreateDir(temp_install_path.parent_path())) {
94         LOG(ERROR) << "unable to create dir for temp backup data";
95         return false;
96       }
97       fs::path temp_unzip_path(unzip_path / file);
98       fs::copy_file(temp_unzip_path, temp_install_path, error);
99       if (error) {
100         LOG(ERROR) << "unable to add file " << error.message();
101         return false;
102       }
103     }
104   }
105   return true;
106 }
107
108 bool StepRDSModify::ModifyFiles(fs::path unzip_path, fs::path install_path) {
109   LOG(INFO) << "about to modify files";
110   std::error_code error;
111   for (const auto& file : context_->files_to_modify.get()) {
112     fs::path temp_install_path(install_path / file);
113     fs::path temp_unzip_path(unzip_path / file);
114     if (!PerformBackup(file, Operation::MODIFY)) {
115       LOG(ERROR) << "unable to perform backup of to be modified file";
116       return false;
117     }
118     fs::copy_file(temp_unzip_path, temp_install_path,
119                   fs::copy_options::overwrite_existing, error);
120     if (error) {
121       LOG(ERROR) << "unable to modify file " << error.message();
122       return false;
123     }
124   }
125   return true;
126 }
127
128 bool StepRDSModify::DeleteFiles(fs::path install_path) {
129   LOG(INFO) << "about to delete files";
130   for (const auto& file : context_->files_to_delete.get()) {
131     if (!PerformBackup(file, Operation::DELETE)) {
132       LOG(ERROR) << "unable to perform backup of to be deleted file";
133       return false;
134     }
135     if (!Remove(install_path / file))
136       return false;
137   }
138   return true;
139 }
140
141 bool StepRDSModify::SetUpTempBackupDir() {
142   LOG(INFO) << "about to setup tmp backup dir";
143   backup_temp_dir_ = "/tmp/" /
144       ci::GenerateUniquePathString("%%%%-%%%%-%%%%-%%%%");
145   if (!CreateDir(backup_temp_dir_)) {
146     LOG(ERROR) << "unable to create backup data temp dir";
147     return false;
148   }
149
150   return true;
151 }
152
153 bool StepRDSModify::PerformBackup(std::string relative_path,
154                                   Operation operation) {
155   if (backup_temp_dir_.empty())
156     return false;
157   if (operation == Operation::DELETE || operation == Operation::MODIFY) {
158     fs::path app_path = context_->GetPkgPath();
159     fs::path source_path = app_path  / relative_path;
160     if (fs::is_directory(source_path)) {
161       if (!CreateDir(backup_temp_dir_ / relative_path)) {
162         LOG(ERROR) << "unable to create dir for temp backup data";
163         return false;
164       }
165     } else {
166       std::error_code error;
167       fs::path tmp_dest_path = backup_temp_dir_ / relative_path;
168       if (!fs::exists((tmp_dest_path).parent_path()) &&
169         (!CreateDir((tmp_dest_path).parent_path()))) {
170         LOG(ERROR) << "unable to create dir for temp backup data";
171         return false;
172       }
173       fs::copy_file(source_path, tmp_dest_path, error);
174       if (error) {
175         LOG(ERROR) << "unable to backup file: "
176                    << source_path << " : " << error.message();
177         return false;
178       }
179     }
180   }
181   success_modifications_.push_back(std::make_pair(relative_path, operation));
182   return true;
183 }
184
185 void StepRDSModify::RestoreFiles() {
186   LOG(ERROR) << "error occured about to restore files";
187   fs::path app_path(context_->GetPkgPath());
188   for (std::pair<std::string, Operation>& modification :
189        success_modifications_) {
190     fs::path source_path(backup_temp_dir_ / modification.first);
191     fs::path destination_path(app_path / modification.first);
192     if (modification.second == Operation::ADD) {
193       if (fs::is_directory(source_path)) {
194         fs::remove_all(destination_path);
195       } else {
196         fs::remove(destination_path);
197       }
198     } else if (modification.second == Operation::MODIFY) {
199       fs::copy_file(source_path, destination_path,
200                     fs::copy_options::overwrite_existing);
201     } else {
202       if (fs::is_directory(source_path)) {
203         if (!CreateDir(destination_path))
204           LOG(ERROR) << "Failed to create dir: " << destination_path;
205       } else {
206         fs::copy_file(source_path, destination_path,
207                       fs::copy_options::overwrite_existing);
208       }
209     }
210   }
211   // after files are restore delete temporary location
212   fs::remove_all(backup_temp_dir_);
213 }
214
215 }  // namespace rds
216 }  // namespace common_installer