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/utils/folder_size.h>
36 #include <widget_install_to_external.h>
38 #define WEBAPP_DEFAULT_UID 5000
39 #define WEBAPP_DEFAULT_GID 5000
42 const mode_t PRIVATE_STORAGE_MODE = 0700;
43 const mode_t SHARE_MODE = 0705;
46 using namespace WrtDB;
49 const char* GLIST_RES_DIR = "res";
50 const char* GLIST_BIN_DIR = "bin";
52 bool _FolderCopy(std::string source, std::string dest)
54 DIR* dir = opendir(source.c_str());
60 struct dirent *dEntryResult;
65 return_code = readdir_r(dir, &dEntry, &dEntryResult);
66 if (dEntryResult != NULL && return_code == 0) {
67 std::string fileName = dEntry.d_name;
68 std::string fullName = source + "/" + fileName;
70 if (stat(fullName.c_str(), &statInfo) != 0) {
75 if (S_ISDIR(statInfo.st_mode)) {
76 if (("." == fileName) || (".." == fileName)) {
79 std::string destFolder = dest + "/" + fileName;
80 WrtUtilMakeDir(destFolder);
82 if (!_FolderCopy(fullName, destFolder)) {
88 std::string destFile = dest + "/" + fileName;
89 std::ifstream infile(fullName);
90 std::ofstream outfile(destFile);
91 outfile << infile.rdbuf();
95 } while (dEntryResult != NULL && return_code == 0);
102 namespace WidgetInstall {
103 TaskFileManipulation::TaskFileManipulation(InstallerContext& context) :
104 DPL::TaskDecl<TaskFileManipulation>(this),
108 if (INSTALL_LOCATION_TYPE_EXTERNAL !=
109 m_context.locationType)
111 AddStep(&TaskFileManipulation::StepCreateDirs);
112 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
113 if (m_context.widgetConfig.packagingType !=
114 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
116 AddStep(&TaskFileManipulation::StepRenamePath);
117 AddAbortStep(&TaskFileManipulation::StepAbortRenamePath);
120 AddStep(&TaskFileManipulation::StepPrepareExternalDir);
121 AddStep(&TaskFileManipulation::StepInstallToExternal);
122 AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
124 AddAbortStep(&TaskFileManipulation::StepAbortCreateExternalDir);
128 void TaskFileManipulation::StepCreateDirs()
130 std::string widgetPath;
132 widgetPath = m_context.locations->getPackageInstallationDir();
134 std::string widgetBinPath = m_context.locations->getBinaryDir();
135 std::string widgetSrcPath = m_context.locations->getSourceDir();
137 WrtUtilMakeDir(widgetPath);
139 // If package type is widget with osp service, we don't need to make bin
141 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
142 LogDebug("Doesn't need to create resource directory");
144 LogDebug("Create resource directory");
145 WrtUtilMakeDir(widgetBinPath);
146 WrtUtilMakeDir(widgetSrcPath);
149 m_context.job->UpdateProgress(
150 InstallerContext::INSTALL_DIR_CREATE,
151 "Widget Directory Created");
154 void TaskFileManipulation::StepCreatePrivateStorageDir()
156 std::string storagePath = m_context.locations->getPrivateStorageDir();
158 if (euidaccess(storagePath.c_str(), F_OK) != 0) {
159 if (!WrtUtilMakeDir(storagePath, PRIVATE_STORAGE_MODE)) {
160 LogError("Failed to create directory for private storage");
161 ThrowMsg(Exceptions::FileOperationFailed,
162 "Failed to create directory for private storage");
164 // '5000' is default uid, gid for applications.
165 // So installed applications should be launched as process of uid
167 // the process can access private directory 'data' of itself.
168 if (chown(storagePath.c_str(),
170 WEBAPP_DEFAULT_GID) != 0)
172 ThrowMsg(Exceptions::FileOperationFailed,
173 "Chown to invaild user");
175 } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) {
176 LogInfo("Private storage already exists.");
177 // Even if private directory already is created, private dircetory
178 // should change owner.
179 if (chown(storagePath.c_str(),
181 WEBAPP_DEFAULT_GID) != 0)
183 ThrowMsg(Exceptions::FileOperationFailed,
184 "Chown to invaild user");
186 if (chmod(storagePath.c_str(), PRIVATE_STORAGE_MODE) != 0) {
187 ThrowMsg(Exceptions::FileOperationFailed,
191 ThrowMsg(Exceptions::FileOperationFailed,
192 "No access to private storage.");
196 void TaskFileManipulation::StepRenamePath()
200 if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
201 instDir = m_context.locations->getPackageInstallationDir();
203 instDir = m_context.locations->getSourceDir();
206 LogDebug("Copy file from temp directory to " << instDir);
207 if (!WrtUtilRemove(instDir)) {
208 ThrowMsg(Exceptions::RemovingFolderFailure,
209 "Error occurs during removing existing folder");
212 if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(),
213 instDir.c_str()) == 0))
215 ThrowMsg(Exceptions::FileOperationFailed,
216 "Error occurs during renaming widget folder");
218 m_context.job->UpdateProgress(
219 InstallerContext::INSTALL_RENAME_PATH,
220 "Widget Rename path Finished");
223 void TaskFileManipulation::StepAbortRenamePath()
225 LogDebug("[Rename Widget Path] Aborting.... (Rename path)");
226 std::string widgetPath;
227 if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) {
228 widgetPath = m_context.locations->getPackageInstallationDir();
229 if (!WrtUtilRemove(widgetPath)) {
230 ThrowMsg(Exceptions::RemovingFolderFailure,
231 "Error occurs during removing existing folder");
234 LogDebug("Rename widget path sucessful!");
237 void TaskFileManipulation::StepPrepareExternalDir()
239 LogDebug("Step prepare to install in exernal directory");
242 DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
244 WidgetInstallToExtSingleton::Instance().initialize(appid);
247 Utils::getFolderSize(m_context.locations->getTemporaryPackageDir());
249 int folderSize = (int)(totalSize / (1024 * 1024)) + 1;
252 app2ext_dir_details* dirDetail = NULL;
254 std::string dirNames[2] = { GLIST_RES_DIR, GLIST_BIN_DIR };
256 for (int i = 0; i < 2; i++) {
257 dirDetail = (app2ext_dir_details*) calloc(1,
259 app2ext_dir_details));
260 if (NULL == dirDetail) {
261 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
264 dirDetail->name = strdup(dirNames[i].c_str());
265 dirDetail->type = APP2EXT_DIR_RO;
266 list = g_list_append(list, dirDetail);
269 if (m_context.isUpdateMode) {
270 WidgetInstallToExtSingleton::Instance().preUpgrade(list,
273 WidgetInstallToExtSingleton::Instance().preInstallation(list,
279 Catch(WidgetInstallToExt::Exception::ErrorInstallToExt)
281 ReThrowMsg(Exceptions::ErrorExternalInstallingFailure,
283 create external folder ");
287 void TaskFileManipulation::StepInstallToExternal()
289 LogDebug("StepInstallExternal");
290 if (!WrtUtilMakeDir(m_context.locations->getSourceDir())) {
291 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
296 LogDebug("Resource move to external storage " <<
297 m_context.locations->getSourceDir());
298 if (!_FolderCopy(m_context.locations->getTemporaryPackageDir(),
299 m_context.locations->getSourceDir()))
301 ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
302 "Error occurs during renaming widget folder");
306 void TaskFileManipulation::StepAbortCreateExternalDir()
308 LogError("Abort StepAbortCreateExternalDir");
309 if (m_context.isUpdateMode) {
310 WidgetInstallToExtSingleton::Instance().postUpgrade(false);
312 WidgetInstallToExtSingleton::Instance().postInstallation(false);
314 WidgetInstallToExtSingleton::Instance().deinitialize();
316 } //namespace WidgetInstall