X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fjobs%2Fwidget_install%2Ftask_file_manipulation.cpp;h=4e257803b9f8b20d59ce2c07c78bf189dad661f7;hb=c7b504b2506c5718e1611c2258b3e345363e0a8c;hp=48abe91e86202499486c65b2cfad8c3674bfc842;hpb=083eaeb52704657feaa7a515f5b95ceb70601023;p=framework%2Fweb%2Fwrt-installer.git diff --git a/src/jobs/widget_install/task_file_manipulation.cpp b/src/jobs/widget_install/task_file_manipulation.cpp index 48abe91..4e25780 100644 --- a/src/jobs/widget_install/task_file_manipulation.cpp +++ b/src/jobs/widget_install/task_file_manipulation.cpp @@ -19,7 +19,9 @@ * @version 1.0 * @brief Implementation file for installer task database updating */ +#include #include +#include #include #include #include @@ -28,29 +30,146 @@ #include #include #include +#include +#include +#include #include +#include +#include + +#define WEBAPP_DEFAULT_UID 5000 +#define WEBAPP_DEFAULT_GID 5000 + +namespace { +const mode_t PRIVATE_STORAGE_MODE = 0700; +const mode_t SHARE_MODE = 0705; +} using namespace WrtDB; +namespace { +const char* GLIST_RES_DIR = "res"; + +bool _FolderCopy(std::string source, std::string dest) +{ + DIR* dir = opendir(source.c_str()); + if (NULL == dir) { + return false; + } + + struct dirent dEntry; + struct dirent *dEntryResult; + int return_code; + + do { + struct stat statInfo; + return_code = readdir_r(dir, &dEntry, &dEntryResult); + if (dEntryResult != NULL && return_code == 0) { + std::string fileName = dEntry.d_name; + std::string fullName = source + "/" + fileName; + + if (stat(fullName.c_str(), &statInfo) != 0) { + closedir(dir); + return false; + } + + if (S_ISDIR(statInfo.st_mode)) { + if (("." == fileName) || (".." == fileName)) { + continue; + } + std::string destFolder = dest + "/" + fileName; + WrtUtilMakeDir(destFolder); + + if (!_FolderCopy(fullName, destFolder)) { + closedir(dir); + return false; + } + } + + std::string destFile = dest + "/" + fileName; + std::ifstream infile(fullName); + std::ofstream outfile(destFile); + outfile << infile.rdbuf(); + outfile.close(); + infile.close(); + } + } while (dEntryResult != NULL && return_code == 0); + closedir(dir); + return true; +} + +void changeOwnerForDirectory(std::string storagePath) { + if (euidaccess(storagePath.c_str(), F_OK) != 0) { + if (!WrtUtilMakeDir(storagePath, PRIVATE_STORAGE_MODE)) { + LogError("Failed to create directory for private storage"); + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Failed to create directory for private storage"); + } + // '5000' is default uid, gid for applications. + // So installed applications should be launched as process of uid + // '5000'. + // the process can access private directory 'data' of itself. + if (chown(storagePath.c_str(), + WEBAPP_DEFAULT_UID, + WEBAPP_DEFAULT_GID) != 0) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Chown to invaild user"); + } + } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) { + LogInfo("Private storage already exists."); + // Even if private directory already is created, private dircetory + // should change owner. + if (chown(storagePath.c_str(), + WEBAPP_DEFAULT_UID, + WEBAPP_DEFAULT_GID) != 0) + { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "Chown to invaild user"); + } + if (chmod(storagePath.c_str(), PRIVATE_STORAGE_MODE) != 0) { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "chmod to 0700"); + } + } else { + ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed, + "No access to private storage."); + } +} +} + namespace Jobs { namespace WidgetInstall { TaskFileManipulation::TaskFileManipulation(InstallerContext& context) : DPL::TaskDecl(this), - m_context(context) + m_context(context), + m_extHandle(NULL) { - AddStep(&TaskFileManipulation::StepCreateDirs); - AddStep(&TaskFileManipulation::StepRenamePath); + if (INSTALL_LOCATION_TYPE_EXTERNAL != + m_context.locationType) + { + AddStep(&TaskFileManipulation::StepCreateDirs); + AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir); + if (m_context.widgetConfig.packagingType != + WrtDB::PKG_TYPE_DIRECTORY_WEB_APP) + { + AddStep(&TaskFileManipulation::StepRenamePath); + AddAbortStep(&TaskFileManipulation::StepAbortRenamePath); + } + AddStep(&TaskFileManipulation::StepLinkForPreload); + + } else { + AddStep(&TaskFileManipulation::StepPrepareExternalDir); + AddStep(&TaskFileManipulation::StepInstallToExternal); + AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir); - AddAbortStep(&TaskFileManipulation::StepAbortRenamePath); + AddAbortStep(&TaskFileManipulation::StepAbortCreateExternalDir); + } } void TaskFileManipulation::StepCreateDirs() { std::string widgetPath; - DPL::OptionalString pkgname = m_context.widgetConfig.pkgname; - if (pkgname.IsNull()) { - ThrowMsg(Exceptions::InternalError, "No Package name exists."); - } widgetPath = m_context.locations->getPackageInstallationDir(); @@ -61,12 +180,18 @@ void TaskFileManipulation::StepCreateDirs() // If package type is widget with osp service, we don't need to make bin // and src directory - if (m_context.widgetConfig.pType == PKG_TYPE_TIZEN_WITHSVCAPP) { + if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) { LogDebug("Doesn't need to create resource directory"); } else { LogDebug("Create resource directory"); WrtUtilMakeDir(widgetBinPath); WrtUtilMakeDir(widgetSrcPath); + if (m_context.job->getInstallerStruct().m_installMode + == InstallMode::INSTALL_MODE_PRELOAD) + { + std::string userWidgetDir = m_context.locations->getUserDataRootDir(); + WrtUtilMakeDir(userWidgetDir); + } } m_context.job->UpdateProgress( @@ -74,15 +199,19 @@ void TaskFileManipulation::StepCreateDirs() "Widget Directory Created"); } +void TaskFileManipulation::StepCreatePrivateStorageDir() +{ + std::string storagePath = m_context.locations->getPrivateStorageDir(); + LogDebug("Create private storage directory : " << + m_context.locations->getPrivateStorageDir()); + changeOwnerForDirectory(storagePath); +} + void TaskFileManipulation::StepRenamePath() { std::string instDir; - DPL::OptionalString pkgname = m_context.widgetConfig.pkgname; - if (pkgname.IsNull()) { - ThrowMsg(Exceptions::InternalError, "No Package name exists."); - } - if (m_context.widgetConfig.pType == PKG_TYPE_TIZEN_WITHSVCAPP) { + if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) { instDir = m_context.locations->getPackageInstallationDir(); } else { instDir = m_context.locations->getSourceDir(); @@ -91,38 +220,183 @@ void TaskFileManipulation::StepRenamePath() LogDebug("Copy file from temp directory to " << instDir); if (!WrtUtilRemove(instDir)) { ThrowMsg(Exceptions::RemovingFolderFailure, - "Error occurs during removing existing folder"); + "Error occurs during removing existing folder"); } - if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(), instDir.c_str()) == 0)) { - ThrowMsg(Exceptions::UnknownError, - "Error occurs during renaming widget folder"); + if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(), + instDir.c_str()) == 0)) + { + ThrowMsg(Exceptions::FileOperationFailed, + "Error occurs during renaming widget folder"); } - m_context.job->UpdateProgress( InstallerContext::INSTALL_RENAME_PATH, "Widget Rename path Finished"); } +void TaskFileManipulation::StepLinkForPreload() +{ + if (m_context.job->getInstallerStruct().m_installMode + == InstallMode::INSTALL_MODE_PRELOAD) + { + std::string srcDir = m_context.locations->getUserDataRootDir() + + WrtDB::GlobalConfig::GetWidgetSrcPath(); + + if (0 != access(srcDir.c_str(), F_OK)) { + LogDebug("Make symbolic name for preaload app" << + m_context.locations->getSourceDir() << " to " << srcDir); + std::string resDir = m_context.locations->getUserDataRootDir() + + "/res"; + + WrtUtilMakeDir(resDir); + if (symlink(m_context.locations->getSourceDir().c_str(), srcDir.c_str()) != 0) + { + int error = errno; + if (error) + LogPedantic("Failed to make a symbolic name for a file " + << "[" << DPL::GetErrnoString(error) << "]"); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + } + + /* link for data directory */ + std::string storagePath = m_context.locations->getPrivateStorageDir(); + std::string dataDir = m_context.locations->getPackageInstallationDir() + + "/" + WrtDB::GlobalConfig::GetWidgetPrivateStoragePath(); + if (0 != access(dataDir.c_str(), F_OK)) { + LogDebug("Make symbolic name for preaload app " << + storagePath << " to " << dataDir); + + if (symlink(storagePath.c_str(), dataDir.c_str()) != 0) + { + int error = errno; + if (error) + LogPedantic("Failed to make a symbolic name for a file " + << "[" << DPL::GetErrnoString(error) << "]"); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + changeOwnerForDirectory(dataDir); + } + + if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) { + std::string widgetBinPath = m_context.locations->getBinaryDir(); + std::string userBinPath = m_context.locations->getUserBinaryDir(); + LogDebug("Make symbolic link for preload app " << widgetBinPath << + " to " << userBinPath); + if (symlink(widgetBinPath.c_str(), userBinPath.c_str()) != 0) + { + int error = errno; + if (error) + LogPedantic("Failed to make a symbolic name for a file " + << "[" << DPL::GetErrnoString(error) << "]"); + ThrowMsg(Exceptions::FileOperationFailed, + "Symbolic link creating is not done."); + } + + } + } +} + void TaskFileManipulation::StepAbortRenamePath() { LogDebug("[Rename Widget Path] Aborting.... (Rename path)"); std::string widgetPath; - if (m_context.widgetConfig.pType == PKG_TYPE_TIZEN_WITHSVCAPP) { + if (m_context.widgetConfig.packagingType != PKG_TYPE_HYBRID_WEB_APP) { widgetPath = m_context.locations->getPackageInstallationDir(); - } else { - widgetPath = m_context.locations->getSourceDir(); + if (!WrtUtilRemove(widgetPath)) { + ThrowMsg(Exceptions::RemovingFolderFailure, + "Error occurs during removing existing folder"); + } + // Remove user data directory if preload web app. + std::string userData = m_context.locations->getUserDataRootDir(); + if (0 == access(userData.c_str(), F_OK)) { + WrtUtilRemove(userData); + } + } - struct stat fileInfo; - if (stat(widgetPath.c_str(), &fileInfo) != 0) { - LogError("Failed to get widget file path : " << widgetPath); - return; + LogDebug("Rename widget path sucessful!"); +} + +void TaskFileManipulation::StepPrepareExternalDir() +{ + LogDebug("Step prepare to install in exernal directory"); + Try { + std::string pkgid = + DPL::ToUTF8String(m_context.widgetConfig.tzPkgid); + + WidgetInstallToExtSingleton::Instance().initialize(pkgid); + + size_t totalSize = + Utils::getFolderSize(m_context.locations->getTemporaryPackageDir()); + + int folderSize = (int)(totalSize / (1024 * 1024)) + 1; + + GList *list = NULL; + app2ext_dir_details* dirDetail = NULL; + + dirDetail = (app2ext_dir_details*) calloc(1, + sizeof( + app2ext_dir_details)); + if (NULL == dirDetail) { + ThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "error in app2ext"); + } + dirDetail->name = strdup(GLIST_RES_DIR); + dirDetail->type = APP2EXT_DIR_RO; + list = g_list_append(list, dirDetail); + + if (m_context.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().preUpgrade(list, + folderSize); + } else { + WidgetInstallToExtSingleton::Instance().preInstallation(list, + folderSize); + } + free(dirDetail); + g_list_free(list); + + /* make bin directory */ + std::string widgetBinPath = m_context.locations->getBinaryDir(); + WrtUtilMakeDir(widgetBinPath); } + Catch(WidgetInstallToExt::Exception::ErrorInstallToExt) + { + ReThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "Error during \ + create external folder "); + } +} - if (!(rename(widgetPath.c_str(), m_context.locations->getTemporaryPackageDir().c_str()) == 0)) { - LogError("Failed to rename"); +void TaskFileManipulation::StepInstallToExternal() +{ + LogDebug("StepInstallExternal"); + if (!WrtUtilMakeDir(m_context.locations->getSourceDir())) { + ThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "To make src \ + directory failed"); } - LogDebug("Rename widget path sucessful!"); + + LogDebug("Resource move to external storage " << + m_context.locations->getSourceDir()); + if (!_FolderCopy(m_context.locations->getTemporaryPackageDir(), + m_context.locations->getSourceDir())) + { + ThrowMsg(Exceptions::ErrorExternalInstallingFailure, + "Error occurs during renaming widget folder"); + } +} + +void TaskFileManipulation::StepAbortCreateExternalDir() +{ + LogError("Abort StepAbortCreateExternalDir"); + if (m_context.isUpdateMode) { + WidgetInstallToExtSingleton::Instance().postUpgrade(false); + } else { + WidgetInstallToExtSingleton::Instance().postInstallation(false); + } + WidgetInstallToExtSingleton::Instance().deinitialize(); } } //namespace WidgetInstall } //namespace Jobs