0ba0a073b85af6782b7d8fdb01ecb53a78385582
[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/exception.h>
43 #include <dpl/errno_string.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     //closing the directory
129     if (-1 == TEMP_FAILURE_RETRY(closedir(pkgDir))) {
130         LogError("Failed to close dir: " << dirPath << " with error: "
131                 << DPL::GetErrnoString());
132     }
133 }
134
135 void TaskUpdateFiles::StepResourceFilesBackup()
136 {
137     LogDebug("StepCopyFiles");
138
139     ExistFileList resList;
140     ExistFileList tempList;
141
142     std::string pkgSrc = m_context.locations->getSourceDir();
143     ReadDirList(pkgSrc, resList, strlen(pkgSrc.c_str())+1);
144
145
146     std::string tempSrc = m_context.locations->getTemporaryPackageDir();
147     ReadDirList(tempSrc, tempList, strlen(tempSrc.c_str())+1);
148
149     FOREACH(it, tempList) {
150         std::set<std::string>::iterator res;
151         res = resList.find(*it);
152         std::string resFile = pkgSrc + "/" + (*it);
153         std::string newFile = tempSrc + "/" +(*it);
154
155         if (res != resList.end()) {
156             std::string backupFile = m_context.locations->getBackupSourceDir() +
157                     "/"+ (*it);
158
159             struct stat sInfo;
160             if (stat(resFile.c_str(), &sInfo) != 0) {
161                 ThrowMsg(Exceptions::InternalError, "Error occurs read file");
162             }
163
164             if (S_ISDIR(sInfo.st_mode)) {
165                 LogDebug(resFile << " is a directory. so create a folder : " <<
166                         backupFile);
167                 WrtUtilMakeDir(backupFile);
168             } else {
169                 if ((rename(resFile.c_str(), backupFile.c_str())) != 0) {
170                     LogError("Failed to rename " << resFile << " to " << backupFile);
171                     ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
172                             rename file");
173                 }
174
175                 LogDebug("backup : " << resFile << " to " << backupFile);
176
177                 if ((rename(newFile.c_str(), resFile.c_str())) != 0) {
178                     LogError("Failed to rename " << newFile << " to " << resFile);
179                     ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
180                             rename file");
181                 }
182                 LogDebug("copy : " << newFile << " to " << resFile);
183             }
184             resList.erase(res);
185         } else {
186             if ((rename(newFile.c_str(), resFile.c_str())) != 0) {
187                 LogError("Failed to rename " << newFile << " to " << resFile);
188                 ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
189                         rename file");
190             }
191             LogDebug("only copy : " << newFile << " to " << resFile);
192         }
193     }
194
195     if (resList.empty() != 0) {
196         FOREACH(remain, resList) {
197             std::string pkgFile = pkgSrc + "/" + (*remain);
198             std::string backFile = tempSrc + "/" + (*remain);
199             if ((rename(pkgFile.c_str(), backFile.c_str())) != 0) {
200                 LogError("Failed to backup : " << pkgFile << " to " << backFile);
201                 ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
202                         rename file");
203             }
204             LogDebug("only backup : " << pkgFile << " to " << backFile);
205         }
206     }
207
208     m_context.job->UpdateProgress(
209         InstallerContext::INSTALL_BACKUP_RES_FILES,
210         "Backup resource file for update");
211 }
212
213 void TaskUpdateFiles::StepExecFileBackup()
214 {
215     std::string execFile = m_context.locations->getExecFile();
216
217     LogDebug(" source : " << execFile);
218
219     std::string tempSource= m_context.locations->getBackupExecFile();
220     LogDebug(" source : " << tempSource);
221
222     if ((rename(execFile.c_str(), tempSource.c_str())) != 0) {
223         LogError("Failed to rename " << execFile << " to " <<
224                 tempSource);
225         ThrowMsg(Exceptions::BackupFailed, "Error occurs during \
226                 rename file");
227     }
228     LogDebug("Backup : " << execFile << " to " << tempSource);
229
230     std::string clientPath = GlobalConfig::GetWrtClientExec();
231
232     LogInfo("link -s " << clientPath << " " << execFile);
233     symlink(clientPath.c_str(), execFile.c_str());
234
235     m_context.job->UpdateProgress(
236         InstallerContext::INSTALL_BACKUP_EXEC,
237         "Backup execution file for update");
238 }
239
240 void TaskUpdateFiles::StepAbortResourceFilesBackup()
241 {
242     LogDebug("StepAbortCopyFiles");
243     std::string srcPath = m_context.locations->getSourceDir();
244     std::string srcBuPath = m_context.locations->getBackupSourceDir();
245
246     LogDebug("Backup Folder " << srcBuPath << " to " << srcPath);
247
248     if(!WrtUtilRemove(srcPath)) {
249         LogError("Failed to remove " << srcPath);
250     }
251
252     if (rename(srcBuPath.c_str(), srcPath.c_str()) != 0) {
253         LogError("Failed to rename " << srcBuPath << " to " << srcPath);
254     }
255 }
256
257 void TaskUpdateFiles::StepAbortExecFileBackup()
258 {
259     LogDebug("StepAbortExecFileBackup");
260     std::string binPath = m_context.locations->getBinaryDir();
261
262     if(!WrtUtilRemove(binPath)) {
263         LogError("Failed to remove " << binPath);
264     }
265
266     std::string binBuPath = m_context.locations->getBackupBinaryDir();
267     if (rename(binBuPath.c_str(), binPath.c_str()) != 0) {
268         LogError("Failed to rename " << binBuPath << " to " << binPath);
269     }
270     LogDebug("Backup Folder " << binBuPath << "move to " << binPath);
271 }
272
273 void TaskUpdateFiles::StepAbortCreateBackupFolder()
274 {
275     LogDebug("StepAbortCreateBackupFolder");
276     std::ostringstream path;
277     path << m_context.locations->getBackupDir();
278     LogDebug("Remove backup directory : " << path.str());
279
280     if(!WrtUtilRemove(path.str())) {
281         LogError("Failed to remove " << path);
282     }
283 }
284
285 void TaskUpdateFiles::StepUpdateExternalFiles()
286 {
287     WidgetDAO dao(m_context.locations->getPkgname());
288     WrtDB::ExternalLocationList externalLocationsUpdate = m_context.locations->listExternalLocations();
289     WrtDB::ExternalLocationList externalLocationsDB = dao.getWidgetExternalLocations();
290     LogDebug("Removing external files:");
291     FOREACH(file, externalLocationsDB)
292     {
293         if(std::find(externalLocationsUpdate.begin(), externalLocationsUpdate.end(), *file) == externalLocationsUpdate.end())
294         {
295             if(WrtUtilFileExists(*file))
296             {
297                 LogDebug("  -> " << *file);
298                 remove(file->c_str());
299             }
300             else if(WrtUtilDirExists(*file))
301             {
302                 LogDebug("  -> " << *file);
303                 if(!WrtUtilRemove(*file)){
304                     ThrowMsg(Exceptions::RemovingFolderFailure,
305                             "Failed to remove external directory");
306                 }
307             }
308             else
309             {
310                 LogWarning("  -> " << *file << "(no such a path)");
311             }
312         }
313     }
314     dao.unregisterAllExternalLocations();
315     LogDebug("Registering(update) external files:");
316     FOREACH(file, externalLocationsUpdate)
317     {
318         LogDebug("  -> " << *file);
319     }
320     dao.registerExternalLocations(externalLocationsUpdate);
321 }
322
323 } //namespace WidgetInstall
324 } //namespace Jobs