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 <widget_install/directory_api.h>
30 #include <dpl/utils/wrt_utility.h>
31 #include <dpl/foreach.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>
39 #include <installer_log.h>
41 #define WEBAPP_DEFAULT_UID 5000
42 #define WEBAPP_DEFAULT_GID 5000
45 const mode_t PRIVATE_STORAGE_MODE = 0700;
46 const mode_t SHARED_STORAGE_MODE = 0755;
49 using namespace WrtDB;
52 const char* GLIST_RES_DIR = "res";
54 bool _FolderCopy(std::string source, std::string dest)
56 DIR* dir = opendir(source.c_str());
62 struct dirent *dEntryResult;
67 return_code = readdir_r(dir, &dEntry, &dEntryResult);
68 if (dEntryResult != NULL && return_code == 0) {
69 std::string fileName = dEntry.d_name;
70 std::string fullName = source + "/" + fileName;
72 if (stat(fullName.c_str(), &statInfo) != 0) {
77 if (S_ISDIR(statInfo.st_mode)) {
78 if (("." == fileName) || (".." == fileName)) {
81 std::string destFolder = dest + "/" + fileName;
82 WrtUtilMakeDir(destFolder);
84 if (!_FolderCopy(fullName, destFolder)) {
90 std::string destFile = dest + "/" + fileName;
91 std::ifstream infile(fullName);
92 std::ofstream outfile(destFile);
93 outfile << infile.rdbuf();
97 } while (dEntryResult != NULL && return_code == 0);
102 void changeOwnerForDirectory(std::string storagePath, mode_t mode) {
103 if (euidaccess(storagePath.c_str(), F_OK) != 0) {
104 if (!WrtUtilMakeDir(storagePath, mode)) {
105 _E("Failed to create directory : %s", storagePath.c_str());
106 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
107 "Failed to create directory : " << storagePath);
109 // '5000' is default uid, gid for applications.
110 // So installed applications should be launched as process of uid
112 // the process can access private directory 'data' of itself.
113 if (chown(storagePath.c_str(),
115 WEBAPP_DEFAULT_GID) != 0)
117 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
118 "Chown to invaild user");
120 } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) {
121 _D("%s already exists.", storagePath.c_str());
122 // Even if private directory already is created, private dircetory
123 // should change owner.
124 if (chown(storagePath.c_str(),
126 WEBAPP_DEFAULT_GID) != 0)
128 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
129 "Chown to invaild user");
131 if (chmod(storagePath.c_str(), mode) != 0) {
132 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
136 ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
137 "No access to private storage.");
143 namespace WidgetInstall {
144 TaskFileManipulation::TaskFileManipulation(InstallerContext& context) :
145 DPL::TaskDecl<TaskFileManipulation>(this),
149 AddStep(&TaskFileManipulation::StartStep);
150 if (INSTALL_LOCATION_TYPE_EXTERNAL !=
151 m_context.locationType)
153 AddStep(&TaskFileManipulation::StepCreateDirs);
154 if (m_context.mode.extension != InstallMode::ExtensionType::DIR)
156 AddStep(&TaskFileManipulation::StepRenamePath);
157 AddAbortStep(&TaskFileManipulation::StepAbortRenamePath);
159 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
160 AddStep(&TaskFileManipulation::StepCreateSharedFolder);
161 AddStep(&TaskFileManipulation::StepLinkForPreload);
164 AddStep(&TaskFileManipulation::StepPrepareExternalDir);
165 AddStep(&TaskFileManipulation::StepInstallToExternal);
166 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
167 AddStep(&TaskFileManipulation::StepCreateSharedFolder);
169 AddAbortStep(&TaskFileManipulation::StepAbortCreateExternalDir);
171 AddStep(&TaskFileManipulation::EndStep);
174 void TaskFileManipulation::StepCreateDirs()
176 std::string widgetPath;
178 widgetPath = m_context.locations->getPackageInstallationDir();
180 std::string widgetBinPath = m_context.locations->getBinaryDir();
181 std::string widgetSrcPath = m_context.locations->getSourceDir();
183 WrtUtilMakeDir(widgetPath);
185 // If package type is widget with osp service, we don't need to make bin
187 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
188 _D("Doesn't need to create resource directory");
190 _D("Create resource directory");
191 WrtUtilMakeDir(widgetBinPath);
192 WrtUtilMakeDir(widgetSrcPath);
193 if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD) {
194 std::string userWidgetDir = m_context.locations->getUserDataRootDir();
195 WrtUtilMakeDir(userWidgetDir);
199 m_context.job->UpdateProgress(
200 InstallerContext::INSTALL_DIR_CREATE,
201 "Widget Directory Created");
204 void TaskFileManipulation::StepCreatePrivateStorageDir()
206 std::string storagePath = m_context.locations->getPrivateStorageDir();
207 _D("Create private storage directory : %s", m_context.locations->getPrivateStorageDir().c_str());
209 changeOwnerForDirectory(storagePath, PRIVATE_STORAGE_MODE);
211 if (m_context.isUpdateMode) { //update
212 std::string backData = m_context.locations->getBackupPrivateDir();
213 _D("copy private storage %s to %s", backData.c_str(), storagePath.c_str());
214 if (!DirectoryApi::DirectoryCopy(backData, storagePath)) {
215 _E("Failed to rename %s to %s", backData.c_str(), storagePath.c_str());
216 ThrowMsg(Exceptions::BackupFailed,
217 "Error occurs copy private strage files");
221 std::string tempStoragePath = m_context.locations->getPrivateTempStorageDir();
222 _D("Create temp private storage directory : %s", tempStoragePath.c_str());
223 changeOwnerForDirectory(tempStoragePath, PRIVATE_STORAGE_MODE);
226 void TaskFileManipulation::StepRenamePath()
230 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
231 instDir = m_context.locations->getPackageInstallationDir();
233 instDir = m_context.locations->getSourceDir();
236 _D("Copy file from temp directory to %s", instDir.c_str());
237 if (!WrtUtilRemove(instDir)) {
238 ThrowMsg(Exceptions::RemovingFolderFailure,
239 "Error occurs during removing existing folder");
242 if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(),
243 instDir.c_str()) == 0))
245 ThrowMsg(Exceptions::FileOperationFailed,
246 "Error occurs during renaming widget folder");
248 m_context.job->UpdateProgress(
249 InstallerContext::INSTALL_RENAME_PATH,
250 "Widget Rename path Finished");
253 void TaskFileManipulation::StepLinkForPreload()
255 if (m_context.mode.rootPath == InstallMode::RootPath::RO) {
256 std::string optRes = m_context.locations->getUserDataRootDir() +
257 WrtDB::GlobalConfig::GetWidgetResPath();
258 std::string usrRes = m_context.locations->getPackageInstallationDir() +
259 WrtDB::GlobalConfig::GetWidgetResPath();
261 if (0 != access(optRes.c_str(), F_OK)) {
262 _D("Make symbolic name for preload app %s to %s", usrRes.c_str(), optRes.c_str());
264 if (symlink(usrRes.c_str(), optRes.c_str()) != 0)
268 _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str());
269 ThrowMsg(Exceptions::FileOperationFailed,
270 "Symbolic link creating is not done.");
274 /* link for data directory */
275 std::string storagePath = m_context.locations->getPrivateStorageDir();
276 std::string dataDir = m_context.locations->getPackageInstallationDir() +
277 "/" + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath();
278 if (0 != access(dataDir.c_str(), F_OK)) {
279 _D("Make symbolic name for preload app %s to %s", storagePath.c_str(), dataDir.c_str());
281 if (symlink(storagePath.c_str(), dataDir.c_str()) != 0)
285 _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str());
286 ThrowMsg(Exceptions::FileOperationFailed,
287 "Symbolic link creating is not done.");
289 changeOwnerForDirectory(dataDir, PRIVATE_STORAGE_MODE);
292 if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) {
293 std::string widgetBinPath = m_context.locations->getBinaryDir();
294 std::string userBinPath = m_context.locations->getUserBinaryDir();
295 _D("Make symbolic link for preload app %s to %s", widgetBinPath.c_str(), userBinPath.c_str());
296 if (symlink(widgetBinPath.c_str(), userBinPath.c_str()) != 0)
300 _E("Failed to make a symbolic name for a file [%s]", (DPL::GetErrnoString(error)).c_str());
301 ThrowMsg(Exceptions::FileOperationFailed,
302 "Symbolic link creating is not done.");
309 void TaskFileManipulation::StepAbortRenamePath()
311 _D("[Rename Widget Path] Aborting.... (Rename path)");
312 std::string widgetPath;
313 widgetPath = m_context.locations->getPackageInstallationDir();
314 if (!WrtUtilRemove(widgetPath)) {
315 _E("Error occurs during removing existing folder");
317 // Remove user data directory if preload web app.
318 std::string userData = m_context.locations->getUserDataRootDir();
319 if (0 == access(userData.c_str(), F_OK)) {
320 if (!WrtUtilRemove(userData)) {
321 _E("Error occurs during removing user data directory");
325 _D("Rename widget path sucessful!");
328 void TaskFileManipulation::StepPrepareExternalDir()
330 _D("Step prepare to install in exernal directory");
333 DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
335 WidgetInstallToExtSingleton::Instance().initialize(pkgid);
338 Utils::getFolderSize(m_context.locations->getTemporaryPackageDir());
340 int folderSize = (int)(totalSize / (1024 * 1024)) + 1;
343 app2ext_dir_details* dirDetail = NULL;
345 dirDetail = (app2ext_dir_details*) calloc(1,
347 app2ext_dir_details));
348 if (NULL == dirDetail) {
349 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
352 dirDetail->name = strdup(GLIST_RES_DIR);
353 dirDetail->type = APP2EXT_DIR_RO;
354 list = g_list_append(list, dirDetail);
356 if (m_context.isUpdateMode) {
357 WidgetInstallToExtSingleton::Instance().preUpgrade(list,
360 WidgetInstallToExtSingleton::Instance().preInstallation(list,
366 /* make bin directory */
367 std::string widgetBinPath = m_context.locations->getBinaryDir();
368 WrtUtilMakeDir(widgetBinPath);
370 Catch(WidgetInstallToExt::Exception::ErrorInstallToExt)
372 ReThrowMsg(Exceptions::ErrorExternalInstallingFailure,
374 create external folder ");
378 void TaskFileManipulation::StepInstallToExternal()
380 _D("StepInstallExternal");
381 if (!WrtUtilMakeDir(m_context.locations->getSourceDir())) {
382 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
387 _D("Resource move to external storage %s", m_context.locations->getSourceDir().c_str());
388 if (!_FolderCopy(m_context.locations->getTemporaryPackageDir(),
389 m_context.locations->getSourceDir()))
391 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
392 "Error occurs during renaming widget folder");
396 void TaskFileManipulation::StepAbortCreateExternalDir()
398 _E("Abort StepAbortCreateExternalDir");
399 if (m_context.isUpdateMode) {
400 WidgetInstallToExtSingleton::Instance().postUpgrade(false);
402 WidgetInstallToExtSingleton::Instance().postInstallation(false);
404 WidgetInstallToExtSingleton::Instance().deinitialize();
407 void TaskFileManipulation::StepCreateSharedFolder()
409 _D("StepCreateSharedFolder");
410 std::string sharedPath = m_context.locations->getSharedRootDir();
411 _D("Create shared directory : %s", m_context.locations->getSharedRootDir().c_str());
413 WrtUtilMakeDir(sharedPath);
414 WrtUtilMakeDir(m_context.locations->getSharedResourceDir());
416 changeOwnerForDirectory(m_context.locations->getSharedDataDir(),
417 SHARED_STORAGE_MODE);
418 changeOwnerForDirectory(m_context.locations->getSharedTrustedDir(),
419 SHARED_STORAGE_MODE);
422 // additional check for rootPath installation
423 // If this app is preloaded, "shared" diretory is already on place and do not needs to be moved
424 // TODO: why "shared" is on RW partion always but "data" and "tmp" are linked
425 if (m_context.isUpdateMode
426 && !(m_context.mode.rootPath == InstallMode::RootPath::RO
427 && m_context.mode.installTime == InstallMode::InstallTime::PRELOAD)) {
429 /* Restore /shared/data */
430 _D("copy %s to %s", m_context.locations->getBackupSharedDataDir().c_str(), m_context.locations->getSharedDataDir().c_str());
431 if (!DirectoryApi::DirectoryCopy(
432 m_context.locations->getBackupSharedDataDir(),
433 m_context.locations->getSharedDataDir())) {
434 _E("Failed to rename %s to %s", m_context.locations->getBackupSharedDataDir().c_str(), m_context.locations->getSharedDataDir().c_str());
435 ThrowMsg(Exceptions::BackupFailed,
436 "Error occurs copy shared strage files");
439 /* Restore /shared/trusted */
440 _D("copy %s to %s", m_context.locations->getBackupSharedTrustedDir().c_str(), m_context.locations->getSharedTrustedDir().c_str());
441 if (!DirectoryApi::DirectoryCopy(
442 m_context.locations->getBackupSharedTrustedDir(),
443 m_context.locations->getSharedTrustedDir())) {
444 _E("Failed to rename %s to %s", m_context.locations->getBackupSharedTrustedDir().c_str(), m_context.locations->getSharedTrustedDir().c_str());
445 ThrowMsg(Exceptions::BackupFailed,
446 "Error occurs copy shared strage files");
451 void TaskFileManipulation::StartStep()
453 _D("--------- <TaskFileManipulation> : START ----------");
456 void TaskFileManipulation::EndStep()
458 _D("--------- <TaskFileManipulation> : END ----------");
460 } //namespace WidgetInstall