Apply RDS copy error checking.
[platform/framework/native/installer.git] / src / Manager / PermissionManager.cpp
index 91d7e3e..d37bfe3 100755 (executable)
@@ -21,6 +21,7 @@
 
 #include <stdio.h>
 #include <sys/stat.h>
+#include <sys/capability.h>
 #include <unistd.h>
 #include <unique_ptr.h>
 
@@ -33,6 +34,7 @@
 #include "PermissionManager.h"
 #include "InstallerUtil.h"
 #include "SmackManager.h"
+#include "CompatibilityManager.h"
 
 using namespace Tizen::Base;
 using namespace Tizen::Base::Collection;
@@ -52,39 +54,52 @@ bool
 PermissionManager::SetDirectory(InstallationContext* pContext)
 {
        result r = E_SUCCESS;
+       bool res = true;
 
        String destPath;
        String appRootPath;
        SmackManager smackManager;
        smackManager.Construct(pContext);
 
+       CompatibilityManager compatibilityManager;
+       compatibilityManager.Construct(pContext);
+
        appRootPath = pContext->__rootPath;
        PackageId packageId = pContext->__packageId;
 
        // appRoot
        // InstallerUtil::ChangeOwner(appRootPath);
        InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
-       smackManager.AddLabelDir(packageId, appRootPath, true);
+       smackManager.SetupPath(packageId, appRootPath, SMACK_DIR_TYPE_ANY_LABEL, L"_");
+
+       if (pContext->__isPreloaded == true)
+       {
+               String preloadedAppPath(PATH_USR_APPS);
+               preloadedAppPath += L"/";
+               preloadedAppPath += packageId;
+
+               smackManager.SetupPath(packageId, preloadedAppPath, SMACK_DIR_TYPE_ANY_LABEL, L"_");
+       }
 
        // appRoot/bin
        destPath = appRootPath + DIR_BIN;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/info
        destPath = appRootPath + DIR_INFO;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/res
        destPath = appRootPath + DIR_RES;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/lib
        destPath = appRootPath + DIR_LIB;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/shared
        destPath = appRootPath + DIR_SHARED;
@@ -94,7 +109,6 @@ PermissionManager::SetDirectory(InstallationContext* pContext)
                TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "Directory::Create() failed");
        }
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelDir(packageId, destPath);
 
        // appRoot/shared/res
        destPath = appRootPath + DIR_SHARED_RES;
@@ -104,31 +118,29 @@ PermissionManager::SetDirectory(InstallationContext* pContext)
                InstallerUtil::CreateSymlink(iconPath, destPath);
        }
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelSharedDir(packageId, destPath);
 
        // appRoot/shared/data
        destPath = appRootPath + DIR_SHARED_DATA;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
-       smackManager.AddLabelSharedDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PUBLIC_RO);
 
        // appRoot/shared/trusted
        destPath = appRootPath + DIR_SHARED_TRUSTED;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
-       smackManager.AddLabelSharedDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_GROUP_RW);
 
        // appRoot/contents
        destPath = appRootPath + DIR_CONTENTS;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/setting
        destPath = appRootPath + DIR_SETTING;
-       if (pContext->__isAppSetting == true)
+       if (File::IsFileExist(destPath) == true)
        {
                String appVersion = pContext->__version;
                String srcPath;
                String settingXmlPath;
-
                srcPath = destPath + L"/setting." + appVersion + L".xml";
                settingXmlPath = destPath + L"/setting.xml";
 
@@ -136,7 +148,7 @@ PermissionManager::SetDirectory(InstallationContext* pContext)
                InstallerUtil::CreateSymlink(srcPath, settingXmlPath);
 
                InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
-               smackManager.AddLabelDir(packageId, destPath);
+               smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_SETTINGS_RW);
        }
 
        // appRoot/data
@@ -144,27 +156,31 @@ PermissionManager::SetDirectory(InstallationContext* pContext)
        if (File::IsFileExist(destPath) == false)
        {
                r = Directory::Create(destPath, false);
-               TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "Directory::Create() failed");
+               TryReturn(!IsFailed(r), false, "Directory::Create() failed");
        }
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
-       smackManager.AddLabelDir(packageId, destPath);
+
+       // appRoot/data/[virtualRoot]
+       if (pContext->__virtualRootPath.IsEmpty() == false)
+       {
+               res = compatibilityManager.PrepareVirtualRoot(appRootPath, packageId);
+               TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.PrepareVirtualRoot(%ls) failed.", appRootPath.GetPointer());
+       }
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        String apiVersion = pContext->__apiVersion;
 
        AppLog("------------------------------------------");
        AppLog("[Tizen::Io] # path = [%ls]", appRootPath.GetPointer());
