2 * Copyright (c) 2010 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
28 #include <vconf-internal-keys.h>
29 #include <widget_install/task_file_manipulation.h>
30 #include <widget_install/widget_install_errors.h>
31 #include <widget_install/widget_install_context.h>
32 #include <widget_install/directory_api.h>
33 #include <dpl/foreach.h>
34 #include <dpl/assert.h>
35 #include <dpl/errno_string.h>
36 #include <dpl/utils/folder_size.h>
37 #include <dpl/wrt-dao-ro/global_config.h>
39 #include <widget_install_to_external.h>
40 #include <dpl/log/secure_log.h>
41 #include <widget_unzip.h>
42 #include <boost/filesystem.hpp>
43 #include <privilege-control.h>
45 #define WEBAPP_DEFAULT_UID 5000
46 #define WEBAPP_DEFAULT_GID 5000
48 using namespace WrtDB;
49 namespace bf = boost::filesystem;
52 const bf::perms PRIVATE_STORAGE_MODE = bf::owner_all;
53 const bf::perms SHARED_STORAGE_MODE = bf::owner_all | bf::group_read
54 | bf::group_exe | bf::others_read | bf::others_exe;
58 const char* GLIST_RES_DIR = "res";
60 bool _FolderCopy(std::string source, std::string dest)
62 DIR* dir = opendir(source.c_str());
68 struct dirent *dEntryResult;
73 return_code = readdir_r(dir, &dEntry, &dEntryResult);
74 if (dEntryResult != NULL && return_code == 0) {
75 std::string fileName = dEntry.d_name;
76 std::string fullName = source + "/" + fileName;
78 if (stat(fullName.c_str(), &statInfo) != 0) {
83 if (S_ISDIR(statInfo.st_mode)) {
84 if (("." == fileName) || (".." == fileName)) {
87 bf::path destFolder(dest + "/" + fileName);
89 if(!bf::exists(destFolder)){
90 bf::create_directories(destFolder);
91 bf::permissions(destFolder,SHARED_STORAGE_MODE);
93 } catch (const bf::filesystem_error& ex) {
94 _E("boost::filesystem::error: %s",ex.what());
96 if (!_FolderCopy(fullName, destFolder.native())) {
102 std::string destFile = dest + "/" + fileName;
103 std::ifstream infile(fullName);
104 std::ofstream outfile(destFile);
105 outfile << infile.rdbuf();
109 } while (dEntryResult != NULL && return_code == 0);
116 namespace WidgetInstall {
117 TaskFileManipulation::TaskFileManipulation(JobWidgetInstall * const &jobContext) :
118 DPL::TaskDecl<TaskFileManipulation>(this),
119 m_jobContext(jobContext),
122 AddStep(&TaskFileManipulation::StartStep);
123 AddStep(&TaskFileManipulation::StepCheckInstallLocation);
124 AddStep(&TaskFileManipulation::StepPrepareRootDirectory);
125 if (m_jobContext->m_installerContext.mode.extension != InstallMode::ExtensionType::DIRECTORY)
127 AddStep(&TaskFileManipulation::StepUnzipWgtFile);
129 AddStep(&TaskFileManipulation::EndStep);
131 AddAbortStep(&TaskFileManipulation::StepAbortPrepareRootDirectory);
134 void TaskFileManipulation::StepCheckInstallLocation()
136 _D("StepCheckInstallLocation");
137 if (m_jobContext->m_installerContext.mode.rootPath == InstallMode::RootPath::RO) {
138 m_jobContext->m_installerContext.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY;
142 // If webapp is hybrid app, it should be installed to internal storage.
143 // Because Service app should be installed to internal.
144 if (m_jobContext->m_installerContext.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
145 m_jobContext->m_installerContext.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY;
149 std::string installedPath = WrtDB::GlobalConfig::GetUserInstalledWidgetPath();
151 if (m_jobContext->m_installerContext.locationType == INSTALL_LOCATION_TYPE_AUTO ||
152 m_jobContext->m_installerContext.locationType == INSTALL_LOCATION_TYPE_UNKNOWN) {
154 // vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT)
155 // 0 : phone internal memory
157 if (vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT,
159 _E("vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_INSTALL_APPLICATIONS_INT) \
162 _D("default setting : storage [%d]", storage);
164 m_jobContext->m_installerContext.locationType = INSTALL_LOCATION_TYPE_PREFER_EXTERNAL;
166 m_jobContext->m_installerContext.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY;
167 if(!m_jobContext->m_wgtUnzip->checkAvailableSpace(installedPath)) {
168 m_jobContext->m_installerContext.locationType = INSTALL_LOCATION_TYPE_PREFER_EXTERNAL;
173 if (m_jobContext->m_installerContext.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) {
175 if (vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmcStatus)) {
176 _E("vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS) failed.");
177 mmcStatus = VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED;
180 if (VCONFKEY_SYSMAN_MMC_MOUNTED != mmcStatus) {
181 _D("mmcStatus is MMC_REMOVED or NOT_MOUNTED.");
182 m_jobContext->m_installerContext.locationType = INSTALL_LOCATION_TYPE_INTERNAL_ONLY;
186 if (m_jobContext->m_installerContext.locationType == INSTALL_LOCATION_TYPE_INTERNAL_ONLY) {
187 if(!m_jobContext->m_wgtUnzip->checkAvailableSpace(installedPath)) {
188 ThrowMsg(Exceptions::OutOfStorageFailed, "There is no space for installation");
193 void TaskFileManipulation::StepPrepareRootDirectory()
195 if (m_jobContext->m_installerContext.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) {
196 prepareExternalDir();
198 bf::path widgetPath(m_jobContext->m_installerContext.locations->getPackageInstallationDir());
199 bf::path widgetBinPath(m_jobContext->m_installerContext.locations->getBinaryDir());
200 bf::path widgetSrcPath(m_jobContext->m_installerContext.locations->getSourceDir());
202 if (!m_jobContext->m_installerContext.isUpdateMode) {
203 _D("Remove existing directory : %s", widgetPath.c_str());
205 JobWidgetInstall::SecureRemove(widgetPath);
206 } catch (const bf::filesystem_error& ex) {
207 _E("Cannot remove %s! boost::filesystem::error: %s", widgetPath.c_str(),ex.what());
211 if (!bf::exists(widgetPath)) {
212 bf::create_directories(widgetPath);
213 bf::permissions(widgetPath,SHARED_STORAGE_MODE);
215 } catch (const bf::filesystem_error& ex) {
216 _E("boost::filesystem error: %s",ex.what());
219 _D("Create resource directory");
221 if(!bf::exists(widgetBinPath)){
222 bf::create_directories(widgetBinPath);
223 bf::permissions(widgetBinPath,SHARED_STORAGE_MODE);
225 } catch (const bf::filesystem_error& ex) {
226 _E("boost::filesystem error: %s",ex.what());
230 if(!bf::exists(widgetSrcPath)){
231 bf::create_directories(widgetSrcPath);
232 bf::permissions(widgetSrcPath,SHARED_STORAGE_MODE);
234 } catch (const bf::filesystem_error& ex) {
235 _E("boost::filesystem error: %s",ex.what());
239 m_jobContext->UpdateProgress(
240 InstallerContext::INSTALL_DIR_CREATE,
241 "Widget Directory Created");
244 void TaskFileManipulation::StepUnzipWgtFile()
246 if (m_jobContext->m_installerContext.widgetConfig.packagingType != PKG_TYPE_HOSTED_WEB_APP) {
248 if (m_jobContext->m_installerContext.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
249 instDir = m_jobContext->m_installerContext.locations->getPackageInstallationDir();
251 instDir = m_jobContext->m_installerContext.locations->getSourceDir();
254 _D("unzip file to %s", instDir.c_str());
255 m_jobContext->m_wgtUnzip->unzipWgtFile(instDir);
257 _D("From browser installation - unzip is not done");
260 m_jobContext->UpdateProgress(
261 InstallerContext::INSTALL_UNZIP_WGT,
265 void TaskFileManipulation::StepAbortPrepareRootDirectory()
267 _D("[Create Root Directory] Aborting.... (Rename path)");
268 if (m_jobContext->m_installerContext.locationType == INSTALL_LOCATION_TYPE_PREFER_EXTERNAL) {
269 if (m_jobContext->m_installerContext.isUpdateMode) {
270 WidgetInstallToExtSingleton::Instance().postUpgrade(false);
272 WidgetInstallToExtSingleton::Instance().postInstallation(false);
274 WidgetInstallToExtSingleton::Instance().deinitialize();
276 bf::path widgetPath(m_jobContext->m_installerContext.locations->getPackageInstallationDir());
278 JobWidgetInstall::SecureRemove(widgetPath);
279 } catch (const bf::filesystem_error& ex) {
280 _E("Error occurs during removing existing folder\n");
281 _E("boost::filesystem:error: %s", ex.what());
283 // Remove user data directory if preload web app.
284 bf::path userData(m_jobContext->m_installerContext.locations->getUserDataRootDir());
285 if (0 == access(userData.c_str(), F_OK)) {
287 JobWidgetInstall::SecureRemove(userData);
288 } catch (const bf::filesystem_error& ex) {
289 _E("Error occurs during removing user data directory");
290 _E("boost::filesystem:error: %s", ex.what());
296 void TaskFileManipulation::prepareExternalDirSmacklabel()
298 _D("Step prepare to smack label in exernal directory");
300 /* change smack label. APP2EXT set label of /.mmc and /res to pkgid.
301 In that case, file copy operation is failed because before task_smack, wrt-installer
302 wrt-installer does not contain permission for pkgid.*/
303 std::string mmcDir = m_jobContext->m_installerContext.locations->getPackageInstallationDir() + "/.mmc";
304 if (PC_OPERATION_SUCCESS != perm_app_setup_path("_", mmcDir.c_str(), APP_PATH_PRIVATE)) {
305 _W("change to wrt-installer label to %s", mmcDir.c_str());
308 std::string resDir = m_jobContext->m_installerContext.locations->getPackageInstallationDir() + "/res";
309 if (PC_OPERATION_SUCCESS != perm_app_setup_path("_", resDir.c_str(), APP_PATH_PRIVATE)) {
310 _W("change to wrt-installer label to %s", resDir.c_str());
314 void TaskFileManipulation::prepareExternalDir()
316 _D("Step prepare to install in exernal directory");
319 DPL::ToUTF8String(m_jobContext->m_installerContext.widgetConfig.tzPkgid);
321 WidgetInstallToExtSingleton::Instance().initialize(pkgid);
323 std::unique_ptr<DPL::ZipInput> zipFile(new
324 DPL::ZipInput(m_jobContext->m_installerContext.requestedPath));
325 double unzipSize = zipFile->GetTotalUncompressedSize();
326 int folderSize = (int)(unzipSize / (1024 * 1024)) + 1;
329 app2ext_dir_details* dirDetail = NULL;
331 dirDetail = (app2ext_dir_details*) calloc(1,
333 app2ext_dir_details));
334 if (NULL == dirDetail) {
335 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
338 dirDetail->name = strdup(GLIST_RES_DIR);
339 dirDetail->type = APP2EXT_DIR_RO;
340 list = g_list_append(list, dirDetail);
342 if (m_jobContext->m_installerContext.isUpdateMode) {
343 WidgetInstallToExtSingleton::Instance().preUpgrade(list,
346 WidgetInstallToExtSingleton::Instance().preInstallation(list,
352 prepareExternalDirSmacklabel();
354 /* make bin directory */
355 bf::path widgetBinPath(m_jobContext->m_installerContext.locations->getBinaryDir());
357 if(!bf::exists(widgetBinPath)){
358 bf::create_directories(widgetBinPath);
359 bf::permissions(widgetBinPath,SHARED_STORAGE_MODE);
361 } catch (const bf::filesystem_error& ex) {
362 _E("boost::filesystem::error: %s", ex.what());
365 bf::path sourceDir(m_jobContext->m_installerContext.locations->getSourceDir());
367 if(!bf::exists(sourceDir)){
368 bf::create_directories(sourceDir);
369 bf::permissions(sourceDir,SHARED_STORAGE_MODE);
371 } catch (const bf::filesystem_error& ex) {
372 _E("boost::filesystem::error: %s", ex.what());
375 Catch(DPL::ZipInput::Exception::OpenFailed) {
376 ReThrowMsg(Exceptions::ErrorExternalInstallingFailure,
378 create external folder ");
380 Catch(WidgetInstallToExt::Exception::ErrorInstallToExt)
382 ReThrowMsg(Exceptions::ErrorExternalInstallingFailure,
383 "Error during create external folder ");
387 void TaskFileManipulation::StartStep()
389 LOGI("--------- <TaskFileManipulation> : START ----------");
392 void TaskFileManipulation::EndStep()
394 LOGI("--------- <TaskFileManipulation> : END ----------");
396 } //namespace WidgetInstall