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
25 #include <widget_install/task_file_manipulation.h>
26 #include <widget_install/job_widget_install.h>
27 #include <widget_install/widget_install_errors.h>
28 #include <widget_install/widget_install_context.h>
29 #include <dpl/utils/wrt_utility.h>
30 #include <dpl/foreach.h>
31 #include <dpl/log/log.h>
32 #include <dpl/assert.h>
33 #include <dpl/errno_string.h>
34 #include <dpl/utils/folder_size.h>
35 #include <dpl/wrt-dao-ro/global_config.h>
38 #include <widget_install_to_external.h>
40 #define WEBAPP_DEFAULT_UID 5000
41 #define WEBAPP_DEFAULT_GID 5000
44 const mode_t PRIVATE_STORAGE_MODE = 0700;
45 const mode_t SHARE_MODE = 0705;
48 using namespace WrtDB;
51 const char* GLIST_RES_DIR = "res";
53 bool _FolderCopy(std::string source, std::string dest)
55 DIR* dir = opendir(source.c_str());
61 struct dirent *dEntryResult;
66 return_code = readdir_r(dir, &dEntry, &dEntryResult);
67 if (dEntryResult != NULL && return_code == 0) {
68 std::string fileName = dEntry.d_name;
69 std::string fullName = source + "/" + fileName;
71 if (stat(fullName.c_str(), &statInfo) != 0) {
76 if (S_ISDIR(statInfo.st_mode)) {
77 if (("." == fileName) || (".." == fileName)) {
80 std::string destFolder = dest + "/" + fileName;
81 WrtUtilMakeDir(destFolder);
83 if (!_FolderCopy(fullName, destFolder)) {
89 std::string destFile = dest + "/" + fileName;
90 std::ifstream infile(fullName);
91 std::ofstream outfile(destFile);
92 outfile << infile.rdbuf();
96 } while (dEntryResult != NULL && return_code == 0);
101 void changeOwnerForDirectory(std::string storagePath) {
102 if (euidaccess(storagePath.c_str(), F_OK) != 0) {
103 if (!WrtUtilMakeDir(storagePath, PRIVATE_STORAGE_MODE)) {
104 LogError("Failed to create directory for private storage");
105 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
106 "Failed to create directory for private storage");
108 // '5000' is default uid, gid for applications.
109 // So installed applications should be launched as process of uid
111 // the process can access private directory 'data' of itself.
112 if (chown(storagePath.c_str(),
114 WEBAPP_DEFAULT_GID) != 0)
116 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
117 "Chown to invaild user");
119 } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) {
120 LogInfo("Private storage already exists.");
121 // Even if private directory already is created, private dircetory
122 // should change owner.
123 if (chown(storagePath.c_str(),
125 WEBAPP_DEFAULT_GID) != 0)
127 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
128 "Chown to invaild user");
130 if (chmod(storagePath.c_str(), PRIVATE_STORAGE_MODE) != 0) {
131 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
135 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
136 "No access to private storage.");
142 namespace WidgetInstall {
143 TaskFileManipulation::TaskFileManipulation(InstallerContext& context) :
144 DPL::TaskDecl<TaskFileManipulation>(this),
148 if (INSTALL_LOCATION_TYPE_EXTERNAL !=
149 m_context.locationType)
151 AddStep(&TaskFileManipulation::StepCreateDirs);
152 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
153 if (m_context.widgetConfig.packagingType !=
154 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
156 AddStep(&TaskFileManipulation::StepRenamePath);
157 AddAbortStep(&TaskFileManipulation::StepAbortRenamePath);
159 AddStep(&TaskFileManipulation::StepLinkForPreload);
162 AddStep(&TaskFileManipulation::StepPrepareExternalDir);
163 AddStep(&TaskFileManipulation::StepInstallToExternal);
164 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
166 AddAbortStep(&TaskFileManipulation::StepAbortCreateExternalDir);
170 void TaskFileManipulation::StepCreateDirs()
172 std::string widgetPath;
174 widgetPath = m_context.locations->getPackageInstallationDir();
176 std::string widgetBinPath = m_context.locations->getBinaryDir();
177 std::string widgetSrcPath = m_context.locations->getSourceDir();
179 WrtUtilMakeDir(widgetPath);
181 // If package type is widget with osp service, we don't need to make bin
183 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
184 LogDebug("Doesn't need to create resource directory");
186 LogDebug("Create resource directory");
187 WrtUtilMakeDir(widgetBinPath);
188 WrtUtilMakeDir(widgetSrcPath);
189 if (m_context.job->getInstallerStruct().m_installMode
190 == InstallMode::INSTALL_MODE_PRELOAD)
192 std::string userWidgetDir = m_context.locations->getUserDataRootDir();
193 WrtUtilMakeDir(userWidgetDir);
197 m_context.job->UpdateProgress(
198 InstallerContext::INSTALL_DIR_CREATE,
199 "Widget Directory Created");
202 void TaskFileManipulation::StepCreatePrivateStorageDir()
204 std::string storagePath = m_context.locations->getPrivateStorageDir();
205 LogDebug("Create private storage directory : " <<
206 m_context.locations->getPrivateStorageDir());
207 changeOwnerForDirectory(storagePath);
210 void TaskFileManipulation::StepRenamePath()
214 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
215 instDir = m_context.locations->getPackageInstallationDir();
217 instDir = m_context.locations->getSourceDir();
220 LogDebug("Copy file from temp directory to " << instDir);
221 if (!WrtUtilRemove(instDir)) {
222 ThrowMsg(Exceptions::RemovingFolderFailure,
223 "Error occurs during removing existing folder");
226 if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(),
227 instDir.c_str()) == 0))
229 ThrowMsg(Exceptions::FileOperationFailed,
230 "Error occurs during renaming widget folder");
232 m_context.job->UpdateProgress(
233 InstallerContext::INSTALL_RENAME_PATH,
234 "Widget Rename path Finished");
237 void TaskFileManipulation::StepLinkForPreload()
239 if (m_context.job->getInstallerStruct().m_installMode
240 == InstallMode::INSTALL_MODE_PRELOAD)
242 std::string srcDir = m_context.locations->getUserDataRootDir() +
243 WrtDB::GlobalConfig::GetWidgetSrcPath();
245 if (0 != access(srcDir.c_str(), F_OK)) {
246 LogDebug("Make symbolic name for preaload app" <<
247 m_context.locations->getSourceDir() << " to " << srcDir);
248 std::string resDir = m_context.locations->getUserDataRootDir() +
251 WrtUtilMakeDir(resDir);
252 if (symlink(m_context.locations->getSourceDir().c_str(), srcDir.c_str()) != 0)
256 LogPedantic("Failed to make a symbolic name for a file "
257 << "[" << DPL::GetErrnoString(error) << "]");
258 ThrowMsg(Exceptions::FileOperationFailed,
259 "Symbolic link creating is not done.");
263 /* link for data directory */
264 std::string storagePath = m_context.locations->getPrivateStorageDir();
265 std::string dataDir = m_context.locations->getPackageInstallationDir() +
266 "/" + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath();
267 if (0 != access(dataDir.c_str(), F_OK)) {
268 LogDebug("Make symbolic name for preaload app " <<
269 storagePath << " to " << dataDir);
271 if (symlink(storagePath.c_str(), dataDir.c_str()) != 0)
275 LogPedantic("Failed to make a symbolic name for a file "
276 << "[" << DPL::GetErrnoString(error) << "]");
277 ThrowMsg(Exceptions::FileOperationFailed,
278 "Symbolic link creating is not done.");
280 changeOwnerForDirectory(dataDir);
283 if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) {
284 std::string widgetBinPath = m_context.locations->getBinaryDir();
285 std::string userBinPath = m_context.locations->getUserBinaryDir();
286 LogDebug("Make symbolic link for preload app " << widgetBinPath <<
287 " to " << userBinPath);
288 if (symlink(widgetBinPath.c_str(), userBinPath.c_str()) != 0)
292 LogPedantic("Failed to make a symbolic name for a file "
293 << "[" << DPL::GetErrnoString(error) << "]");
294 ThrowMsg(Exceptions::FileOperationFailed,
295 "Symbolic link creating is not done.");
302 void TaskFileManipulation::StepAbortRenamePath()
304 LogDebug("[Rename Widget Path] Aborting.... (Rename path)");
305 std::string widgetPath;
306 if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) {
307 widgetPath = m_context.locations->getPackageInstallationDir();
308 if (!WrtUtilRemove(widgetPath)) {
309 ThrowMsg(Exceptions::RemovingFolderFailure,
310 "Error occurs during removing existing folder");
313 LogDebug("Rename widget path sucessful!");
316 void TaskFileManipulation::StepPrepareExternalDir()
318 LogDebug("Step prepare to install in exernal directory");
321 DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
323 WidgetInstallToExtSingleton::Instance().initialize(pkgid);
326 Utils::getFolderSize(m_context.locations->getTemporaryPackageDir());
328 int folderSize = (int)(totalSize / (1024 * 1024)) + 1;
331 app2ext_dir_details* dirDetail = NULL;
333 dirDetail = (app2ext_dir_details*) calloc(1,
335 app2ext_dir_details));
336 if (NULL == dirDetail) {
337 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
340 dirDetail->name = strdup(GLIST_RES_DIR);
341 dirDetail->type = APP2EXT_DIR_RO;
342 list = g_list_append(list, dirDetail);
344 if (m_context.isUpdateMode) {
345 WidgetInstallToExtSingleton::Instance().preUpgrade(list,
348 WidgetInstallToExtSingleton::Instance().preInstallation(list,
354 /* make bin directory */
355 std::string widgetBinPath = m_context.locations->getBinaryDir();
356 WrtUtilMakeDir(widgetBinPath);
358 Catch(WidgetInstallToExt::Exception::ErrorInstallToExt)
360 ReThrowMsg(Exceptions::ErrorExternalInstallingFailure,
362 create external folder ");
366 void TaskFileManipulation::StepInstallToExternal()
368 LogDebug("StepInstallExternal");
369 if (!WrtUtilMakeDir(m_context.locations->getSourceDir())) {
370 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
375 LogDebug("Resource move to external storage " <<
376 m_context.locations->getSourceDir());
377 if (!_FolderCopy(m_context.locations->getTemporaryPackageDir(),
378 m_context.locations->getSourceDir()))
380 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
381 "Error occurs during renaming widget folder");
385 void TaskFileManipulation::StepAbortCreateExternalDir()
387 LogError("Abort StepAbortCreateExternalDir");
388 if (m_context.isUpdateMode) {
389 WidgetInstallToExtSingleton::Instance().postUpgrade(false);
391 WidgetInstallToExtSingleton::Instance().postInstallation(false);
393 WidgetInstallToExtSingleton::Instance().deinitialize();
395 } //namespace WidgetInstall