[Release] wrt-installer_0.0.73
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_plugins_copy.cpp
1 /*
2  * Copyright (c) 2012 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_plugin_copy.cpp
18  * @author  Marcin Kaminski (marcin.ka@samsung.com)
19  * @version 1.0
20  * @brief   Copying plugins delivered in widget package.
21  */
22
23 #include "task_plugins_copy.h"
24 #include <dpl/log/log.h>
25 #include <dpl/string.h>
26 #include <dpl/utils/wrt_utility.h>
27 #include <dpl/errno_string.h>
28 #include <widget_install_context.h>
29 #include <widget_install/widget_install_errors.h>
30 #include <dpl/exception.h>
31 /* Headers needed for listing directories */
32 #include <sys/stat.h>
33 #include <dirent.h>
34 /* Installation expceptions support */
35 #include <dpl/exception.h>
36 #include <cerrno>
37
38 /* wrt-installer has to copy plugins for ARM architecture
39  * when running on target or for i586 architecture if launched
40  * on SDK emulator. */
41 #ifdef __arm__
42 const std::string plugins_dir = "arm";
43 #else
44 const std::string plugins_dir = "i586";
45 #endif
46
47 namespace {
48     const std::string PackagePluginsDir = "/plugins/";
49     const std::string InstallationPluginsDir = "/data/.netscape/plugins/";
50     const mode_t InstallationPluginsDirMode = 0755;
51 }
52
53 namespace Jobs {
54 namespace WidgetInstall {
55
56 TaskPluginsCopy::TaskPluginsCopy(InstallerContext& context) :
57     DPL::TaskDecl<TaskPluginsCopy>(this),
58     m_context(context)
59 {
60     LogDebug("Starting widget plugins copy task");
61     AddStep(&TaskPluginsCopy::StepFindPlugins);
62     AddStep(&TaskPluginsCopy::StepCopyPlugins);
63     AddStep(&TaskPluginsCopy::StepCopyingFinished);
64     LogDebug("Widget plugins copy task ended");
65     m_npsource = m_context.locations->getSourceDir() + PackagePluginsDir
66             + plugins_dir;
67     m_npdestination = m_context.locations->getPackageInstallationDir()
68             + InstallationPluginsDir;
69 }
70
71 void TaskPluginsCopy::StepFindPlugins()
72 {
73     LogDebug("Starting plugins finding step");
74     /* Check whether plugins directory for actual architecture exists
75      * (plugins for other architectures are omitted even they exists). */
76     if(!WrtUtilDirExists(m_npsource)) {
77         LogDebug("Plugins directory (" <<m_npsource
78                 <<") does not exists - skipping copy step");
79         SwitchToStep(&TaskPluginsCopy::StepCopyingFinished);
80         return;
81     }
82
83     /* Find all .so files and store their names in list */
84     DIR *dir;
85     struct dirent *entry;
86     struct stat st;
87     LogDebug("Opening plugins directory");
88     dir = opendir(m_npsource.c_str());
89     if(dir == NULL) {
90         LogError("Unable to open plugins directory");
91         ThrowMsg(Exceptions::InternalError, "Unable to read plugins directory");
92     }
93     std::string tempname;
94     const std::string ext(".so");
95     /* Listing directory and checking entries found inside */
96     while ((entry = readdir(dir)) != NULL){
97         tempname = m_npsource + "/" + entry->d_name;
98         if(lstat(tempname.c_str(), &st) != 0) {
99             LogWarning("Failed to call \"lstat\" (errno:" <<errno
100                     <<") on entry - skipping");
101             continue;
102         }
103         /* Directories other than "." and ".." should not be found*/
104         if(S_ISDIR(st.st_mode)){
105             if(strncmp(entry->d_name, "..", 2)!=0
106                         && strncmp(entry->d_name, ".", 1)!=0) {
107                 LogError("Directory detected instead of plugin file: "
108                         << entry->d_name);
109                 /* Subdirectories inside plugins/ARCH are not supported */
110                 if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
111                     LogError("Failed to close dir: " << m_npsource
112                             << " with error: " << DPL::GetErrnoString());
113                 }
114                 ThrowMsg(Exceptions::PluginsSubdirectory,
115                         "Subdirectories inside plugins directory are not supported");
116             }
117             else {
118                 continue;
119             }
120         }
121
122         tempname = std::string(entry->d_name);
123         /* Check whether file extension is ".so" */
124         if(tempname.compare(tempname.size()-ext.size(), ext.size(), ext) == 0) {
125             /* Plugin file found */
126             LogDebug("Plugin file found: " <<tempname);
127             m_nplugins.push_back(tempname);
128         }
129         else {
130             /* Non-.so file found in plugins directory- skipping */
131             LogWarning("Non-plugin file found: " <<tempname);
132         }
133     }
134     if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
135         LogError("Failed to close dir: " << m_npsource << " with error: "
136                 << DPL::GetErrnoString());
137     }
138     /* If no .so files found (list is empty) abort taks*/
139     if(m_nplugins.empty()) {
140         LogError("No valid plugin files found");
141         ThrowMsg(Exceptions::EmptyPluginsDirectory, "No valid plugin found");
142     }
143     LogDebug("Number of detected plugins: " <<m_nplugins.size());
144     LogDebug("Plugins finding step ended");
145 }
146
147 void TaskPluginsCopy::StepCopyPlugins()
148 {
149     LogDebug("Starting plugins copying step");
150     std::string source;
151     std::string destination;
152
153     /* Create new directory for plugins (data/.netscape/plugins/) */
154     LogDebug("Creating destination plugin directory");
155     if(!WrtUtilMakeDir(m_npdestination, InstallationPluginsDirMode)){
156         LogError("Failed to create directory for plugins");
157         ThrowMsg(Exceptions::InternalError, "Failed to create directory for plugins");
158     }
159
160     LogDebug("Copying plugins to: " <<m_npdestination);
161     /* Copy plugins from widget package into
162      * .netscape/plugins in widget's target directory */
163     for(std::list<std::string>::const_iterator it = m_nplugins.begin();
164             it != m_nplugins.end(); it++) {
165         LogDebug("Copying plugin file: " << (*it));
166         source = m_npsource + "/" + (*it);
167         destination = m_npdestination + (*it);
168         if(rename(source.c_str(), destination.c_str()) != 0) {
169             LogError("Failed to move " <<source <<" to " <<destination);
170             LogError("(errno: " <<errno <<")");
171             ThrowMsg(Exceptions::InternalError, "Failed to copy plugin file");
172         }
173     }
174
175     /* Remove last part of path in source directory path
176      * (that is "arm" or "i586" depending on architecture) */
177     size_t position = m_npsource.find_last_of('/');
178     source = m_npsource.substr(0, position);
179     LogDebug("Removing unnecessary directory: " << source);
180     /* Remove source directory with plugins (possibly for multiple
181      * architectures). */
182     if(!WrtUtilRemove(source)){
183         LogError("Failed to plugins source remove directory");
184         ThrowMsg(Exceptions::InternalError, "Failed to plugins source remove directory");
185     }
186     LogDebug("Plugins copying step ended");
187 }
188
189 void TaskPluginsCopy::StepCopyingFinished()
190 {
191     LogDebug("Plugins copy task finished");
192 }
193
194 } //namespace WidgetInstall
195 } //namespace Jobs