2 * Copyright (c) 2011 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_db_update.cpp
18 * @author Lukasz Wrzosek(l.wrzosek@samsung.com)
20 * @brief Implementation file for installer task database updating
24 #include <widget_install/task_file_manipulation.h>
25 #include <widget_install/job_widget_install.h>
26 #include <widget_install/widget_install_errors.h>
27 #include <widget_install/widget_install_context.h>
28 #include <dpl/utils/wrt_utility.h>
29 #include <dpl/foreach.h>
30 #include <dpl/log/log.h>
31 #include <dpl/assert.h>
32 #include <dpl/utils/folder_size.h>
35 #include <widget_install_to_external.h>
37 #define WEBAPP_DEFAULT_UID 5000
38 #define WEBAPP_DEFAULT_GID 5000
41 const mode_t PRIVATE_STORAGE_MODE = 0700;
42 const mode_t SHARE_MODE = 0705;
45 using namespace WrtDB;
48 const char* GLIST_RES_DIR = "res";
49 const char* GLIST_BIN_DIR = "bin";
51 bool _FolderCopy(std::string source, std::string dest)
53 DIR* dir = opendir(source.c_str());
58 struct dirent* dEntry = NULL;
61 if (dEntry = readdir(dir)) {
62 std::string fileName = dEntry->d_name;
63 std::string fullName = source + "/" + fileName;
65 if (stat(fullName.c_str(), &statInfo) != 0) {
69 if (S_ISDIR(statInfo.st_mode)) {
70 if(("." == fileName) || (".." == fileName)) {
73 std::string destFolder = dest + "/" + fileName;
74 WrtUtilMakeDir(destFolder);
76 if (!_FolderCopy(fullName, destFolder)) {
81 std::string destFile = dest + "/" + fileName;
82 std::ifstream infile(fullName);
83 std::ofstream outfile(destFile);
84 outfile << infile.rdbuf();
95 namespace WidgetInstall {
96 TaskFileManipulation::TaskFileManipulation(InstallerContext& context) :
97 DPL::TaskDecl<TaskFileManipulation>(this),
100 if (INSTALL_LOCATION_TYPE_EXTERNAL !=
101 m_context.locationType) {
102 AddStep(&TaskFileManipulation::StepCreateDirs);
103 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
104 AddStep(&TaskFileManipulation::StepCreateShareDir);
105 if (m_context.widgetConfig.packagingType !=
106 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
108 AddStep(&TaskFileManipulation::StepRenamePath);
109 AddAbortStep(&TaskFileManipulation::StepAbortRenamePath);
112 AddStep(&TaskFileManipulation::StepPrepareExternalDir);
113 AddStep(&TaskFileManipulation::StepInstallToExternal);
114 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
115 AddStep(&TaskFileManipulation::StepCreateShareDir);
117 AddAbortStep(&TaskFileManipulation::StepAbortCreateExternalDir);
121 void TaskFileManipulation::StepCreateDirs()
123 std::string widgetPath;
124 DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
125 if (pkgname.IsNull()) {
126 ThrowMsg(Exceptions::InternalError, "No Package name exists.");
129 widgetPath = m_context.locations->getPackageInstallationDir();
131 std::string widgetBinPath = m_context.locations->getBinaryDir();
132 std::string widgetSrcPath = m_context.locations->getSourceDir();
134 WrtUtilMakeDir(widgetPath);
136 // If package type is widget with osp service, we don't need to make bin
138 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
139 LogDebug("Doesn't need to create resource directory");
141 LogDebug("Create resource directory");
142 WrtUtilMakeDir(widgetBinPath);
143 WrtUtilMakeDir(widgetSrcPath);
146 m_context.job->UpdateProgress(
147 InstallerContext::INSTALL_DIR_CREATE,
148 "Widget Directory Created");
151 void TaskFileManipulation::StepCreatePrivateStorageDir()
153 std::string storagePath = m_context.locations->getPrivateStorageDir();
155 if (euidaccess(storagePath.c_str(), F_OK) != 0) {
156 if(!WrtUtilMakeDir(storagePath, PRIVATE_STORAGE_MODE)){
157 LogError("Failed to create directory for private storage");
158 ThrowMsg(Exceptions::InternalError,
159 "Failed to create directory for private storage");
161 // '5000' is default uid, gid for applications.
162 // So installed applications should be launched as process of uid '5000'.
163 // the process can access private directory 'data' of itself.
164 if(chown(storagePath.c_str(),
166 WEBAPP_DEFAULT_GID) != 0)
168 ThrowMsg(Exceptions::InternalError,
169 "Chown to invaild user");
171 } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) {
172 LogInfo("Private storage already exists.");
173 // Even if private directory already is created, private dircetory
174 // should change owner.
175 if(chown(storagePath.c_str(),
177 WEBAPP_DEFAULT_GID) != 0)
179 ThrowMsg(Exceptions::InternalError,
180 "Chown to invaild user");
182 if(chmod(storagePath.c_str(), PRIVATE_STORAGE_MODE) != 0) {
183 ThrowMsg(Exceptions::InternalError,
188 ThrowMsg(Exceptions::InternalError,
189 "No access to private storage.");
193 void TaskFileManipulation::StepCreateShareDir()
195 std::string sharePath = m_context.locations->getShareDir();
197 if (euidaccess(sharePath.c_str(), F_OK) != 0) {
198 if(!WrtUtilMakeDir(sharePath, SHARE_MODE)){
199 LogError("Failed to create directory for share");
200 ThrowMsg(Exceptions::InternalError,
201 "Failed to create directory for share");
203 // '5000' is default uid, gid for applications.
204 // So installed applications should be launched as process of uid '5000'.
205 // the process can access private directory 'data' of itself.
206 if(chown(sharePath.c_str(),
208 WEBAPP_DEFAULT_GID) != 0)
210 ThrowMsg(Exceptions::InternalError,
211 "Chown to invaild user");
213 } else if (euidaccess(sharePath.c_str(), W_OK | R_OK | X_OK) == 0) {
214 LogInfo("Share directory already exists.");
215 // Even if share directory already is created, share dircetory
216 // should change owner.
217 if(chown(sharePath.c_str(),
219 WEBAPP_DEFAULT_GID) != 0)
221 ThrowMsg(Exceptions::InternalError,
222 "Chown to invaild user");
224 if(chmod(sharePath.c_str(), SHARE_MODE) != 0) {
225 ThrowMsg(Exceptions::InternalError,
230 ThrowMsg(Exceptions::InternalError,
231 "No access to private storage.");
236 void TaskFileManipulation::StepRenamePath()
239 DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
240 if (pkgname.IsNull()) {
241 ThrowMsg(Exceptions::InternalError, "No Package name exists.");
244 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
245 instDir = m_context.locations->getPackageInstallationDir();
247 instDir = m_context.locations->getSourceDir();
250 LogDebug("Copy file from temp directory to " << instDir);
251 if (!WrtUtilRemove(instDir)) {
252 ThrowMsg(Exceptions::RemovingFolderFailure,
253 "Error occurs during removing existing folder");
256 if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(), instDir.c_str()) == 0)) {
257 ThrowMsg(Exceptions::UnknownError,
258 "Error occurs during renaming widget folder");
260 m_context.job->UpdateProgress(
261 InstallerContext::INSTALL_RENAME_PATH,
262 "Widget Rename path Finished");
265 void TaskFileManipulation::StepAbortRenamePath()
267 LogDebug("[Rename Widget Path] Aborting.... (Rename path)");
268 std::string widgetPath;
269 if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) {
270 widgetPath = m_context.locations->getPackageInstallationDir();
271 if (!WrtUtilRemove(widgetPath)) {
272 ThrowMsg(Exceptions::RemovingFolderFailure,
273 "Error occurs during removing existing folder");
276 LogDebug("Rename widget path sucessful!");
279 void TaskFileManipulation::StepPrepareExternalDir()
281 LogDebug("Step prepare to install in exernal directory");
283 std::string pkgname =
284 DPL::ToUTF8String(*m_context.widgetConfig.pkgname);
286 WidgetInstallToExtSingleton::Instance().initialize(pkgname);
289 Utils::getFolderSize(m_context.locations->getTemporaryPackageDir());
291 int folderSize = (int)(totalSize / (1024 * 1024)) + 1;
294 app2ext_dir_details* dirDetail = NULL;
296 std::string dirNames[2] = {GLIST_RES_DIR, GLIST_BIN_DIR};
298 for (int i = 0; i < 2; i++) {
299 dirDetail = (app2ext_dir_details*) calloc(1,
300 sizeof(app2ext_dir_details));
301 if (NULL == dirDetail) {
302 ThrowMsg(Exceptions::ErrorExternalInstallingFailure, "error in app2ext");
304 dirDetail->name = strdup(dirNames[i].c_str());
305 dirDetail->type = APP2EXT_DIR_RO;
306 list = g_list_append(list, dirDetail);
309 if (false == m_context.existingWidgetInfo.isExist) {
310 WidgetInstallToExtSingleton::Instance().preInstallation(list,
313 WidgetInstallToExtSingleton::Instance().preUpgrade(list,
319 Catch (WidgetInstallToExt::Exception::ErrorInstallToExt)
321 ReThrowMsg(Exceptions::ErrorExternalInstallingFailure, "Error during \
322 create external folder ");
326 void TaskFileManipulation::StepInstallToExternal()
328 LogDebug("StepInstallExternal");
329 if (!WrtUtilMakeDir(m_context.locations->getSourceDir())) {
330 ThrowMsg(Exceptions::ErrorExternalInstallingFailure, "To make src \
334 LogDebug("Resource move to external storage " <<
335 m_context.locations->getSourceDir());
336 if (!_FolderCopy(m_context.locations->getTemporaryPackageDir(),
337 m_context.locations->getSourceDir()))
339 ThrowMsg(Exceptions::UnknownError,
340 "Error occurs during renaming widget folder");
344 void TaskFileManipulation::StepAbortCreateExternalDir()
346 LogError("Abort StepAbortCreateExternalDir");
347 if (false == m_context.existingWidgetInfo.isExist) {
348 WidgetInstallToExtSingleton::Instance().postInstallation(false);
350 WidgetInstallToExtSingleton::Instance().postUpgrade(false);
352 WidgetInstallToExtSingleton::Instance().deinitialize();
354 } //namespace WidgetInstall