[Release] wrt-installer_0.1.114
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_file_manipulation.cpp
index db50d6b..c7b0ec6 100644 (file)
 #include <widget_install/job_widget_install.h>
 #include <widget_install/widget_install_errors.h>
 #include <widget_install/widget_install_context.h>
+#include <widget_install/directory_api.h>
 #include <dpl/utils/wrt_utility.h>
 #include <dpl/foreach.h>
 #include <dpl/log/log.h>
 #include <dpl/assert.h>
+#include <dpl/errno_string.h>
 #include <dpl/utils/folder_size.h>
+#include <dpl/wrt-dao-ro/global_config.h>
 #include <string>
 #include <fstream>
 #include <widget_install_to_external.h>
 
 namespace {
 const mode_t PRIVATE_STORAGE_MODE = 0700;
-const mode_t SHARE_MODE = 0705;
+const mode_t SHARED_STORAGE_MODE = 0755;
 }
 
 using namespace WrtDB;
 
 namespace {
 const char* GLIST_RES_DIR = "res";
-const char* GLIST_BIN_DIR = "bin";
 
 bool _FolderCopy(std::string source, std::string dest)
 {
@@ -96,6 +98,45 @@ bool _FolderCopy(std::string source, std::string dest)
     closedir(dir);
     return true;
 }
+
+void changeOwnerForDirectory(std::string storagePath, mode_t mode) {
+    if (euidaccess(storagePath.c_str(), F_OK) != 0) {
+        if (!WrtUtilMakeDir(storagePath, mode)) {
+            LogError("Failed to create directory : " << storagePath);
+            ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
+                     "Failed to create directory : " << storagePath);
+        }
+        // '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) {
+        LogDebug(storagePath << " 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(), mode) != 0) {
+            ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
+                     "chmod to 0700");
+        }
+    } else {
+        ThrowMsg(Jobs::WidgetInstall::Exceptions::FileOperationFailed,
+                 "No access to private storage.");
+    }
+}
 }
 
 namespace Jobs {
@@ -105,24 +146,29 @@ TaskFileManipulation::TaskFileManipulation(InstallerContext& context) :
     m_context(context),
     m_extHandle(NULL)
 {
+    AddStep(&TaskFileManipulation::StartStep);
     if (INSTALL_LOCATION_TYPE_EXTERNAL !=
-        m_context.locationType)
+            m_context.locationType)
     {
         AddStep(&TaskFileManipulation::StepCreateDirs);
-        AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
-        if (m_context.widgetConfig.packagingType !=
-            WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
+        if (m_context.mode.extension != InstallMode::ExtensionType::DIR)
         {
             AddStep(&TaskFileManipulation::StepRenamePath);
             AddAbortStep(&TaskFileManipulation::StepAbortRenamePath);
         }
+        AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
+        AddStep(&TaskFileManipulation::StepCreateSharedFolder);
+        AddStep(&TaskFileManipulation::StepLinkForPreload);
+
     } else {
         AddStep(&TaskFileManipulation::StepPrepareExternalDir);
         AddStep(&TaskFileManipulation::StepInstallToExternal);
         AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
+        AddStep(&TaskFileManipulation::StepCreateSharedFolder);
 
         AddAbortStep(&TaskFileManipulation::StepAbortCreateExternalDir);
     }
+    AddStep(&TaskFileManipulation::EndStep);
 }
 
 void TaskFileManipulation::StepCreateDirs()
@@ -144,6 +190,10 @@ void TaskFileManipulation::StepCreateDirs()
         LogDebug("Create resource directory");
         WrtUtilMakeDir(widgetBinPath);
         WrtUtilMakeDir(widgetSrcPath);
+        if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD) {
+            std::string userWidgetDir = m_context.locations->getUserDataRootDir();
+            WrtUtilMakeDir(userWidgetDir);
+        }
     }
 
     m_context.job->UpdateProgress(
@@ -154,43 +204,24 @@ void TaskFileManipulation::StepCreateDirs()
 void TaskFileManipulation::StepCreatePrivateStorageDir()
 {
     std::string storagePath = m_context.locations->getPrivateStorageDir();
-
-    if (euidaccess(storagePath.c_str(), F_OK) != 0) {
-        if (!WrtUtilMakeDir(storagePath, PRIVATE_STORAGE_MODE)) {
-            LogError("Failed to create directory for private storage");
-            ThrowMsg(Exceptions::InternalError,
-                     "Failed to create directory for private storage");
+    LogDebug("Create private storage directory : " <<
+            m_context.locations->getPrivateStorageDir());
+
+    changeOwnerForDirectory(storagePath, PRIVATE_STORAGE_MODE);
+
+    if (m_context.isUpdateMode) { //update
+        std::string backData = m_context.locations->getBackupPrivateDir();
+        LogDebug("copy private storage " << backData << " to " << storagePath);
+        if (!DirectoryApi::DirectoryCopy(backData, storagePath)) {
+            LogError("Failed to rename " << backData << " to " << storagePath);
+            ThrowMsg(Exceptions::BackupFailed,
+                    "Error occurs copy private strage files");
         }
-        // '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(Exceptions::InternalError,
-                     "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(Exceptions::InternalError,
-                     "Chown to invaild user");
-        }
-        if (chmod(storagePath.c_str(), PRIVATE_STORAGE_MODE) != 0) {
-            ThrowMsg(Exceptions::InternalError,
-                     "chmod to 0700");
-        }
-    } else {
-        ThrowMsg(Exceptions::InternalError,
-                 "No access to private storage.");
     }
+
+    std::string tempStoragePath = m_context.locations->getPrivateTempStorageDir();
+    LogDebug("Create temp private storage directory : " << tempStoragePath);
+    changeOwnerForDirectory(tempStoragePath, PRIVATE_STORAGE_MODE);
 }
 
 void TaskFileManipulation::StepRenamePath()
@@ -212,7 +243,7 @@ void TaskFileManipulation::StepRenamePath()
     if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(),
                  instDir.c_str()) == 0))
     {
-        ThrowMsg(Exceptions::UnknownError,
+        ThrowMsg(Exceptions::FileOperationFailed,
                  "Error occurs during renaming widget folder");
     }
     m_context.job->UpdateProgress(
@@ -220,17 +251,84 @@ void TaskFileManipulation::StepRenamePath()
         "Widget Rename path Finished");
 }
 
