2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file task_plugin_copy.cpp
18 * @author Marcin Kaminski (marcin.ka@samsung.com)
20 * @brief Copying plugins delivered in widget package.
24 #include "task_plugins_copy.h"
25 #include <dpl/log/log.h>
26 #include <dpl/string.h>
27 #include <dpl/utils/wrt_utility.h>
28 #include <dpl/errno_string.h>
29 #include <widget_install/job_widget_install.h>
30 #include <widget_install_context.h>
31 #include <widget_install/widget_install_errors.h>
32 #include <dpl/exception.h>
33 /* Headers needed for listing directories */
36 /* Installation expceptions support */
37 #include <dpl/exception.h>
40 /* wrt-installer has to copy plugins for ARM architecture
41 * when running on target or for i586 architecture if launched
44 const std::string plugins_dir = "arm";
46 const std::string plugins_dir = "i586";
50 const std::string PackagePluginsDir = "/plugins/";
51 const std::string InstallationPluginsDir = "/data/.netscape/plugins/";
52 const mode_t InstallationPluginsDirMode = 0755;
56 namespace WidgetInstall {
57 TaskPluginsCopy::TaskPluginsCopy(InstallerContext& context) :
58 DPL::TaskDecl<TaskPluginsCopy>(this),
61 LogDebug("Starting widget plugins copy task");
62 AddStep(&TaskPluginsCopy::StepFindPlugins);
63 AddStep(&TaskPluginsCopy::StepCopyPlugins);
64 AddStep(&TaskPluginsCopy::StepCopyingFinished);
65 LogDebug("Widget plugins copy task ended");
66 m_npsource = m_context.locations->getSourceDir() + PackagePluginsDir
68 m_npdestination = m_context.locations->getPackageInstallationDir()
69 + InstallationPluginsDir;
72 void TaskPluginsCopy::StepFindPlugins()
74 LogDebug("Starting plugins finding step");
75 /* Check whether plugins directory for actual architecture exists
76 * (plugins for other architectures are omitted even they exists). */
77 if (!WrtUtilDirExists(m_npsource)) {
79 "Plugins directory (" << m_npsource
81 ") does not exists - skipping copy step");
82 SwitchToStep(&TaskPluginsCopy::StepCopyingFinished);
86 /* Find all .so files and store their names in list */
89 LogDebug("Opening plugins directory");
90 dir = opendir(m_npsource.c_str());
92 LogError("Unable to open plugins directory");
93 ThrowMsg(Exceptions::FileOperationFailed, "Unable to read plugins directory");
97 struct dirent *result;
100 const std::string ext(".so");
101 /* Listing directory and checking entries found inside */
102 for (return_code = readdir_r(dir, &entry, &result);
103 result != NULL && return_code == 0;
104 return_code = readdir_r(dir, &entry, &result))
106 tempname = m_npsource + "/" + entry.d_name;
107 if (lstat(tempname.c_str(), &st) != 0) {
109 "Failed to call \"lstat\" (errno:" << errno
111 ") on entry - skipping");
114 /* Directories other than "." and ".." should not be found*/
115 if (S_ISDIR(st.st_mode)) {
116 if (strncmp(entry.d_name, "..", 2) != 0
117 && strncmp(entry.d_name, ".", 1) != 0)
119 LogError("Directory detected instead of plugin file: "
121 /* Subdirectories inside plugins/ARCH are not supported */
122 if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
124 "Failed to close dir: " << m_npsource
125 << " with error: " <<
126 DPL::GetErrnoString());
129 Exceptions::PluginsSubdirectory,
130 "Subdirectories inside plugins directory are not supported");
136 tempname = std::string(entry.d_name);
137 /* Check whether file extension is ".so" */
138 if (tempname.compare(tempname.size() - ext.size(), ext.size(),
141 /* Plugin file found */
142 LogDebug("Plugin file found: " << tempname);
143 m_nplugins.push_back(tempname);
145 /* Non-.so file found in plugins directory- skipping */
146 LogWarning("Non-plugin file found: " << tempname);
149 if (return_code != 0 || errno != 0) {
150 LogError("readdir_r() failed with " << DPL::GetErrnoString());
153 if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
154 LogError("Failed to close dir: " << m_npsource << " with error: "
155 << DPL::GetErrnoString());
157 /* If no .so files found (list is empty) abort taks*/
158 if (m_nplugins.empty()) {
159 LogError("No valid plugin files found");
160 ThrowMsg(Exceptions::EmptyPluginsDirectory, "No valid plugin found");
162 LogDebug("Number of detected plugins: " << m_nplugins.size());
163 LogDebug("Plugins finding step ended");
166 void TaskPluginsCopy::StepCopyPlugins()
168 LogDebug("Starting plugins copying step");
170 std::string destination;
172 /* Create new directory for plugins (data/.netscape/plugins/) */
173 LogDebug("Creating destination plugin directory");
174 if (!WrtUtilMakeDir(m_npdestination, InstallationPluginsDirMode)) {
175 LogError("Failed to create directory for plugins");
176 ThrowMsg(Exceptions::FileOperationFailed,
177 "Failed to create directory for plugins");
180 LogDebug("Copying plugins to: " << m_npdestination);
181 /* Copy plugins from widget package into
182 * .netscape/plugins in widget's target directory */
183 for (std::list<std::string>::const_iterator it = m_nplugins.begin();
184 it != m_nplugins.end(); ++it)
186 LogDebug("Copying plugin file: " << (*it));
187 source = m_npsource + "/" + (*it);
188 destination = m_npdestination + (*it);
189 if (rename(source.c_str(), destination.c_str()) != 0) {
190 LogError("Failed to move " << source << " to " << destination);
191 LogError("(errno: " << errno << ")");
192 ThrowMsg(Exceptions::FileOperationFailed, "Failed to copy plugin file");
196 /* Remove last part of path in source directory path
197 * (that is "arm" or "i586" depending on architecture) */
198 size_t position = m_npsource.find_last_of('/');
199 source = m_npsource.substr(0, position);
200 LogDebug("Removing unnecessary directory: " << source);
201 /* Remove source directory with plugins (possibly for multiple
203 if (!WrtUtilRemove(source)) {
204 LogError("Failed to plugins source remove directory");
205 ThrowMsg(Exceptions::FileOperationFailed,
206 "Failed to plugins source remove directory");
208 LogDebug("Plugins copying step ended");
210 m_context.job->UpdateProgress(
211 InstallerContext::INSTALL_PLUGINS_COPY,
215 void TaskPluginsCopy::StepCopyingFinished()
217 LogDebug("Plugins copy task finished");
219 } //namespace WidgetInstall