2b4b60c46f7808831757d2978e442d4cbaee676d
[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 <boost/system/error_code.hpp>
8
9 #include <manifest_parser/utils/logging.h>
10
11 #include <common/utils/file_util.h>
12
13 namespace common_installer {
14 namespace rds {
15
16 namespace bf = boost::filesystem;
17 namespace bs = boost::system;
18 namespace ci = common_installer;
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 (!bf::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   bf::path install_path = context_->GetPkgPath();
56   bf::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(bf::path unzip_path, bf::path install_path) {
77   LOG(INFO) << "about to add files";
78   bs::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     bf::path temp_install_path(install_path / file);
85     if (bf::is_directory(temp_install_path)) {
86       if (!bf::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 (!bf::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       bf::path temp_unzip_path(unzip_path / file);
98       bf::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(bf::path unzip_path, bf::path install_path) {
109   LOG(INFO) << "about to modify files";
110   bs::error_code error;
111   for (const auto& file : context_->files_to_modify.get()) {
112     bf::path temp_install_path(install_path / file);
113     bf::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     bf::copy_file(temp_unzip_path, temp_install_path,
119                   bf::copy_option::overwrite_if_exists, 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(bf::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   bs::error_code error;
144   backup_temp_dir_ = "/tmp/" /
145       bf::unique_path("%%%%-%%%%-%%%%-%%%%", error);
146   if (error || !CreateDir(backup_temp_dir_)) {
147     LOG(ERROR) << "unable to create backup data temp dir";
148     return false;
149   }
150
151   return true;
152 }
153
154 bool StepRDSModify::PerformBackup(std::string relative_path,
155                                   Operation operation) {
156   if (backup_temp_dir_.empty())
157     return false;
158   if (operation == Operation::DELETE || operation == Operation::MODIFY) {
159     bf::path app_path = context_->GetPkgPath();
160     bf::path source_path = app_path  / relative_path;
161     if (bf::is_directory(source_path)) {
162       if (!CreateDir(backup_temp_dir_ / relative_path)) {
163         LOG(ERROR) << "unable to create dir for temp backup data";
164         return false;
165       }
166     } else {
167       bs::error_code error;
168       bf::path tmp_dest_path = backup_temp_dir_ / relative_path;
169       if (!bf::exists((tmp_dest_path).parent_path()) &&
170         (!CreateDir((tmp_dest_path).parent_path()))) {
171         LOG(ERROR) << "unable to create dir for temp backup data";
172         return false;
173       }
174       bf::copy_file(source_path, tmp_dest_path, error);
175       if (error) {
176         LOG(ERROR) << "unable to backup file: "
177                    << source_path << " : " << error.message();
178         return false;
179       }
180     }
181   }
182   success_modifications_.push_back(std::make_pair(relative_path, operation));
183   return true;
184 }
185
186 void StepRDSModify::RestoreFiles() {
187   LOG(ERROR) << "error occured about to restore files";
188   bf::path app_path(context_->GetPkgPath());
189   for (std::pair<std::string, Operation>& modification :
190        success_modifications_) {
191     bf::path source_path(backup_temp_dir_ / modification.first);
192     bf::path destination_path(app_path / modification.first);
193     if (modification.second == Operation::ADD) {
194       if (bf::is_directory(source_path)) {
195         bf::remove_all(destination_path);
196       } else {
197         bf::remove(destination_path);
198       }
199     } else if (modification.second == Operation::MODIFY) {
200       bf::copy_file(source_path, destination_path,
201                     bf::copy_option::overwrite_if_exists);
202     } else {
203       if (bf::is_directory(source_path)) {
204         CreateDir(destination_path);
205       } else {
206         bf::copy_file(source_path, destination_path,
207                       bf::copy_option::overwrite_if_exists);
208       }
209     }
210   }
211   // after files are restore delete temporary location
212   bf::remove_all(backup_temp_dir_);
213 }
214
215 }  // namespace rds
216 }  // namespace common_installer