b13ab39f369bb34b2c85d202466e964eac45f9c1
[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 <algorithm>
27 #include <sys/stat.h>
28 #include <dirent.h>
29
30 #include <widget_install/task_update_files.h>
31 #include <dpl/assert.h>
32 #include <dpl/log/log.h>
33 #include <dpl/foreach.h>
34 #include <dpl/utils/wrt_utility.h>
35
36 #include <widget_install/widget_install_context.h>
37 #include <widget_install/widget_install_errors.h>
38 #include <widget_install/job_widget_install.h>
39
40 #include <dpl/wrt-dao-rw/widget_dao.h>
41 #include <dpl/wrt-dao-ro/global_config.h>
42 #include <dpl/utils/wrt_utility.h>
43 #include <dpl/exception.h>
44
45 using namespace WrtDB;
46
47 namespace {
48
49 inline const char* GetWidgetBackupDirPath()
50 {
51     return "backup";
52 }
53 }
54
55 namespace Jobs {
56 namespace WidgetInstall {
57
58 TaskUpdateFiles::TaskUpdateFiles(InstallerContext& context) :
59     DPL::TaskDecl<TaskUpdateFiles>(this),
60     m_context(context)
61 {
62     AddStep(&TaskUpdateFiles::StepCreateBackupFolder);
63     AddStep(&TaskUpdateFiles::StepResourceFilesBackup);
64     AddStep(&TaskUpdateFiles::StepExecFileBackup);
65     AddStep(&TaskUpdateFiles::StepUpdateExternalFiles);
66
67     AddAbortStep(&TaskUpdateFiles::StepAbortCreateBackupFolder);
68     AddAbortStep(&TaskUpdateFiles::StepAbortExecFileBackup);
69     AddAbortStep(&TaskUpdateFiles::StepAbortResourceFilesBackup);
70 }
71
72 void TaskUpdateFiles::StepCreateBackupFolder()
73 {
74     LogDebug("StepCreateBackupFolder");
75     std::ostringstream backDirPath;
76
77     std::string srcBuPath = m_context.locations->getBackupSourceDir();
78     LogDebug("backup resource directory path : " << srcBuPath);
79     if(!WrtUtilMakeDir(srcBuPath)) {
80         ThrowMsg(Exceptions::BackupFailed, "Error occurs during create \
81                 backup directory.");
82     }
83
84     std::string binBuPath = m_context.locations->getBackupBinaryDir();
85     LogDebug("backup execution directory path : " << binBuPath);
86     if(!WrtUtilMakeDir(binBuPath)) {
87         ThrowMsg(Exceptions::BackupFailed, "Error occurs during create backup \
88                 directory.");
89     }
90
91     m_context.job->UpdateProgress(
92         InstallerContext::INSTALL_CREATE_BACKUP_DIR,
93         "Backup directory created for update");
94 }
95
96 void TaskUpdateFiles::ReadDirList(std::string dirPath, ExistFileList &list,
97         size_t subLen)
98 {
99     DIR* pkgDir = opendir(dirPath.c_str());
100     if (!pkgDir) {
101         LogError("Package directory " << dirPath << " doesn't exist");
102         ThrowMsg(Exceptions::InternalError, "Error occurs during read \
103                 directory");
104     }
105
106     struct dirent* dirent;
107     struct stat statInfo;
108     do {
109         if ((dirent = readdir(pkgDir))) {
110             std::string dirName = dirent->d_name;
111             std::string absFileName = dirPath + "/" + dirName;
112             if (stat(absFileName.c_str(), &statInfo) != 0) {
113                 ThrowMsg(Exceptions::InternalError, "Error occurs read file");
114             }
115
116             if (S_ISDIR(statInfo.st_mode)) {
117                 if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name,
118                             "..") == 0) {
119                     continue;
120                 }
121                 ReadDirList(absFileName, list, subLen);
122             }
123
124             list.insert(absFileName.substr(subLen));
125         }
126     }
127     while(dirent);
128 }
129
130 void TaskUpdateFiles::StepResourceFilesBackup()
131 {
132     LogDebug("StepCopyFiles");
133
134     ExistFileList resList;
135     ExistFileList tempList;
136
137     std::string pkgSrc = m_context.locations->getSourceDir();
138     ReadDirList(pkgSrc, resList, strlen(pkgSrc.c_str())+1);
139
140
141     std::string tempSrc = m_context.locations->getTemporaryPackageDir();
142     ReadDirList(tempSrc, tempList, strlen(tempSrc.c_str())+1);
143
144     FOREACH(it, tempList) {
145         std::set<std::string>::iterator res;
146         res = resList.find(*it);
147         std::string resFile = pkgSrc + "/" + (*it);
148         std::string newFile = tempSrc + "/" +(*it);
149
150         if (res != resList.end()) {
151             std::string backupFile = m_context.locations->getBackupSourceDir() +
152                     "/"+ (*it);
153
154             struct stat sInfo;
155             if (stat(resFile.c_str(), &sInfo) != 0) {
156                 ThrowMsg(Exceptions::InternalError, "Error occurs read file");
157             }
158
159             if (S_ISDIR(sInfo.st_mode)) {
160                 LogDebug(resFile << " is a directory. so create a folder : " <<
161                         backupFile);
162                 WrtUtilMakeDir(backupFile);
163             } else {
164                 if ((rename(resFile.c_str(), backupFile.c_str())) != 0) {
165                     LogError("Failed to rename " << resFile << " to " << backupFile);
166                     ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
167                             rename file");
168                 }
169
170                 LogDebug("backup : " << resFile << " to " << backupFile);
171
172                 if ((rename(newFile.c_str(), resFile.c_str())) != 0) {
173                     LogError("Failed to rename " << newFile << " to " << resFile);
174                     ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
175                             rename file");
176                 }
177                 LogDebug("copy : " << newFile << " to " << resFile);
178             }
179             resList.erase(res);
180         } else {
181             if ((rename(newFile.c_str(), resFile.c_str())) != 0) {
182                 LogError("Failed to rename " << newFile << " to " << resFile);
183                 ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
184                         rename file");
185             }
186             LogDebug("only copy : " << newFile << " to " << resFile);
187         }
188     }
189
190     if (resList.empty() != 0) {
191         FOREACH(remain, resList) {
192             std::string pkgFile = pkgSrc + "/" + (*remain);
193             std::string backFile = tempSrc + "/" + (*remain);
194             if ((rename(pkgFile.c_str(), backFile.c_str())) != 0) {
195                 LogError("Failed to backup : " << pkgFile << " to " << backFile);
196                 ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
197                         rename file");
198             }
199             LogDebug("only backup : " << pkgFile << " to " << backFile);
200         }
201     }
202
203     m_context.job->UpdateProgress(
204         InstallerContext::INSTALL_BACKUP_RES_FILES,
205         "Backup resource file for update");
206 }
207
208 void TaskUpdateFiles::StepExecFileBackup()
209 {
210     std::string execFile = m_context.locations->getExecFile();
211
212     LogDebug(" source : " << execFile);
213
214     std::string tempSource= m_context.locations->getBackupExecFile();
215     LogDebug(" source : " << tempSource);
216
217     if ((rename(execFile.c_str(), tempSource.c_str())) != 0) {
218         LogError("Failed to rename " << execFile << " to " <<
219                 tempSource);
220         ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
221                 rename file");
222     }
223     LogDebug("Backup : " << execFile << " to " << tempSource);
224
225     std::string clientPath = GlobalConfig::GetWrtClientExec();
226
227     LogInfo("link -s " << clientPath << " " << execFile);
228     symlink(clientPath.c_str(), execFile.c_str());
229
230     m_context.job->UpdateProgress(
231         InstallerContext::INSTALL_BACKUP_EXEC,
232         "Backup execution file for update");
233 }
234
235 void TaskUpdateFiles::StepAbortResourceFilesBackup()
236 {
237     LogDebug("StepAbortCopyFiles");
238     std::string srcPath = m_context.locations->getSourceDir();
239     std::string srcBuPath = m_context.locations->getBackupSourceDir();
240
241     LogDebug("Backup Folder " << srcBuPath << " to " << srcPath);
242
243     if(!WrtUtilRemove(srcPath)) {
244         LogError("Failed to remove " << srcPath);
245     }
246
247     if (rename(srcBuPath.c_str(), srcPath.c_str()) != 0) {
248         LogError("Failed to rename " << srcBuPath << " to " << srcPath);
249     }
250 }
251
252 void TaskUpdateFiles::StepAbortExecFileBackup()
253 {
254     LogDebug("StepAbortExecFileBackup");
255     std::string binPath = m_context.locations->getBinaryDir();
256
257     if(!WrtUtilRemove(binPath)) {
258         LogError("Failed to remove " << binPath);
259     }
260
261     std::string binBuPath = m_context.locations->getBackupBinaryDir();
262     if (rename(binBuPath.c_str(), binPath.c_str()) != 0) {
263         LogError("Failed to rename " << binBuPath << " to " << binPath);
264     }
265     LogDebug("Backup Folder " << binBuPath << "move to " << binPath);
266 }
267
268 void TaskUpdateFiles::StepAbortCreateBackupFolder()
269 {
270     LogDebug("StepAbortCreateBackupFolder");
271     std::ostringstream path;
272     path << m_context.locations->getBackupDir();
273     LogDebug("Remove backup directory : " << path.str());
274
275     if(!WrtUtilRemove(path.str())) {
276         LogError("Failed to remove " << path);
277     }
278 }
279
280 void TaskUpdateFiles::StepUpdateExternalFiles()
281 {
282     WidgetDAO dao(m_context.locations->getPkgname());
283     WrtDB::ExternalLocationList externalLocationsUpdate = m_context.locations->listExternalLocations();
284     WrtDB::ExternalLocationList externalLocationsDB = dao.getWidgetExternalLocations();
285     LogDebug("Removing external files:");
286     FOREACH(file, externalLocationsDB)
287     {
288         if(std::find(externalLocationsUpdate.begin(), externalLocationsUpdate.end(), *file) == externalLocationsUpdate.end())
289         {
290             if(WrtUtilFileExists(*file))
291             {
292                 LogDebug("  -> " << *file);
293                 remove(file->c_str());
294             }
295             else if(WrtUtilDirExists(*file))
296             {
297                 LogDebug("  -> " << *file);
298                 if(!WrtUtilRemove(*file)){
299                     ThrowMsg(Exceptions::RemovingFolderFailure,
300                             "Failed to remove external directory");
301                 }
302             }
303             else
304             {
305                 LogWarning("  -> " << *file << "(no such a path)");
306             }
307         }
308     }
309     dao.unregisterAllExternalLocations();
310     LogDebug("Registering(update) external files:");
311     FOREACH(file, externalLocationsUpdate)
312     {
313         LogDebug("  -> " << *file);
314     }
315     dao.registerExternalLocations(externalLocationsUpdate);
316 }
317
318 } //namespace WidgetInstall
319 } //namespace Jobs