Modify compatibility manager
[platform/framework/native/installer.git] / src / Util / InstallerUtil.cpp
index 36680f9..e07ee81 100755 (executable)
 
 #include <sys/stat.h>
 #include <dirent.h>
+#include <dlfcn.h>
 #include <errno.h>
 #include <unistd.h>
 #include <unique_ptr.h>
+#include <vconf.h>
 
 #include <FBaseErrorDefine.h>
 #include <FIoFile.h>
 #include <FIoDirectory.h>
+#include <FAppPkgPackageAppInfo.h>
+#include <FAppPkgPackageInfo.h>
 #include <FBase_StringConverter.h>
+#include <FSecCryptoSha2Hash.h>
+#include <FApp_Aul.h>
+#include <FAppPkg_PackageManagerImpl.h>
+#include <FAppPkg_PackageInfoImpl.h>
+#include <FAppPkg_PackageAppInfoImpl.h>
 
 #include "InstallerDefs.h"
 #include "InstallerUtil.h"
 
 using namespace Tizen::Base;
 using namespace Tizen::Base::Collection;
+using namespace Tizen::Base::Utility;
 using namespace Tizen::App;
+using namespace Tizen::App::Package;
 using namespace Tizen::Io;
+using namespace Tizen::Security::Crypto;
 
 InstallerUtil::InstallerUtil(void)
 {
@@ -67,19 +79,19 @@ InstallerUtil::Remove(const Tizen::Base::String& filePath)
 
        if (S_ISLNK(fileinfo.st_mode))
        {
-               AppLog("Remove(): symlink, path=[%s]", pFilePath.get());
+               AppLog("Remove(): symlink=[%s]", pFilePath.get());
                err = unlink(pFilePath.get());
-               TryReturn(err >= 0, false, "unlink() failed(%s), filepath=[%s]", strerror(errno), pFilePath.get());
+               TryReturn(err >= 0, false, "unlink() failed(%s), file=[%s]", strerror(errno), pFilePath.get());
        }
        else if (S_ISDIR(fileinfo.st_mode))
        {
-               AppLog("Remove(): directory, path=[%ls]", filePath.GetPointer());
+               AppLog("Remove(): directory=[%ls]", filePath.GetPointer());
                r = Directory::Remove(filePath, true);
                TryReturn(!IsFailed(r), false, "Directory::Remove() failed, filePath=%ls", filePath.GetPointer());
        }
        else
        {
-               AppLog("Remove(): file, path=[%ls]", filePath.GetPointer());
+               AppLog("Remove(): file=[%ls]", filePath.GetPointer());
                r = File::Remove(filePath);
                TryReturn(!IsFailed(r), false, "File::Remove() failed, filePath=%ls", filePath.GetPointer());
        }
@@ -195,7 +207,7 @@ InstallerUtil::IsSymlink(const Tizen::Base::String& filePath)
        TryReturn(pFilePath, false, "pFilePath is null");
 
        err = lstat(pFilePath.get(), &fileinfo);
-       TryReturn(err >= 0, false, "lstat() failed(%s), filepath=[%s]", strerror(errno), pFilePath.get());
+       TryReturn(err >= 0, false, "lstat() failed(%s), file=[%s]", strerror(errno), pFilePath.get());
 
        if (S_ISLNK(fileinfo.st_mode))
        {
@@ -225,7 +237,7 @@ InstallerUtil::GetRealPath(const String& filePath, String& realPath)
 }
 
 bool
-InstallerUtil::CreateSymlink(const String& oldPath, const String& newPath)
+InstallerUtil::CreateSymlink(const String& oldPath, const String& newPath, bool SmackLabelToRealPath)
 {
        int err = -1;
        bool res = false;
@@ -248,7 +260,15 @@ InstallerUtil::CreateSymlink(const String& oldPath, const String& newPath)
 
        SmackManager smackManager;
        String label("_");
-       smackManager.AddLabelDir(label, newPath);
+
+       if (SmackLabelToRealPath == true)
+       {
+               smackManager.AddLabelDir(label, newPath);
+       }
+       else
+       {
+               smackManager.AddLabelSymlink(label, newPath);
+       }
 
        AppLog("CreateSymlink(): [%ls] -> [%ls]", newPath.GetPointer(), oldPath.GetPointer());
 
@@ -264,7 +284,7 @@ InstallerUtil::ChangeMode(const String& filePath, int mode)
        TryReturn(pFilePath, false, "pFilePath is null");
 
        err = chmod(pFilePath.get(), mode);
-       TryReturn(err == 0, false, "chmod() is failed(%s), filepath=[%s], mode=[%o]", strerror(errno), pFilePath.get(), mode);
+       TryReturn(err == 0, false, "chmod() is failed(%s), file=[%s], mode=[%o]", strerror(errno), pFilePath.get(), mode);
 
        return true;
 }
@@ -278,29 +298,29 @@ InstallerUtil::ChangeOwner(const String& filePath)
        TryReturn(pFilePath, false, "pFilePath is null");
 
        err = chown(pFilePath.get(), APP_OWNER_ID, APP_GROUP_ID);
-       TryReturn(err == 0, false, "chown() is failed(%s), filepath=[%s]", strerror(errno), pFilePath.get());
+       TryReturn(err == 0, false, "chown() is failed(%s), file=[%s]", strerror(errno), pFilePath.get());
 
        return true;
 }
 
 bool
