446c043d5b92ccc4ed1e30fda403b5113f6b8fa9
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_update_files.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_update_files.cpp
18  * @author  Soyoung Kim (sy037.kim@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task update files
21  */
22
23 #include <utility>
24 #include <vector>
25 #include <string>
26 #include <sys/stat.h>
27 #include <dirent.h>
28
29 #include <widget_install/task_update_files.h>
30 #include <dpl/assert.h>
31 #include <dpl/log/log.h>
32 #include <dpl/foreach.h>
33
34 #include <widget_install/widget_install_context.h>
35 #include <widget_install/widget_install_errors.h>
36 #include <widget_install/job_widget_install.h>
37
38 #include <dpl/wrt-dao-rw/widget_dao.h>
39 #include <dpl/wrt-dao-ro/global_config.h>
40 #include <dpl/utils/wrt_utility.h>
41 #include <dpl/exception.h>
42
43 using namespace WrtDB;
44
45 namespace {
46
47 inline const char* GetWidgetBackupDirPath()
48 {
49     return "backup";
50 }
51 }
52
53 namespace Jobs {
54 namespace WidgetInstall {
55
56 TaskUpdateFiles::TaskUpdateFiles(InstallerContext& context) :
57     DPL::TaskDecl<TaskUpdateFiles>(this),
58     m_context(context)
59 {
60     AddStep(&TaskUpdateFiles::StepCreateBackupFolder);
61     AddStep(&TaskUpdateFiles::StepResourceFilesBackup);
62     AddStep(&TaskUpdateFiles::StepExecFileBackup);
63
64     AddAbortStep(&TaskUpdateFiles::StepAbortCreateBackupFolder);
65     AddAbortStep(&TaskUpdateFiles::StepAbortExecFileBackup);
66     AddAbortStep(&TaskUpdateFiles::StepAbortResourceFilesBackup);
67 }
68
69 void TaskUpdateFiles::StepCreateBackupFolder()
70 {
71     LogDebug("StepCreateBackupFolder");
72     std::ostringstream backDirPath;
73
74     backDirPath << GlobalConfig::GetUserInstalledWidgetPath() << "/";
75     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
76
77     backDirPath << pkgname;
78     m_pkgPath = backDirPath.str();
79
80     backDirPath << "/" << GetWidgetBackupDirPath() << "/";
81     m_srcBuPath = backDirPath.str() + GlobalConfig::GetWidgetSrcPath();
82     LogDebug("backup resource directory path : " << m_srcBuPath);
83     if(!_WrtMakeDir(m_srcBuPath.c_str(), 0755, WRT_FILEUTILS_RECUR)) {
84         ThrowMsg(Exceptions::BackupFailed, "Error occurs during create \
85                 backup directory.");
86     }
87
88     m_binBuPath = backDirPath.str() + GlobalConfig::GetUserWidgetExecPath();
89     LogDebug("backup execution directory path : " << m_binBuPath);
90     if(!_WrtMakeDir(m_binBuPath.c_str(), 0755, WRT_FILEUTILS_RECUR)) {
91         ThrowMsg(Exceptions::BackupFailed, "Error occurs during create backup \
92                 directory.");
93     }
94
95     m_context.job->UpdateProgress(
96         InstallerContext::INSTALL_CREATE_BACKUP_DIR,
97         "Backup directory created for update");
98 }
99
100 void TaskUpdateFiles::ReadDirList(std::string dirPath, ExistFileList &list,
101         size_t subLen)
102 {
103     DIR* pkgDir = opendir(dirPath.c_str());
104     if (!pkgDir) {
105         LogDebug("Package directory doesn't exist");
106         ThrowMsg(Exceptions::InternalError, "Error occurs during read \
107                 directory");
108     }
109
110     struct dirent* dirent;
111     struct stat statInfo;
112     do {
113         if ((dirent = readdir(pkgDir))) {
114             std::string dirName = dirent->d_name;
115             std::string absFileName = dirPath + "/" + dirName;
116             if (stat(absFileName.c_str(), &statInfo) != 0) {
117                 ThrowMsg(Exceptions::InternalError, "Error occurs read file");
118             }
119
120             if (S_ISDIR(statInfo.st_mode)) {
121                 if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name,
122                             "..") == 0) {
123                     continue;
124                 }
125                 ReadDirList(absFileName, list, subLen);
126             }
127
128             list.insert(absFileName.substr(subLen));
129         }
130     }
131     while(dirent);
132 }
133
134 void TaskUpdateFiles::StepResourceFilesBackup()
135 {
136     LogDebug("StepCopyFiles");
137
138     ExistFileList resList;
139     ExistFileList tempList;
140
141     std::string pkgSrc = m_pkgPath + "/" + GlobalConfig::GetWidgetSrcPath();
142     ReadDirList(pkgSrc, resList, strlen(pkgSrc.c_str())+1);
143
144
145     std::string tempSrc = m_context.tempWidgetPath;
146     ReadDirList(tempSrc, tempList, strlen(m_context.tempWidgetPath.c_str())+1);
147
148     FOREACH(it, tempList) {
149         std::set<std::string>::iterator res;
150         res = resList.find(*it);
151         std::string resFile = pkgSrc + "/" + (*it);
152         std::string newFile = tempSrc + "/" +(*it);
153
154         if (res != resList.end()) {
155             std::string backupFile = m_srcBuPath + "/"+ (*it);
156
157             struct stat sInfo;
158             if (stat(resFile.c_str(), &sInfo) != 0) {
159                 ThrowMsg(Exceptions::InternalError, "Error occurs read file");
160             }
161
162             if (S_ISDIR(sInfo.st_mode)) {
163                 LogDebug(resFile << " is a directory. so create a folder : " <<
164                         backupFile);
165                 _WrtMakeDir(backupFile.c_str(), 0755, WRT_FILEUTILS_RECUR);
166             } else {
167                 if ((rename(resFile.c_str(), backupFile.c_str())) != 0) {
168                     LogError("Failed to rename " << resFile << " to " << backupFile);
169                     ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
170                             rename file");
171                 }
172
173                 LogDebug("backup : " << resFile << " to " << backupFile);
174
175                 if ((rename(newFile.c_str(), resFile.c_str())) != 0) {
176                     LogError("Failed to rename " << newFile << " to " << resFile);
177                     ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
178                             rename file");
179                 }
180                 LogDebug("copy : " << newFile << " to " << resFile);
181             }
182             resList.erase(res);
183         } else {
184             if ((rename(newFile.c_str(), resFile.c_str())) != 0) {
185                 LogError("Failed to rename " << newFile << " to " << resFile);
186                 ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
187                         rename file");
188             }
189             LogDebug("only copy : " << newFile << " to " << resFile);
190         }
191     }
192
193     if (resList.empty() != 0) {
194         FOREACH(remain, resList) {
195             std::string pkgFile = pkgSrc + "/" + (*remain);
196             std::string backFile = tempSrc + "/" + (*remain);
197             if ((rename(pkgFile.c_str(), backFile.c_str())) != 0) {
198                 LogError("Failed to backup : " << pkgFile << " to " << backFile);
199                 ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
200                         rename file");
201             }
202             LogDebug("only backup : " << pkgFile << " to " << backFile);
203         }
204     }
205
206     m_context.job->UpdateProgress(
207         InstallerContext::INSTALL_BACKUP_RES_FILES,
208         "Backup resource file for update");
209 }
210
211 void TaskUpdateFiles::StepExecFileBackup()
212 {
213     std::ostringstream source;
214     source << m_pkgPath << "/" << GlobalConfig::GetUserWidgetExecPath();
215     source << "/" << m_context.existingWidgetInfo.existingHandle;
216
217     LogDebug(" source : " << source.str());
218
219     std::ostringstream tempSource;
220     tempSource << m_binBuPath << "/" <<
221         m_context.existingWidgetInfo.existingHandle;
222     LogDebug(" source : " << tempSource.str());
223
224     if ((rename(source.str().c_str(), tempSource.str().c_str())) != 0) {
225         LogError("Failed to rename " << source.str() << " to " <<
226                 tempSource.str());
227         ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
228                 rename file");
229     }
230     LogDebug("Backup : " << source.str() << " to " << tempSource.str());
231
232     std::ostringstream newClient;
233     newClient << m_pkgPath << "/" << GlobalConfig::GetUserWidgetExecPath();
234     newClient << "/" << m_context.widgetHandle;
235
236     std::string clientPath = GlobalConfig::GetWrtClientExec();
237
238     LogInfo("link -s " << clientPath << " " << newClient.str());
239     symlink(clientPath.c_str(), newClient.str().c_str());
240
241     m_context.job->UpdateProgress(
242         InstallerContext::INSTALL_BACKUP_EXEC,
243         "Backup execution file for update");
244 }
245
246 void TaskUpdateFiles::StepAbortResourceFilesBackup()
247 {
248     LogDebug("StepAbortCopyFiles");
249     std::string srcPath = m_pkgPath + "/" + GlobalConfig::GetWidgetSrcPath();
250
251     LogDebug("Backup Folder " << m_srcBuPath << " to " << srcPath);
252
253     if(!_WrtUtilRemoveDir(srcPath.c_str())) {
254         LogError("Failed to remove " << srcPath);
255     }
256
257     if (rename(m_srcBuPath.c_str(), srcPath.c_str()) != 0) {
258         LogError("Failed to rename " << m_srcBuPath << " to " << srcPath);
259     }
260 }
261
262 void TaskUpdateFiles::StepAbortExecFileBackup()
263 {
264     LogDebug("StepAbortExecFileBackup");
265     std::string binPath = m_pkgPath + "/" +
266         GlobalConfig::GetUserWidgetExecPath();
267
268     if(!_WrtUtilRemoveDir(binPath.c_str())) {
269         LogError("Failed to remove " << binPath);
270     }
271
272     if (rename(m_binBuPath.c_str(), binPath.c_str()) != 0) {
273         LogError("Failed to rename " << m_binBuPath << " to " << binPath);
274     }
275     LogDebug("Backup Folder " << m_binBuPath << "move to " << binPath);
276 }
277
278 void TaskUpdateFiles::StepAbortCreateBackupFolder()
279 {
280     LogDebug("StepAbortCreateBackupFolder");
281     std::ostringstream path;
282     path << GlobalConfig::GetUserInstalledWidgetPath() << "/";
283     path << m_context.widgetConfig.pkgname << "/";
284     path << GetWidgetBackupDirPath();
285     LogDebug("Remove backup directory : " << path.str());
286
287     if(!_WrtUtilRemoveDir(path.str().c_str())) {
288         LogError("Failed to remove " << path);
289     }
290 }
291 } //namespace WidgetInstall
292 } //namespace Jobs