-       AppLog("[Tizen::Io] # packageId = [%ls]", packageId.GetPointer());
+       AppLog("[Tizen::Io] # package = [%ls]", packageId.GetPointer());
        AppLog("[Tizen::Io] # apiVersion = [%ls]", apiVersion.GetPointer());
 
        if (pContext->__isOspCompat == true)
        {
                AppLog("[Tizen::Io] OSP 2.0 application");
 
-               if (_FileImpl::PrepareDataCaging(appRootPath, packageId) == false)
-               {
-                       AppLog("[Tizen::Io] _FileImpl::PrepareDataCaging() failed");
-                       return false;
-               }
+               res = compatibilityManager.PrepareDataCaging(appRootPath, packageId);
+               TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.PrepareDataCaging() failed.");
 
                SetSymLink(pContext);
        }
@@ -172,12 +188,13 @@ PermissionManager::SetDirectory(InstallationContext* pContext)
        {
                AppLog("[Tizen::Io] apiVersion is equal to or greater than Tizen 2.0");
 
-               if (_FileImpl::CreateOspApplicationDirectories(appRootPath, packageId) == false)
-               {
-                       AppLog("[Tizen::Io] _FileImpl::CreateOspApplicationDirectories() failed");
-                       return false;
-               }
+               res = compatibilityManager.CleanDirectories(appRootPath, packageId);
+               TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.CleanDirectories() failed.");
+
+               res = compatibilityManager.LinkOspSharePath(appRootPath, packageId);
+               TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.LinkOspSharePath() failed.");
        }
+
        AppLog("------------------------------------------");
 
        return true;
@@ -190,18 +207,25 @@ PermissionManager::SetFile(InstallationContext* pContext)
        String appRootPath = pContext->__rootPath;
 
        IListT<AppData*>* pAppDataList = pContext->__pAppDataList;