-InstallerUtil::ChangeDirectoryPermission(const String& filePath, int mode, bool appOwner)
+InstallerUtil::ChangeDirectoryPermission(const String& file, int mode, bool appOwner)
 {
        result r = E_SUCCESS;
        bool res = false;
 
-       res = File::IsFileExist(filePath);
+       res = File::IsFileExist(file);
        if (res == false)
        {
-               AppLog("path=[%ls]: skip", filePath.GetPointer());
+               AppLog("path=[%ls]: skip", file.GetPointer());
                return true;
        }
 
        std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
        TryReturn(pDir, false, "pDir is null.");
 
-       r = pDir->Construct(filePath);
-       TryReturn(!IsFailed(r), false, "pDir->Construct() failed, filePath=[%ls]", filePath.GetPointer());
+       r = pDir->Construct(file);
+       TryReturn(!IsFailed(r), false, "pDir->Construct() failed, file=[%ls]", file.GetPointer());
 
        std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
        TryReturn(pDirEnum, false, "pDirEnum is null.");
@@ -315,7 +335,7 @@ InstallerUtil::ChangeDirectoryPermission(const String& filePath, int mode, bool
                        continue;
                }
 
-               String entryDir = filePath;
+               String entryDir = file;
                entryDir += L"/";
                entryDir += entryName;
 
@@ -353,7 +373,7 @@ InstallerUtil::ChangeDirectoryPermission(const String& filePath, int mode, bool
        }
 
        AppLog("path=[%ls], mode=[%04o], appOwner=[%s]",
-                       filePath.GetPointer(), mode, appOwner?"true":"false");
+                       file.GetPointer(), mode, appOwner?"true":"false");
 
        return true;
 }
@@ -361,13 +381,92 @@ InstallerUtil::ChangeDirectoryPermission(const String& filePath, int mode, bool
 bool
 InstallerUtil::IsDrmFile(const String& path)
 {
-       return false;
+       int ret = 0;
+       void* pHandle = null;
+       char* pErrorMsg = null;
+       int (*drm_oem_sapps_is_drm_file)(const char* pDcfPath, int dcfPathLen);
+
+       std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(path));
+       TryReturn(pFilePath, false, "pFilePath is null.");
+
+       pHandle = dlopen("/usr/lib/libdrm-service-core-sapps.so.0", RTLD_LAZY | RTLD_GLOBAL);
+       if (!pHandle)
+       {
+               AppLog("dlopen() failed. [%ls][%s]", path.GetPointer(), dlerror());
+               return false;
+       }
+
+       drm_oem_sapps_is_drm_file = reinterpret_cast <int (*)(const char*, int)>(dlsym(pHandle, "drm_oem_sapps_is_drm_file"));
+       pErrorMsg = dlerror();
+       if ((pErrorMsg != null) || (drm_oem_sapps_is_drm_file == null))
+       {
+               AppLog("dlsym() failed. [%ls][%s]", path.GetPointer(), pErrorMsg);
+               dlclose(pHandle);
+               return false;
+       }
+
+       AppLog("[drm] drm_oem_sapps_is_drm_file(%s, %d)", pFilePath.get(), strlen(pFilePath.get()));
+       ret = drm_oem_sapps_is_drm_file(pFilePath.get(), strlen(pFilePath.get()));
+       AppLog("[drm] drm_oem_sapps_is_drm_file(), result = [%d]", ret);
+
+       dlclose(pHandle);
+
+       if (ret == 1)
+       {
+               AppLog("file[%ls] is DRM file.", path.GetPointer());
+               return true;
+       }
+       else
+       {
+               return false;
+       }
 }
 
 bool