+void TaskFileManipulation::StepLinkForPreload()
+{
+    if (m_context.mode.rootPath == InstallMode::RootPath::RO) {
+        std::string optRes = m_context.locations->getUserDataRootDir() +
+            WrtDB::GlobalConfig::GetWidgetResPath();
+        std::string usrRes = m_context.locations->getPackageInstallationDir() +
+            WrtDB::GlobalConfig::GetWidgetResPath();
+
+        if (0 != access(optRes.c_str(), F_OK)) {
+            LogDebug("Make symbolic name for preaload app" <<
+                    usrRes << " to " << optRes);
+
+            if (symlink(usrRes.c_str(), optRes.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, PRIVATE_STORAGE_MODE);
+        }
+
+        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.packagingType != PKG_TYPE_HYBRID_WEB_APP) {
-        widgetPath = m_context.locations->getPackageInstallationDir();
-        if (!WrtUtilRemove(widgetPath)) {
-            ThrowMsg(Exceptions::RemovingFolderFailure,
-                     "Error occurs during removing existing folder");
+    widgetPath = m_context.locations->getPackageInstallationDir();
+    if (!WrtUtilRemove(widgetPath)) {
+        LogError("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)) {
+        if (!WrtUtilRemove(userData)) {
+            LogError("Error occurs during removing user data directory");
         }
     }
+
     LogDebug("Rename widget path sucessful!");
 }
 
@@ -238,10 +336,10 @@ void TaskFileManipulation::StepPrepareExternalDir()
 {
     LogDebug("Step prepare to install in exernal directory");
     Try {
-        std::string appid =
-            DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
+        std::string pkgid =
+            DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
 
-        WidgetInstallToExtSingleton::Instance().initialize(appid);
+        WidgetInstallToExtSingleton::Instance().initialize(pkgid);
 
         size_t totalSize =
             Utils::getFolderSize(m_context.locations->getTemporaryPackageDir());
@@ -251,30 +349,30 @@ void TaskFileManipulation::StepPrepareExternalDir()
         GList *list = NULL;
         app2ext_dir_details* dirDetail = NULL;
 
-        std::string dirNames[2] = { GLIST_RES_DIR, GLIST_BIN_DIR };
-
-        for (int i = 0; i < 2; i++) {
-            dirDetail = (app2ext_dir_details*) calloc(1,
-                                                      sizeof(
-                                                          app2ext_dir_details));
-            if (NULL == dirDetail) {
-                ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
-                         "error in app2ext");
-            }
-            dirDetail->name = strdup(dirNames[i].c_str());
-            dirDetail->type = APP2EXT_DIR_RO;
-            list = g_list_append(list, dirDetail);
+        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 (false == m_context.existingWidgetInfo.isExist) {
-            WidgetInstallToExtSingleton::Instance().preInstallation(list,
-                                                                    folderSize);
-        } else {
+        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)
     {
@@ -298,7 +396,7 @@ void TaskFileManipulation::StepInstallToExternal()
     if (!_FolderCopy(m_context.locations->getTemporaryPackageDir(),
                      m_context.locations->getSourceDir()))
     {
-        ThrowMsg(Exceptions::UnknownError,
+        ThrowMsg(Exceptions::ErrorExternalInstallingFailure,
                  "Error occurs during renaming widget folder");
     }
 }
@@ -306,12 +404,48 @@ void TaskFileManipulation::StepInstallToExternal()
 void TaskFileManipulation::StepAbortCreateExternalDir()
 {
     LogError("Abort StepAbortCreateExternalDir");
-    if (false == m_context.existingWidgetInfo.isExist) {
-        WidgetInstallToExtSingleton::Instance().postInstallation(false);
-    } else {
+    if (m_context.isUpdateMode) {
         WidgetInstallToExtSingleton::Instance().postUpgrade(false);
+    } else {
+        WidgetInstallToExtSingleton::Instance().postInstallation(false);
     }
     WidgetInstallToExtSingleton::Instance().deinitialize();
 }
+
+void TaskFileManipulation::StepCreateSharedFolder()
+{
+    LogDebug("StepCreateSharedFolder");
+    std::string sharedPath = m_context.locations->getSharedRootDir();
+    LogDebug("Create shared directory : " <<
+            m_context.locations->getSharedRootDir());
+
+    WrtUtilMakeDir(sharedPath);
+
+    if (m_context.isUpdateMode) { //update
+        std::string backData = m_context.locations->getBackupSharedDir();
+        LogDebug("copy shared storage " << backData << " to " << sharedPath);
+        if (!DirectoryApi::DirectoryCopy(backData, sharedPath)) {
+            LogError("Failed to rename " << backData << " to " << sharedPath);
+            ThrowMsg(Exceptions::BackupFailed,
+                    "Error occurs copy shared strage files");
+        }
+    } else {
+        WrtUtilMakeDir(m_context.locations->getSharedResourceDir());
+        changeOwnerForDirectory(m_context.locations->getSharedDataDir(),
+                SHARED_STORAGE_MODE);
+        changeOwnerForDirectory(m_context.locations->getSharedTrustedDir(),
+                SHARED_STORAGE_MODE);
+    }
+}
+
+void TaskFileManipulation::StartStep()
+{
+    LogDebug("--------- <TaskFileManipulation> : START ----------");
+}
+
+void TaskFileManipulation::EndStep()
+{
+    LogDebug("--------- <TaskFileManipulation> : END ----------");
+}
 } //namespace WidgetInstall
 } //namespace Jobs