-       TryReturn(pAppDataList, false, "pAppDataList is null");
+       TryReturn(pAppDataList, false, "pAppDataList is null.");
 
        for (int i = 0 ; i < pAppDataList->GetCount(); i++)
        {
                AppData* pAppData = null;
                pAppDataList->GetAt(i, pAppData);
-               TryReturn(pAppData, false, "pAppData is null");
+               TryReturn(pAppData, false, "pAppData is null.");
+
+               String loader = appRootPath + DIR_BIN + L"/" + pAppData->__name;
+               if (File::IsFileExist(loader) == true)
+               {
+                       SetFileCapability(loader, pContext);
+               }
 
                // set permission(755) to bin file.
                destPath = appRootPath + DIR_BIN + L"/" + pAppData->__name + L".exe";
                if (File::IsFileExist(destPath) == true)
                {
+                       SetFileCapability(destPath, pContext);
                        InstallerUtil::ChangeMode(destPath, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
                }
        }
@@ -212,47 +236,54 @@ PermissionManager::SetFile(InstallationContext* pContext)
 bool
 PermissionManager::SetSymLink(InstallationContext* pContext)
 {
+       bool res = true;
+       int result = 0;
+       char* pCwd = null;
        String oldPath;
        String newPath;
        String appRootPath = pContext->__rootPath;
 
-#if 0
-       oldPath = appRootPath + DIR_RES;
-       newPath = appRootPath + L"/Res";
-       InstallerUtil::CreateSymlink(oldPath, newPath);
-#else
+       std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
+       TryCatch(pRootPath != null, res = false, "The memory is insufficient.");
+
+       pCwd = get_current_dir_name();
+       TryCatch(pCwd != null, res = false, "get_current_dir_name() failed.");
+
+       result = chdir(pRootPath.get());
+       TryCatch(result == 0, res = false, "chdir(%s) failed.", pRootPath.get());
+
        newPath = appRootPath + L"/Res";
-       std::unique_ptr< char[] > pResPath(_StringConverter::CopyToCharArrayN(newPath));
-       int ret = symlink("./res", pResPath.get());
-#endif
+       InstallerUtil::CreateSymlink(L"./res", newPath, false);
 
-#if 0
-       oldPath = appRootPath + DIR_DATA;
-       newPath = appRootPath + L"/Home";
-       InstallerUtil::CreateSymlink(oldPath, newPath);
-#else
        newPath = appRootPath + L"/Home";
-       std::unique_ptr< char[] > pHomePath(_StringConverter::CopyToCharArrayN(newPath));
-       ret = symlink("./data", pHomePath.get());
-#endif
+       InstallerUtil::CreateSymlink(L"./data", newPath, false);
+
+       result = chdir(pCwd);
+       TryCatch(result == 0, res = false, "chdir(%s) failed.", pCwd);
 
        oldPath = appRootPath + DIR_RES + L"/screen-size-normal";
        newPath = appRootPath + L"/Res/ScreenSize-Normal";
-       InstallerUtil::CreateSymlink(oldPath, newPath);
+       InstallerUtil::CreateSymlink(oldPath, newPath, false);
 
        oldPath = appRootPath + DIR_RES + L"/screen-density-high";
        newPath = appRootPath + L"/Res/ScreenDensity-High";
-       InstallerUtil::CreateSymlink(oldPath, newPath);
+       InstallerUtil::CreateSymlink(oldPath, newPath, false);
 
        oldPath = appRootPath + DIR_RES + L"/screen-density-middle";
        newPath = appRootPath + L"/Res/ScreenDensity-Middle";
-       InstallerUtil::CreateSymlink(oldPath, newPath);
+       InstallerUtil::CreateSymlink(oldPath, newPath, false);
 
        oldPath = appRootPath + DIR_RES + L"/screen-density-low";
        newPath = appRootPath + L"/Res/ScreenDensity-Low";
-       InstallerUtil::CreateSymlink(oldPath, newPath);
+       InstallerUtil::CreateSymlink(oldPath, newPath, false);
 
-       return true;
+CATCH:
+       if (pCwd)
+       {
+               free(pCwd);
+       }
+
+       return res;
 }
 
 bool
@@ -300,7 +331,14 @@ PermissionManager::CopyForRds(InstallationContext* pContext, IList* pFileList, b
                        Directory::Create(destDir, true);
                }
                InstallerUtil::Remove(destFile);
-               File::Copy(srcFile, destFile, true);
+
+               r = File::Copy(srcFile, destFile, true);
+               TryReturn(!IsFailed(r), false, "File::Copy() failed, [%ls] -> [%ls]", srcFile.GetPointer(), destFile.GetPointer());
+
+               if ((destFile.Contains(pContext->__packageId + DIR_BIN) == true) && (destFile.EndsWith(L".exe") == true))
+               {
+                       SetFileCapability(destFile, pContext);
+               }
 
                if (*pFilePath == L"info/manifest.xml")
                {
@@ -330,57 +368,78 @@ PermissionManager::ApplyPermissionForRds(InstallationContext* pContext)
 
        // appRoot
        InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
-       smackManager.AddLabelDir(packageId, appRootPath, true);
+       smackManager.SetupPath(packageId, appRootPath, SMACK_DIR_TYPE_ANY_LABEL, L"_");
 
        // appRoot/bin
        destPath = appRootPath + DIR_BIN;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/info
        destPath = appRootPath + DIR_INFO;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/res
        destPath = appRootPath + DIR_RES;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/lib
        destPath = appRootPath + DIR_LIB;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
 
        // appRoot/shared
        destPath = appRootPath + DIR_SHARED;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelDir(packageId, destPath);
 
        // appRoot/shared/res
        destPath = appRootPath + DIR_SHARED_RES;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
-       smackManager.AddLabelSharedDir(packageId, destPath);
 
        // appRoot/shared/data
        destPath = appRootPath + DIR_SHARED_DATA;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
-       smackManager.AddLabelSharedDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PUBLIC_RO);
 
        // appRoot/shared/trusted
        destPath = appRootPath + DIR_SHARED_TRUSTED;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
-       smackManager.AddLabelSharedDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_GROUP_RW);
 
        // appRoot/setting
        destPath = appRootPath + DIR_SETTING;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_SETTINGS_RW);
 
        // appRoot/data
        destPath = appRootPath + DIR_DATA;
        InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
-       smackManager.AddLabelDir(packageId, destPath);
+       smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
+
+       return true;
+}
+
+bool
+PermissionManager::SetFileCapability(const String& path, InstallationContext* pContext)
+{
+       TryReturn(path.IsEmpty() == false, false, "path is empty.");
+       TryReturn(pContext, false, "pContext is null.");
+
+       if (pContext->__isPreloaded == true)
+       {
+               AppLog("cap_set_file() is skipped.");
+               return true;
+       }
+
+       std::unique_ptr<char[]> pPath(_StringConverter::CopyToCharArrayN(path));
+       TryReturn(pPath != null, false, "The memory is insufficient.");
+
+       int res = cap_set_file(pPath.get(), cap_from_text("CAP_NET_RAW,CAP_SYS_CHROOT+i"));
+       TryReturn(res == 0, false, "cap_set_file() failed. [res = %d]", res);
+
+       AppLog("cap_set_file(%s, cap_from_text(CAP_NET_RAW,CAP_SYS_CHROOT+i)) called.", pPath.get());
 
        return true;
 }