-InstallerUtil::DecryptPackage(const String& packagePath)
+InstallerUtil::DecryptPackage(const String& path, const String& decryptedPath)
 {
-       return true;
+       int ret = 0;
+       void* pHandle = null;
+       char* pErrorMsg = null;
+       int (*drm_oem_sapps_decrypt_package)(const char* pDcfPath, int dcfPathLen, const char* pDecryptedFile, int decryptedFileLen);
+
+       std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(path));
+       TryReturn(pFilePath, false, "pFilePath is null.");
+
+       std::unique_ptr<char[]> pDecryptedPath(_StringConverter::CopyToCharArrayN(decryptedPath));
+       TryReturn(pDecryptedPath, false, "pDecryptedPath is null.");
+
+       pHandle = dlopen("/usr/lib/libdrm-service-core-sapps.so.0", RTLD_LAZY | RTLD_GLOBAL);
+       if (!pHandle)
+       {
+               AppLog("dlopen() failed. [%ls][%s]", path.GetPointer(), dlerror());
+               return false;
+       }
+
+       drm_oem_sapps_decrypt_package = reinterpret_cast <int (*)(const char*, int, const char*, int)>(dlsym(pHandle, "drm_oem_sapps_decrypt_package"));
+       pErrorMsg = dlerror();
+       if ((pErrorMsg != null) || (drm_oem_sapps_decrypt_package == null))
+       {
+               AppLog("dlsym() failed. [%ls][%s]", path.GetPointer(), pErrorMsg);
+               dlclose(pHandle);
+               return false;
+       }
+
+       AppLog("[drm] drm_oem_sapps_decrypt_package(%s, %d, %s, %d)", pFilePath.get(), strlen(pFilePath.get()), pDecryptedPath.get(), strlen(pDecryptedPath.get()));
+       ret = drm_oem_sapps_decrypt_package(pFilePath.get(), strlen(pFilePath.get()), pDecryptedPath.get(), strlen(pDecryptedPath.get()));
+       AppLog("[drm] drm_oem_sapps_decrypt_package(), result = [%d]", ret);
+
+       dlclose(pHandle);
+
+       if (ret == 1)
+       {
+               AppLog("[%ls] -> [%ls] is decrypted.", path.GetPointer(), decryptedPath.GetPointer());
+               return true;
+       }
+       else
+       {
+               return false;
+       }
 }
 
 String
