Initialize Tizen 2.3
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_prepare_reinstall.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  * @file    task_prepare_reinstall.cpp
18  * @author  Jihoon Chung(jihoon.chung@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task prepare reinstalling
21  */
22
23 #include "task_prepare_reinstall.h"
24
25 #include <stdio.h>
26 #include <fstream>
27 #include <unistd.h>
28
29 #include <privilege-control.h>
30
31 #include <dpl/task.h>
32 #include <dpl/string.h>
33 #include <dpl/foreach.h>
34 #include <boost/filesystem.hpp>
35
36 #include <widget_install/widget_install_context.h>
37 #include <widget_install/widget_install_errors.h>
38 #include <dpl/log/secure_log.h>
39
40 namespace bf = boost::filesystem;
41
42 namespace Jobs {
43 namespace WidgetInstall {
44 namespace {
45 const char* const KEY_DELETE = "#delete";
46 const char* const KEY_ADD = "#add";
47 const char* const KEY_MODIFY = "#modify";
48 std::list<std::string> keyList = {KEY_DELETE, KEY_ADD, KEY_MODIFY};
49
50 void verifyFile(const std::string &filePath)
51 {
52     if (access(filePath.c_str(), F_OK) != 0) {
53         ThrowMsg(Exceptions::RDSDeltaFailure, "File is missed " << filePath);
54     }
55 }
56
57 std::string parseSubPath(const std::string& filePath)
58 {
59     std::string subPath("");
60     size_t pos = filePath.find_last_of('/') + 1;
61
62     if (pos != std::string::npos) {
63         subPath = filePath.substr(0, pos);
64     }
65     return subPath;
66 }
67
68 void createDir(const std::string& path)
69 {
70     bf::path p(path);
71     try {
72         if(!bf::exists(p)){
73             bf::create_directories(p);
74             bf::permissions(p, bf::owner_all | bf::group_read | bf::group_exe
75                             | bf::others_read | bf::others_exe);
76             _D("Create directory : %s", path.c_str());
77          }
78     } catch (const bf::filesystem_error& ex) {
79         _E("boost::filesystem::error; %s", ex.what());
80         ThrowMsg(Exceptions::RDSDeltaFailure, "Fail to create dir" << path);
81     }
82 }
83 } // namespace anonymous
84
85 TaskPrepareReinstall::TaskPrepareReinstall(JobWidgetInstall * const &jobContext) :
86     DPL::TaskDecl<TaskPrepareReinstall>(this),
87     m_jobContext(jobContext)
88 {
89     AddStep(&TaskPrepareReinstall::StartStep);
90     AddStep(&TaskPrepareReinstall::StepPrepare);
91     AddStep(&TaskPrepareReinstall::StepParseRDSDelta);
92     AddStep(&TaskPrepareReinstall::StepVerifyRDSDelta);
93     AddStep(&TaskPrepareReinstall::StepAddFile);
94     AddStep(&TaskPrepareReinstall::StepDeleteFile);
95     AddStep(&TaskPrepareReinstall::StepModifyFile);
96     AddStep(&TaskPrepareReinstall::StepUpdateSmackLabel);
97     AddStep(&TaskPrepareReinstall::EndStep);
98 }
99
100 void TaskPrepareReinstall::StepPrepare()
101 {
102     _D("Prepare");
103     m_sourcePath = m_jobContext->m_installerContext.locations->getTemporaryPackageDir();
104     m_sourcePath += "/";
105
106     m_installedPath = m_jobContext->m_installerContext.locations->getPackageInstallationDir();
107     m_installedPath += "/";
108 }
109
110 void TaskPrepareReinstall::StepParseRDSDelta()
111 {
112     _D("parse RDS delta");
113     std::string rdsDeltaPath = m_sourcePath;
114     rdsDeltaPath += ".rds_delta";
115     std::ifstream delta(rdsDeltaPath);
116
117     if (!delta.is_open()) {
118         ThrowMsg(Exceptions::RDSDeltaFailure, "rds_delta file is missed");
119         return;
120     }
121
122     std::string line;
123     std::string key;
124     while (std::getline(delta, line) &&!delta.eof()) {
125         FOREACH(keyIt, keyList) {
126             if (line == *keyIt) {
127                 _D("find key = [%s]", line.c_str());
128                 key = line;
129                 break;
130             }
131         }
132         if (key == line || line.empty() || line == "\n") {
133             continue;
134         }
135         if (key == KEY_DELETE) {
136             m_deleteFileList.push_back(line);
137             _D("line = [%s]", line.c_str());
138         } else if (key == KEY_ADD) {
139             m_addFileList.push_back(line);
140             _D("line = [%s]", line.c_str());
141         } else if (key == KEY_MODIFY) {
142             m_modifyFileList.push_back(line);
143             _D("line = [%s]", line.c_str());
144         }
145     }
146 }
147
148 void TaskPrepareReinstall::StepVerifyRDSDelta()
149 {
150     _D("verify RDS delta");
151     // Verify ADD file
152     FOREACH(file, m_addFileList) {
153         std::string addFilePath = m_sourcePath;
154         addFilePath += *file;
155         verifyFile(addFilePath);
156     }
157     // Verify DELETE file
158     FOREACH(file, m_deleteFileList) {
159         std::string deleteFilePath = m_installedPath;
160         deleteFilePath += *file;
161         verifyFile(deleteFilePath);
162     }
163     // Verify MODIFY file
164     FOREACH(file, m_modifyFileList) {
165         std::string newFilePath = m_sourcePath;
166         newFilePath += *file;
167         verifyFile(newFilePath);
168
169         std::string existingFilePath = m_installedPath;
170         existingFilePath += *file;
171         verifyFile(existingFilePath);
172     }
173     _D("Finished veify RDS Delta");
174
175     m_jobContext->UpdateProgress(
176         InstallerContext::INSTALL_RDS_DELTA_CHECK,
177         "RDS delta verify finished");
178 }
179
180 void TaskPrepareReinstall::StepAddFile()
181 {
182     _D("Add file");
183     FOREACH(file, m_addFileList) {
184         std::string newfile = m_sourcePath;
185         newfile += *file;
186         std::string destPath = m_installedPath;
187         destPath += *file;
188
189         try{
190             if (bf::is_directory(bf::path(newfile))) {
191                 // In case of a new directory
192                 createDir(destPath);
193             } else {
194                 // In case of a new file
195
196                 // Parse directory and file separately
197                 std::string subPath = parseSubPath(destPath);
198                 if (subPath.empty()) {
199                     ThrowMsg(Exceptions::RDSDeltaFailure,
200                              "Invalid path given" << destPath);
201                 }
202
203                 // Create a new directory
204                 createDir(subPath);
205
206                 // Add file
207                 if (rename(newfile.c_str(), destPath.c_str()) != 0) {
208                     ThrowMsg(Exceptions::RDSDeltaFailure,
209                             "Fail to add file " << newfile);
210                 }
211                 _D("Add %s to %s", newfile.c_str(), destPath.c_str());
212             }
213         } catch (const bf::filesystem_error& ex) {
214             _E("boost::filesystem::error: %s", ex.what());
215         }
216     }
217 }
218
219 void TaskPrepareReinstall::StepDeleteFile()
220 {
221     _D("Delete file");
222     FOREACH(file, m_deleteFileList) {
223         std::string deleteFilePath = m_installedPath;
224         deleteFilePath += *file;
225         if (remove(deleteFilePath.c_str()) != 0) {
226             ThrowMsg(Exceptions::RDSDeltaFailure,
227                 "Fail to DELETE file " << deleteFilePath);
228         }
229         _D("Delete %s", deleteFilePath.c_str());
230     }
231 }
232
233 void TaskPrepareReinstall::StepModifyFile()
234 {
235     _D("Modify  file");
236     FOREACH(file, m_modifyFileList) {
237         std::string destPath = m_installedPath;
238         destPath += *file;
239         if (remove(destPath.c_str()) != 0) {
240             ThrowMsg(Exceptions::RDSDeltaFailure,
241                 "Fail to delete existing file " << destPath);
242         }
243
244         std::string newfile = m_sourcePath;
245         newfile += *file;
246         if (rename(newfile.c_str(), destPath.c_str()) != 0) {
247             ThrowMsg(Exceptions::RDSDeltaFailure,
248                 "Fail to move new file" << destPath);
249         }
250         _D("Replace %s to %s", newfile.c_str(), destPath.c_str());
251     }
252
253     m_jobContext->UpdateProgress(
254         InstallerContext::INSTALL_RDS_PREPARE,
255         "RDS prepare finished");
256 }
257
258 void TaskPrepareReinstall::StepUpdateSmackLabel()
259 {
260     /* res directory */
261     std::string resDir = m_installedPath + "res";
262     std::string pkgId = DPL::ToUTF8String(m_jobContext->m_installerContext.widgetConfig.tzPkgid);
263     if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId.c_str(), resDir.c_str(),
264                 APP_PATH_PRIVATE)) {
265         _W("Add label to %s", resDir.c_str());
266     }
267 }
268
269 void TaskPrepareReinstall::StartStep()
270 {
271     LOGI("---------- <TaskPrepareReinstall> : START ----------");
272 }
273
274 void TaskPrepareReinstall::EndStep()
275 {
276     LOGI("---------- <TaskPrepareReinstall> : END ----------");
277     m_jobContext->UpdateProgress(
278         InstallerContext::INSTALL_END,
279         "End RDS update");
280 }
281
282 } //namespace WidgetInstall
283 } //namespace Jobs