@@ -462,13 +561,13 @@ InstallerUtil::CreateInfoFile(const String& filePath, const String* pContext)
 bool
 InstallerUtil::DumpLog(const char* pBuf)
 {
-       char temp[4096] = {0};
        TryReturn(pBuf, false, "pBuf is null");
 
+       char temp[4096] = {0};
        int bufLen = strlen(pBuf);
-       strncpy(temp, pBuf, sizeof(temp));
+       strncpy(temp, pBuf, sizeof(temp)-1);
 
-       char *pStart = &temp[0];
+       charpStart = &temp[0];
 
        for (int i = 0; i < bufLen; i++)
        {
@@ -650,8 +749,25 @@ InstallerUtil::AppendLog(const char* pFunction, int lineNumber, bool fatal, cons
        r = file.Write(logs2, length+1);
        if (IsFailed(r))
        {
+               va_end(args);
                return false;
        }
+
+       if (pManager->IsHistoryFileLogOn() == true)
+       {
+               File historyLogFile;
+               String historyLogFilePath = pManager->GetHistoryLogFilePath();
+               r = historyLogFile.Construct(historyLogFilePath, "a");
+               if (!IsFailed(r))
+               {
+                       r = historyLogFile.Write(logs2, length+1);
+                       if (!IsFailed(r))
+                       {
+                               // success
+                       }
+               }
+       }
+
        va_end(args);
 
        return true;
@@ -711,6 +827,7 @@ InstallerUtil::PrintLog(const String& logFile)
 bool
 InstallerUtil::GetRdsList(const PackageId& packageId, IList* pDeletedList, IList* pAddedList, IList* pModifiedList)
 {
+       bool res = true;
        FILE* fp = null;
        char rdsFilePath[1024] = {0};
        char buffer[1024] = {0};
@@ -725,6 +842,8 @@ InstallerUtil::GetRdsList(const PackageId& packageId, IList* pDeletedList, IList
 
        while (fgets(buffer, sizeof(buffer), fp) != null)
        {
+               bool isMetadata = false;
+
                if (buffer[0] == '#')
                {
                        if (strcasestr(buffer, INSTALLER_RDS_DELETE_STR))
@@ -739,6 +858,8 @@ InstallerUtil::GetRdsList(const PackageId& packageId, IList* pDeletedList, IList
                        {
                                state = INSTALLER_RDS_STATE_MODIFY;
                        }
+
+                       isMetadata = true;
                }
 
                if (state == INSTALLER_RDS_STATE_NONE)
@@ -748,13 +869,16 @@ InstallerUtil::GetRdsList(const PackageId& packageId, IList* pDeletedList, IList
                }
 
                std::unique_ptr<String> pStr(new (std::nothrow) String(buffer));
-               TryReturn(pStr, false, "pStr is null.");
-               TryReturn(pStr->IsEmpty() == false, false, "pStr is empty.");
+               TryCatch(pStr, res = false, "pStr is null.");
+               TryCatch(pStr->IsEmpty() == false, res = false, "pStr is empty.");
 
                pStr->Trim();
                AppLog(".rds_delta: line(%03d)=[%ls]", line, pStr->GetPointer());
                line++;
 
+               if (isMetadata == true)
+                       continue;
+
                if (state == INSTALLER_RDS_STATE_DELETE)
                {
                        pDeletedList->Add(pStr.release());
@@ -771,7 +895,9 @@ InstallerUtil::GetRdsList(const PackageId& packageId, IList* pDeletedList, IList
                memset(buffer, 0, sizeof(buffer));
        }
 
-       return true;
+CATCH:
+       fclose(fp);
+       return res;
 }
 
 const char*
@@ -793,3 +919,251 @@ InstallerUtil::GetInstallerOperationString(int operation)
        return "Unknown";
 }
 
+bool
+InstallerUtil::GetFileDigest(const String& filePath, String& digestValue)
+{
+       const int bufSize = 64*1024;
+       int readBytes = 0;
+       result r = E_SUCCESS;
+
+       File file;
+       std::unique_ptr<Sha2Hash> pHash(new (std::nothrow) Sha2Hash());
+
+       r = pHash->SetAlgorithm("SHA2/256");
+       TryReturn(!IsFailed(r), false, "pHash->SetAlgorithm() is failed.");
+
+       r = pHash->Initialize();
+       TryReturn(!IsFailed(r), false, "pHash->Initialize() is failed.");
+
+       std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
+       TryReturn(pBuf, false, "pBuf is null");
+
+       r = file.Construct(filePath, L"r");
+       TryReturn(!IsFailed(r), false, "file.Construct() is failed.");
+
+       do
+       {
+               readBytes = file.Read(pBuf.get(), bufSize);
+               AppLog("readBytes for Hash=[%d]", readBytes);
+
+               if (readBytes > 0)
+               {
+                       ByteBuffer buffer;
+                       r = buffer.Construct((const byte*)pBuf.get(), 0, readBytes, bufSize);
+                       TryReturn(!IsFailed(r), false, "buffer.Construct() is failed.");
+
+                       r = pHash->Update(buffer);
+                       TryReturn(!IsFailed(r), false, "pHash->Update() is failed.");
+               }
+       }
+       while (readBytes > 0);
+
+       std::unique_ptr<ByteBuffer> pResultBuf(pHash->FinalizeN());
+       TryReturn(pResultBuf, false, "pResultBuf is null.");
+
+       r = StringUtil::EncodeToBase64String(*pResultBuf, digestValue);
+       TryReturn(!IsFailed(r), false, "EncodeToBase64String() is failed.");
+
+       return true;
+}
+
+IMap*
+InstallerUtil::ParseN(const String& str, const String& tokenDelimiter)
+{
+       TryReturn(str.IsEmpty() == false, null, "str is empty.");
+       TryReturn(tokenDelimiter.IsEmpty() == false, null, "tokenDelimiter is empty.");
+
+       std::unique_ptr< HashMap > pMap(new (std::nothrow) HashMap);
+       TryReturn(pMap, null, "pMap is null.");
+
+       result r = pMap->Construct();
+       TryReturn(!IsFailed(r), null, "pMap->Construct() is failed.");
+
+       StringTokenizer strTok(str, tokenDelimiter);
+       while(strTok.HasMoreTokens() == true)
+       {
+               String token;
+               r = strTok.GetNextToken(token);
+               TryReturn(!IsFailed(r), null, "strTok.GetNextToken() is failed.");
+
+               AppLog("token = [%ls]", token.GetPointer());
+
+               StringTokenizer infoTok(token, L"=");
+
+               if (infoTok.GetTokenCount() != 2)
+               {
+                       AppLog("'=' is not existed.");
+                       continue;
+               }
+
+               std::unique_ptr< String > pKey(new (std::nothrow) String);
+               r = infoTok.GetNextToken(*pKey);
+               TryReturn(!IsFailed(r), null, "infoTok.GetNextToken(*pKey) is failed.");
+               AppLog(" - key = [%ls]", pKey->GetPointer());
+
+               std::unique_ptr< String > pValue(new (std::nothrow) String);
+               r = infoTok.GetNextToken(*pValue);
+               TryReturn(!IsFailed(r), null, "infoTok.GetNextToken(*pValue) is failed.");
+               AppLog(" - value = [%ls]", pValue->GetPointer());
+
+               r = pMap->Add(pKey.release(), pValue.release());
+               TryReturn(!IsFailed(r), null, "pMap->Add() is failed.");
+       }
+
+       if (pMap->GetCount() <= 0)
+       {
+               AppLog("pMap->GetCount() is invalid.");
+               return null;
+       }
+
+       return pMap.release();
+}
+
+bool
+InstallerUtil::TerminateApp(const AppId& appId)
+{
+       bool res = true;
+
+       if (_Aul::IsRunning(appId) == true)
+       {
+               AppLog("App(%ls) is running.", appId.GetPointer());
+
+               result r = _Aul::TerminateApplication(appId);
+               TryReturn(r == E_SUCCESS, false, "TerminateApplication() failed. [%ls]", appId.GetPointer());
+
+               for (int j = 0; j < TERMINATE_RETRY_COUNT; j++)
+               {
+                       res = _Aul::IsRunning(appId);
+                       if (res == false)
+                       {
+                               AppLog("App(%ls) is terminated.", appId.GetPointer());
+                               break;
+                       }
+                       else
+                       {
+                               AppLog("App(%ls) is not terminated yet. wait count = [%d]", appId.GetPointer(), j);
+                               usleep(100000);
+                       }
+               }
+
+               if (res == true)
+               {
+                       AppLog("App(%ls) can't be terminated.", appId.GetPointer());
+                       return false;
+               }
+       }
+       else
+       {
+               AppLog("App(%ls) is not running.", appId.GetPointer());
+       }
+
+       return true;
+}
+
+bool
+InstallerUtil::TerminateApps(const PackageId& packageId)
+{
+       std::unique_ptr< PackageInfo > pPackageInfo(_PackageManagerImpl::GetInstance()->GetPackageInfoN(packageId));
+       TryReturn(pPackageInfo, false, "GetPackageInfoN() failed.");
+
+       _PackageInfoImpl* pPackageInfoImpl = _PackageInfoImpl::GetInstance(pPackageInfo.get());
+       TryReturn(pPackageInfoImpl, false, "GetInstance() failed.");
+
+       std::unique_ptr< IList > pPackageAppList(pPackageInfoImpl->GetPackageAppInfoListN());
+       TryReturn(pPackageAppList, false, "GetPackageAppInfoListN() failed.");
+
+       for (int i = 0; i < pPackageAppList->GetCount(); i++)
+       {
+               PackageAppInfo* pPackageAppInfo = dynamic_cast < PackageAppInfo* >(pPackageAppList->GetAt(i));
+               TryReturn(pPackageAppInfo, false, "pPackageAppList->GetAt(%d) failed.", i);
+
+               AppId appId = pPackageAppInfo->GetAppId();
+               TerminateApp(appId);
+       }
+
+       return true;
+}
+
+bool
+InstallerUtil::IsUninstallable(const PackageId& packageId)
+{
+       bool res = false;
+
+       std::unique_ptr< PackageInfo > pPackageInfo(_PackageManagerImpl::GetInstance()->GetPackageInfoN(packageId));
+       TryReturn(pPackageInfo, false, "GetPackageInfoN() failed.");
+
+       _PackageInfoImpl* pPackageInfoImpl = _PackageInfoImpl::GetInstance(pPackageInfo.get());
+       TryReturn(pPackageInfoImpl, false, "GetInstance() failed.");
+
+       res = pPackageInfoImpl->IsUninstallable();
+
+       AppLog("packageId[%ls]: Uninstallable = [%s]", packageId.GetPointer(), res?"true":"false");
+
+       return res;
+}
+
+bool
+InstallerUtil::IsCscPackage(const PackageId& packageId, String& cscInfo)
+{
+       bool res = false;
+       int result = 0;
+       char* pPath = null;
+       pkgmgrinfo_pkginfo_h handle = null;
+
+       std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
+       TryReturn(pPackageId, false, "pPackageId is null.");
+
+       result = pkgmgrinfo_pkginfo_get_pkginfo(pPackageId.get(), &handle);
+       TryReturn(result == PMINFO_R_OK, false, "pkgmgrinfo_pkginfo_get_pkginfo() failed. result=[%d], package=[%s]", result, pPackageId.get());
+
+       result = pkgmgrinfo_pkginfo_get_csc_path(handle, &pPath);
+       TryReturn(result == PMINFO_R_OK, false, "pkgmgrinfo_pkginfo_get_csc_path() failed. result=[%d], package=[%s]", result, pPackageId.get());
+
+       AppLog("csc_path = [%s]", pPath);
+
+       cscInfo = pPath;
+
+       if (cscInfo.IsEmpty() == false)
+       {
+               res = true;
+               AppLog("packageId[%ls]: cscInfo = [%ls]", packageId.GetPointer(), cscInfo.GetPointer());
+       }
+
+       if (handle)
+       {
+               pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+       }
+
+       return res;
+}
+
+bool
+InstallerUtil::IsDefaultExternalStorage()
+{
+       int res = 0;
+       int storage = 0;
+       int mmcStatus = VCONFKEY_SYSMAN_MMC_REMOVED;
+
+       res = vconf_get_int("db/setting/default_memory/download", &storage);
+       TryReturn(res == 0, false, "vconf_get_int(db/setting/default_memory/download) failed.");
+
+       AppLog("Storage = [%d]", storage);
+
+       if (storage == 1)
+       {
+               res = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmcStatus);
+               TryReturn(res == 0, false, "vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS) failed.");
+
+               if ((mmcStatus == VCONFKEY_SYSMAN_MMC_REMOVED) || (mmcStatus == VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED))
+               {
+                       AppLog("mmcStatus is MMC_REMOVED or NOT_MOUNTED.");
+               }
+               else
+               {
+                       AppLog("mmcStatus is MMC_MOUNTED.");
+                       return true;
+               }
+       }
+
+       return false;
+}