X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=NativeLauncher%2Finstaller-plugin%2Fprefer_nuget_cache_plugin.cc;h=30518b12f5a51a882aea4ae6cd0d5c0c064f71cf;hb=ebad648f17029c908403b945f4c04631a25e4312;hp=8ae9e00aae9ddc15b73fa3847dd125ff1af27c3a;hpb=d864d641984681445948f588235047ff89d3dee8;p=platform%2Fcore%2Fdotnet%2Flauncher.git diff --git a/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc b/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc index 8ae9e00..30518b1 100644 --- a/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc +++ b/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc @@ -17,20 +17,17 @@ #include "log.h" #include "utils.h" #include "db_manager.h" -#include "path_manager.h" -#include "plugin_manager.h" #include "tac_common.h" #include #include +#include #include #include #include #include #include #include -#include -#include #ifdef LOG_TAG #undef LOG_TAG @@ -43,115 +40,18 @@ static const char* __DOTNET_DIR = __STR(DOTNET_DIR); #undef __STR #undef __XSTR -typedef struct Metadata { - const char *key; - const char *value; -} Metadata; - std::vector nugetPackagesAssembliesSha; std::vector tacDB; std::vector createDirectories; +std::vector createLibraries; std::vector updateTac; std::string status = ""; -std::string rootPath; -std::string execName; -std::string binPath; static sqlite3 *tac_db = NULL; +static sqlite3 *tlc_db = NULL; bool tacPluginInstalled = false; bool tacPluginFinished = false; -bool metadataCheck(GList *list) -{ - GList *tag = NULL; - Metadata *mdInfo = NULL; - tag = g_list_first(list); - mdInfo = (Metadata*)tag->data; - if (strcmp(mdInfo->key, TAC_METADATA_KEY) == 0 && strcmp(mdInfo->value, METADATA_VALUE) == 0) { - _DBG("Prefer nuget cache set TRUE"); - if (initializePluginManager("normal")) { - _ERR("Fail to initialize PluginManager"); - return false; - } - if (initializePathManager(std::string(), std::string(), std::string())) { - _ERR("Fail to initialize PathManger"); - return false; - } - return true; - } - return false; -} - -bool appTypeCheck(std::string pkgId) -{ - uid_t uid = 0; - if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { - _ERR("Failed to get UID"); - return false; - } - - pkgmgrinfo_pkginfo_h handle; - int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle); - if (ret != PMINFO_R_OK) { - _ERR("Failed to get pkg info"); - return false; - } - - bool isDotnetAppType = false; - auto dotnetAppCounter = [] (pkgmgrinfo_appinfo_h handle, void *userData) -> int { - char* type = nullptr; - bool* dotnet = static_cast(userData); - if (pkgmgrinfo_appinfo_get_apptype(handle, &type) != PMINFO_R_OK) { - _ERR("Failed to get app type : %s", type); - return -1; - } - if (strcmp(type, "dotnet") == 0) { - *dotnet = true; - } - return 0; - }; - - if (pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, dotnetAppCounter, &isDotnetAppType, uid) != PMINFO_R_OK) { - _ERR("Failed to get list of app in pkg : %s", pkgId.c_str()); - pkgmgrinfo_pkginfo_destroy_pkginfo(handle); - return false; - } - - pkgmgrinfo_pkginfo_destroy_pkginfo(handle); - return isDotnetAppType; -} - -void SHA256(std::string path, char outputBuffer[65]) -{ - FILE *file = fopen(path.c_str(), "rb"); - if (!file) { - return; - } - - unsigned char hash[SHA256_DIGEST_LENGTH]; - SHA256_CTX sha256; - SHA256_Init(&sha256); - int bytesRead = 0; - const int bufSize = 32768; - char *buffer = (char*)malloc(bufSize); - if (!buffer) { - fclose(file); - return; - } - - while ((bytesRead = fread(buffer, 1, bufSize, file))) { - SHA256_Update(&sha256, buffer, bytesRead); - } - SHA256_Final(hash, &sha256); - for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { - snprintf(outputBuffer + (i * 2), 3, "%02x", hash[i]); - } - outputBuffer[64] = 0; - - fclose(file); - free(buffer); -} - -void createSHA256Info(std::string sha256Info, std::string nugetPackage) +static void createSHA256Info(std::string sha256Info, std::string nugetPackage) { std::ofstream ofs(sha256Info, std::ios::app); int assembly_count = 0; @@ -169,7 +69,7 @@ void createSHA256Info(std::string sha256Info, std::string nugetPackage) ofs.close(); } -int compareSHA256Info(std::string sha256Info, std::string nugetPackage) +static bool compareSHA256Info(std::string sha256Info, std::string nugetPackage) { int compare_count = 0; int assembly_count = 0; @@ -197,62 +97,109 @@ int compareSHA256Info(std::string sha256Info, std::string nugetPackage) if (!strcmp(std::to_string(assembly_count).c_str(), std::to_string(compare_count).c_str()) && !strcmp(std::to_string(assembly_count).c_str(), sha256_count.c_str())) { _INFO("Same nuget : %s", nugetPackage.c_str()); - return 1; + return true; } - return 0; + return false; } -int copyNCreateSymlink(std::string tacVersionDir, std::string nugetPackage, bool isCreateTacDir) +static bool copyAssemblyCreateSymlink(std::string binPath, std::string tacDir, std::string nugetPackage, bool isCreateTacDir) { - uid_t g_uid = 0; - gid_t g_gid = 0; - if (pkgmgr_installer_info_get_target_uid(&g_uid) < 0) { - _ERR("Failed to get UID"); - return -1; - } - - std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR); - if (!createDir(tac_dir)) { - _ERR("Cannot create directory: %s", tac_dir.c_str()); - return -1; - } - + std::string tac_version_dir = concatPath(__DOTNET_DIR, nugetPackage); + bool nuget_restoration = false; for (auto& npAssemblySha : nugetPackagesAssembliesSha) { std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind(':')); std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind(':')); std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind(':') + 1); if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) { - if (bf::exists(concatPath(binPath, assembly))) { + if (exist(concatPath(binPath, assembly))) { if (isCreateTacDir) { - if (!copyFile(concatPath(binPath, assembly), concatPath(tacVersionDir, assembly))) { + if (!copyFile(concatPath(binPath, assembly), concatPath(tac_version_dir, assembly))) { _ERR("Failed to copy of %s", assembly.c_str()); - return -1; + nuget_restoration = true; + break; } } - bf::create_symlink(concatPath(tacVersionDir, assembly), concatPath(tac_dir, assembly)); - if (lchown(concatPath(tac_dir, assembly).c_str(), g_uid, g_gid)) { - _ERR("Failed to change owner of: %s", concatPath(tac_dir, assembly).c_str()); - return -1; - } + bf::create_symlink(concatPath(tac_version_dir, assembly), concatPath(tacDir, assembly)); + copySmackAndOwnership(tacDir, concatPath(tacDir, assembly), true); + if (!removeFile(concatPath(binPath, assembly))) { _ERR("Failed to remove of %s", assembly.c_str()); - return -1; + nuget_restoration = true; + break; } } } } - return 0; + + if (nuget_restoration) { + for (auto& npAssemblySha : nugetPackagesAssembliesSha) { + std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind(':')); + std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind(':')); + std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind(':') + 1); + if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) { + copyFile(concatPath(tac_version_dir, assembly), concatPath(binPath, assembly)); + copySmackAndOwnership(binPath, concatPath(binPath, assembly)); + removeFile(concatPath(tacDir, assembly)); + } + } + } + + return nuget_restoration; +} + +static void copyLibraryCreateSymlink(const char* pkgId, std::vector LibrariesInfo, std::string tlcDir) +{ + if (LibrariesInfo.empty()) { + return; + } + + for (auto& librarySha : LibrariesInfo) { + std::string library = librarySha.substr(0, librarySha.find(':')); + std::string filename = library.substr(library.rfind('/') + 1); + std::string fileSha = filename + ".." + librarySha.substr(librarySha.find(':') + 1); + bool fileCopied = false; + if (!exist(concatPath(tlcDir, fileSha))) { + if (!copyFile(library, concatPath(tlcDir, fileSha))) { + _ERR("Failed to copy of %s", filename.c_str()); + continue; + } + fileCopied = true; + createLibraries.push_back(concatPath(tlcDir, fileSha)); + } + if (!removeFile(library)) { + _ERR("Failed to remove of %s", library.c_str()); + if (fileCopied) { + removeFile(concatPath(tlcDir, fileSha)); + } + continue; + } + bf::create_symlink(concatPath(tlcDir, fileSha), library); + copySmackAndOwnership(getBaseName(library), library, true); + + char *sql = sqlite3_mprintf("INSERT INTO TLC (PKGID, LIBRARY) VALUES (%Q, %Q);", pkgId, fileSha.c_str()); + if (!insertDB(tlc_db, sql)) { + _ERR("Sqlite insert error"); + sqlite3_free(sql); + copyFile(concatPath(tlcDir, fileSha), library); + copySmackAndOwnership(getBaseName(library), library); + if (fileCopied) { + removeFile(concatPath(tlcDir, fileSha)); + } + continue; + } + sqlite3_free(sql); + } } -void depsJsonCheck() { - for (auto& npAssembly : depsJsonParser(rootPath, execName, getTPA())) { +static void checkDepsJson(std::string rootPath, std::string binPath, std::string execName) +{ + for (auto& npAssembly : depsJsonParser(rootPath, execName)) { std::string nuget_package = npAssembly.substr(0, npAssembly.rfind(':')); std::string assembly_name = npAssembly.substr(npAssembly.rfind(':') + 1); tacDB.push_back(nuget_package); - char buffer[65] = {0}; - SHA256(concatPath(binPath, assembly_name), buffer); + std::string buffer = SHA256(concatPath(binPath, assembly_name)); nugetPackagesAssembliesSha.push_back(nuget_package + ":" + assembly_name + ":" + buffer); - _INFO("Assembly : [%s] / SHA256 : [%s]", assembly_name.c_str(), buffer); + _INFO("Assembly : [%s] / SHA256 : [%s]", assembly_name.c_str(), buffer.c_str()); } std::sort(tacDB.begin(), tacDB.end()); tacDB.erase(unique(tacDB.begin(), tacDB.end()), tacDB.end()); @@ -270,33 +217,51 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app } tacPluginInstalled = true; - if (!appTypeCheck(std::string(pkgId))) { - _INFO("App type is not dotnet"); + std::string appType = getAppType(std::string(pkgId)); + if (strstr(appType.c_str(), "dotnet") == NULL) { + _ERR("App type is not dotnet"); return 0; } - if (getExecName(std::string(pkgId), execName) < 0) { + std::string execName = getExecName(std::string(pkgId)); + std::string rootPath = getRootPath(std::string(pkgId)); + if (execName.empty() || rootPath.empty()) { return 0; } - if (getRootPath(std::string(pkgId), rootPath) < 0) { + std::string binPath = concatPath(rootPath, "bin"); + std::string metaValue = getMetadataValue(std::string(pkgId), TAC_METADATA_KEY); + if (metaValue.empty()) { return 0; - } else { - binPath = concatPath(rootPath, "bin"); } - if (metadataCheck(list)) { - depsJsonCheck(); + if (metaValue == METADATA_VALUE) { + checkDepsJson(rootPath, binPath, execName); } status = "install"; - tac_db = dbCreate(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); - if (!tac_db) { - _ERR("Sqlite create error"); + if (tacDB.empty()) { return 0; } - if (tacDB.empty()) { - _INFO("Not exist data for TAC in %s", pkgId); + tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); + if (!tac_db) { + _ERR("Sqlite create error. So restore the database."); + if (tac_restoreDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return -1; + } + tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); + if (!tac_db) { + _ERR("Sqlite create error"); + return -1; + } + } + sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL); + + std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR); + if (!createDir(tac_dir)) { + _ERR("Cannot create directory: %s", tac_dir.c_str()); return 0; } + copySmackAndOwnership(binPath.c_str(), tac_dir.c_str()); for (auto& np : tacDB) { std::string tac_name = np.substr(0, np.find('/')); @@ -306,68 +271,111 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app std::string tac_version_dir = concatPath(__DOTNET_DIR, np); std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO); - if (!bf::exists(tac_version_dir)) { + if (!exist(tac_version_dir)) { _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str()); if (!createDir(tac_version_dir)) { _ERR("Cannot create directory: %s", tac_version_dir.c_str()); - return 0; + status = "restore"; + return -1; } createDirectories.push_back(tac_version_dir); if (!bf::is_symlink(sha256_info)) { createSHA256Info(sha256_info, np); } else { _ERR("Failed to create sha256_info. Symbolic link is detected"); + status = "restore"; + return -1; + } + + if (!exist(sha256_info)) { + status = "restore"; return -1; } - if (copyNCreateSymlink(tac_version_dir, np, true) < 0) { + if (copyAssemblyCreateSymlink(binPath, tac_dir, np, true)) { _ERR("Failed to create symlink"); + status = "restore"; return -1; } char *sql = sqlite3_mprintf( "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ "VALUES (%Q, %Q, %Q, %Q);", pkgId, np.c_str(), tac_name.c_str(), tac_version.c_str()); - dbInsert(tac_db, TAC_APP_LIST_DB, sql); + if (!insertDB(tac_db, sql)) { + _ERR("Sqlite insert error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } sqlite3_free(sql); } else { _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str()); if (!bf::is_symlink(sha256_info)) { if (compareSHA256Info(sha256_info, np)) { - if (copyNCreateSymlink(tac_version_dir, np, false) < 0) { + if (copyAssemblyCreateSymlink(binPath, tac_dir, np, false)) { _ERR("Failed to create symlink"); + status = "restore"; return -1; } char *sql = sqlite3_mprintf( "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ "VALUES (%Q, %Q, %Q, %Q);", pkgId, np.c_str(), tac_name.c_str(), tac_version.c_str()); - dbInsert(tac_db, TAC_APP_LIST_DB, sql); + if (!insertDB(tac_db, sql)) { + _ERR("Sqlite insert error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } sqlite3_free(sql); } else { _INFO("Different nuget : %s", np.c_str()); + continue; } } else { _ERR("Failed to create sha256_info. Symbolic link is detected"); + status = "restore"; return -1; } } - if (!bf::exists(sha256_info)) { - if(!removeAll(tac_version_dir)) { - _ERR("Failed to remove of %s", tac_version_dir.c_str()); - } + } + + ///// TLC ///// + std::string tlcDir = concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR); + if (!createDir(tlcDir)) { + _ERR("Cannot create directory: %s", tlcDir.c_str()); + return 0; + } + copySmackAndOwnership(__DOTNET_DIR, tlcDir); + + tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error. So restore the database."); + if (tlc_restoreDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return 0; + } + tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error"); + return 0; } } + sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL); + + copyLibraryCreateSymlink(pkgId, getLibrariesInfo(rootPath), tlcDir); + return 0; } -static int sqliteCb(void *count, int argc, char **argv, char **colName) { +static int sqliteCb(void *count, int argc, char **argv, char **colName) +{ int *c = (int*)count; *c = atoi(argv[0]); return 0; } -int updateTacDB(sqlite3 *sqlite) +static void tac_updateDB(sqlite3 *sqlite) { for (auto& unp : updateTac) { int count = -1; @@ -376,7 +384,7 @@ int updateTacDB(sqlite3 *sqlite) if (ret != SQLITE_OK) { _ERR("Sqlite select error"); sqlite3_free(sql); - return -1; + continue; } if (count == 0) { std::string tac_version_dir_prev = concatPath(__DOTNET_DIR, unp); @@ -384,17 +392,45 @@ int updateTacDB(sqlite3 *sqlite) if (!copyDir(tac_version_dir_prev, tac_version_dir_backup)) { _ERR("Failed to copy of %s to %s", tac_version_dir_prev.c_str(), tac_version_dir_backup.c_str()); sqlite3_free(sql); - return -1; + continue; } if (!removeAll(tac_version_dir_prev)) { _ERR("Failed to remove of %s", tac_version_dir_prev.c_str()); sqlite3_free(sql); - return -1; + continue; + } + } + sqlite3_free(sql); + } +} + +static void tlc_updateDB(sqlite3 *sqlite, std::vector updateTlc, std::string tlcDir) +{ + for (auto& ulp : updateTlc) { + int count = -1; + char *sql = sqlite3_mprintf("SELECT COUNT(LIBRARY) FROM TLC WHERE LIBRARY = %Q;", ulp.c_str()); + int ret = sqlite3_exec(sqlite, sql, sqliteCb, &count, NULL); + if (ret != SQLITE_OK) { + _ERR("Sqlite select error"); + sqlite3_free(sql); + continue; + } + if (count == 0) { + std::string library_prev = concatPath(tlcDir, ulp); + std::string library_backup = library_prev + ".bck"; + if (!copyFile(library_prev, library_backup)) { + _ERR("Failed to copy of %s", library_prev.c_str()); + sqlite3_free(sql); + continue; + } + if (!removeFile(library_prev)) { + _ERR("Failed to remove of %s", library_prev.c_str()); + sqlite3_free(sql); + continue; } } sqlite3_free(sql); } - return 0; } extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *appId, GList *list) @@ -409,47 +445,71 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app } tacPluginInstalled = true; - if (!appTypeCheck(std::string(pkgId))) { - _INFO("App type is not dotnet"); - return 0; - } - if (getExecName(std::string(pkgId), execName) < 0) { + std::string appType = getAppType(std::string(pkgId)); + if (strstr(appType.c_str(), "dotnet") == NULL) { + _ERR("App type is not dotnet"); return 0; } - if (getRootPath(std::string(pkgId), rootPath) < 0) { + std::string execName = getExecName(std::string(pkgId)); + std::string rootPath = getRootPath(std::string(pkgId)); + if (execName.empty() || rootPath.empty()) { return 0; - } else { - binPath = concatPath(rootPath, "bin"); } + std::string binPath = concatPath(rootPath, "bin"); + if (!strcmp("removed", status.c_str())) { _INFO("Skipped to parse of deps.json"); } else { - if (metadataCheck(list)) { - depsJsonCheck(); + std::string metaValue = getMetadataValue(std::string(pkgId), TAC_METADATA_KEY); + if (metaValue.empty()) { + return 0; + } + if (metaValue == METADATA_VALUE) { + checkDepsJson(rootPath, binPath, execName); } } status = "update"; - tac_db = dbCreate(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); + tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); if (!tac_db) { - _ERR("Sqlite open error"); - return 0; + _ERR("Sqlite create error. So restore the database."); + if (tac_restoreDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return -1; + } + tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); + if (!tac_db) { + _ERR("Sqlite create error"); + return -1; + } } + sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL); char *sql = sqlite3_mprintf("SELECT * FROM TAC WHERE PKGID = %Q;", pkgId); - updateTac = dbSelect(tac_db, TAC_APP_LIST_DB, sql); + updateTac = selectDB(tac_db, sql); sqlite3_free(sql); + bool skipTLC = false; if (tacDB.empty()) { sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q;", pkgId); - dbDelete(tac_db, TAC_APP_LIST_DB, sql); - sqlite3_free(sql); - if (updateTacDB(tac_db) < 0) { + if (!deleteDB(tac_db, sql)) { + _ERR("Sqlite delete error"); + sqlite3_free(sql); return -1; } - _INFO("Not exist data for TAC in %s", pkgId); - return 0; + sqlite3_free(sql); + + tac_updateDB(tac_db); + + skipTLC = true; } else { + std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR); + if (!createDir(tac_dir)) { + _ERR("Cannot create directory: %s", tac_dir.c_str()); + return 0; + } + copySmackAndOwnership(binPath.c_str(), tac_dir.c_str()); + for (auto& np : tacDB) { std::string tac_name = np.substr(0, np.find('/')); std::string tac_version = np.substr(np.rfind('/') + 1); @@ -458,22 +518,30 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app std::string tac_version_dir = concatPath(__DOTNET_DIR, np); std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO); - if (!bf::exists(tac_version_dir)) { + if (!exist(tac_version_dir)) { _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str()); if (!createDir(tac_version_dir)) { _ERR("Cannot create directory: %s", tac_version_dir.c_str()); - return 0; + status = "restore"; + return -1; } createDirectories.push_back(tac_version_dir); if (!bf::is_symlink(sha256_info)) { createSHA256Info(sha256_info, np); } else { _ERR("Failed to create sha256_info. Symbolic link is detected"); + status = "restore"; return -1; } - if (copyNCreateSymlink(tac_version_dir, np, true) < 0) { + if (!exist(sha256_info)) { + status = "restore"; + return -1; + } + + if (copyAssemblyCreateSymlink(binPath, tac_dir, np, true)) { _ERR("Failed to create symlink"); + status = "restore"; return -1; } @@ -484,6 +552,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app if (ret != SQLITE_OK) { _ERR("Sqlite select error"); sqlite3_free(sql); + status = "restore"; return -1; } sqlite3_free(sql); @@ -491,21 +560,32 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app sql = sqlite3_mprintf( "UPDATE TAC SET NAME = %Q, VERSION = %Q, NUGET = %Q WHERE PKGID = %Q AND NAME = %Q;", tac_name.c_str(), tac_version.c_str(), np.c_str(), pkgId, tac_name.c_str()); - dbUpdate(tac_db, TAC_APP_LIST_DB, sql); + if (!updateDB(tac_db, sql)) { + _ERR("Sqlite update error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } sqlite3_free(sql); } else if (count == 0) { sql = sqlite3_mprintf( "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ "VALUES (%Q, %Q, %Q, %Q);", pkgId, np.c_str(), tac_name.c_str(), tac_version.c_str()); - dbInsert(tac_db, TAC_APP_LIST_DB, sql); + if (!insertDB(tac_db, sql)) { + _ERR("Sqlite insert error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } sqlite3_free(sql); } } else { _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str()); if (!bf::is_symlink(sha256_info)) { if (compareSHA256Info(sha256_info, np)) { - if (copyNCreateSymlink(tac_version_dir, np, false) < 0) { + if (copyAssemblyCreateSymlink(binPath, tac_dir, np, false)) { _ERR("Failed to create symlink"); + status = "restore"; return -1; } @@ -516,6 +596,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app if (ret != SQLITE_OK) { _ERR("Sqlite select error"); sqlite3_free(sql); + status = "restore"; return -1; } sqlite3_free(sql); @@ -523,28 +604,35 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app sql = sqlite3_mprintf( "UPDATE TAC SET NAME = %Q, VERSION = %Q, NUGET = %Q WHERE PKGID = %Q AND NAME = %Q;", tac_name.c_str(), tac_version.c_str(), np.c_str(), pkgId, tac_name.c_str()); - dbUpdate(tac_db, TAC_APP_LIST_DB, sql); + if (!updateDB(tac_db, sql)) { + _ERR("Sqlite update error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } sqlite3_free(sql); } else if (count == 0) { sql = sqlite3_mprintf( "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ "VALUES (%Q, %Q, %Q, %Q);", pkgId, np.c_str(), tac_name.c_str(), tac_version.c_str()); - dbInsert(tac_db, TAC_APP_LIST_DB, sql); + if (!insertDB(tac_db, sql)) { + _ERR("Sqlite insert error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } sqlite3_free(sql); } } else { _INFO("Different nuget : %s", np.c_str()); + continue; } } else { _ERR("Failed to create sha256_info. Symbolic link is detected"); + status = "restore"; return -1; } } - if (!bf::exists(sha256_info)) { - if(!removeAll(tac_version_dir)) { - _ERR("Failed to remove of %s", tac_version_dir.c_str()); - } - } } for (auto& unp : updateTac) { bool isExits = false; @@ -556,14 +644,62 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app } if (!isExits) { char *sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q AND NUGET = %Q;", pkgId, unp.c_str()); - dbDelete(tac_db, TAC_APP_LIST_DB, sql); + if (!deleteDB(tac_db, sql)) { + _ERR("Sqlite delete error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } sqlite3_free(sql); } } - if (updateTacDB(tac_db) < 0) { - return -1; + tac_updateDB(tac_db); + } + + ///// TLC ///// + std::string tlcDir = concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR); + if (!createDir(tlcDir)) { + _ERR("Cannot create directory: %s", tlcDir.c_str()); + return 0; + } + copySmackAndOwnership(__DOTNET_DIR, tlcDir); + + tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error. So restore the database."); + if (tlc_restoreDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return 0; + } + tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error"); + return 0; } } + sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL); + + sql = sqlite3_mprintf("SELECT * FROM TLC WHERE PKGID = %Q;", pkgId); + std::vector updateTlc = selectDB(tlc_db, sql); + sqlite3_free(sql); + + sql = sqlite3_mprintf("DELETE FROM TLC WHERE PKGID = %Q;", pkgId); + if (!deleteDB(tlc_db, sql)) { + _ERR("Sqlite delete error"); + sqlite3_free(sql); + return 0; + } + sqlite3_free(sql); + + std::vector librariesInfo; + if (!skipTLC) { + librariesInfo = getLibrariesInfo(rootPath); + } + + copyLibraryCreateSymlink(pkgId, librariesInfo, tlcDir); + + tlc_updateDB(tlc_db, updateTlc, tlcDir); + return 0; } @@ -580,23 +716,67 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *a tacPluginInstalled = true; status = "uninstall"; - tac_db = dbOpen(TAC_APP_LIST_DB); + tac_db = openDB(TAC_APP_LIST_DB); if (!tac_db) { - _ERR("Sqlite open error"); - return 0; + _ERR("Sqlite open error. So restore the database."); + if (tac_restoreDB() != TAC_ERROR_NONE) { + _ERR("Sqlite open error"); + return -1; + } + tac_db = openDB(TAC_APP_LIST_DB); + if (!tac_db) { + _ERR("Sqlite open error"); + return -1; + } } + sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL); char *sql = sqlite3_mprintf("SELECT * FROM TAC WHERE PKGID = %Q;", pkgId); - updateTac = dbSelect(tac_db, TAC_APP_LIST_DB, sql); + updateTac = selectDB(tac_db, sql); sqlite3_free(sql); sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q;", pkgId); - dbDelete(tac_db, TAC_APP_LIST_DB, sql); - sqlite3_free(sql); - if (updateTacDB(tac_db) < 0) { + if (!deleteDB(tac_db, sql)) { + _ERR("Sqlite delete error"); + sqlite3_free(sql); + status = "restore"; return -1; } + sqlite3_free(sql); + + tac_updateDB(tac_db); + + ///// TLC ///// + tlc_db = openDB(TLC_APP_LIST_DB); + if (!tlc_db) { + _ERR("Sqlite open error. So restore the database."); + if (tlc_restoreDB() != TAC_ERROR_NONE) { + _ERR("Sqlite open error"); + return 0; + } + tlc_db = openDB(TLC_APP_LIST_DB); + if (!tlc_db) { + _ERR("Sqlite open error"); + return 0; + } + } + sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL); + + sql = sqlite3_mprintf("SELECT * FROM TLC WHERE PKGID = %Q;", pkgId); + std::vector updateTlc = selectDB(tlc_db, sql); + sqlite3_free(sql); + + sql = sqlite3_mprintf("DELETE FROM TLC WHERE PKGID = %Q;", pkgId); + if (!deleteDB(tlc_db, sql)) { + _ERR("Sqlite delete error"); + sqlite3_free(sql); + return 0; + } + sqlite3_free(sql); + + tlc_updateDB(tlc_db, updateTlc, concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR)); + return 0; } @@ -610,155 +790,257 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_REMOVED(const char *pkgId, const char *app return PKGMGR_MDPARSER_PLUGIN_UPGRADE(pkgId, appId, list); } -void cleanStep(std::string tac) +void undoStep(std::string tac) { std::string current_tac = concatPath(__DOTNET_DIR, tac.substr(0, tac.find('/'))); try { for (auto& bck : bf::recursive_directory_iterator(current_tac)) { std::string bck_path = bck.path().string(); if (bf::is_directory(bck_path) && strstr(bck_path.c_str(), ".bck") != NULL) { - if (!removeAll(bck_path)) { - _ERR("Failed to remove of %s", bck_path.c_str()); + if (!moveFile(bck_path, bck_path.substr(0, bck_path.rfind(".bck")))) { + _ERR("Failed to move %s", bck_path.c_str()); } break; } } - - bool isExist = false; - for (auto& bck : bf::recursive_directory_iterator(current_tac)) { - std::string bck_path = bck.path().string(); - if (bf::exists(bck_path) && bf::is_directory(bck_path) && strstr(bck_path.c_str(), ".bck") == NULL) { - isExist = true; - break; - } - } - if (!isExist) { - if (!removeAll(current_tac)) { - _ERR("Failed to remove of %s", current_tac.c_str()); - } - } } catch (const bf::filesystem_error& error) { _ERR("Failed to recursive directory: %s", error.what()); return; } + + ///// TLC ///// + auto convert = [](const std::string& path, const std::string& filename) { + if (filename.rfind(".bck") != std::string::npos) { + if (!moveFile(path, replaceAll(path, ".bck", ""))) { + _ERR("Failed to move %s", path.c_str()); + } + } + }; + + scanFilesInDirectory(concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR), convert, 0); } -void install_Clean() +void install_Undo() { - return; + for (auto& cd : createDirectories) { + if (!removeAll(cd)) { + _ERR("Failed to remove of %s", cd.c_str()); + } + } + + for (auto& cl : createLibraries) { + if (!removeFile(cl)) { + _ERR("Failed to remove of %s", cl.c_str()); + } + } } -void unInstall_Clean() +void unInstall_Undo() { for (auto& unp : updateTac) { - cleanStep(unp); + undoStep(unp); } } -void update_Clean() +void update_Undo() { + install_Undo(); if (!tacDB.empty()) { for (auto& np : tacDB) { - cleanStep(np); + undoStep(np); } } - unInstall_Clean(); + unInstall_Undo(); } -extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId, GList *list) +extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, GList *list) { - _DBG("[===== PKGMGR_MDPARSER_PLUGIN_CLEAN =====]"); + _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNDO =====]"); _INFO("PackageID : %s", pkgId); // Can be multiple apps in one package if (tacPluginFinished) { - _INFO("TAC plugin already finished(CLEAN)"); + _INFO("TAC plugin already finished(UNDO)"); return 0; } tacPluginFinished = true; - if (tac_db) { - dbClose(tac_db); - tac_db = NULL; - } if (!strcmp("install", status.c_str())) { - install_Clean(); + install_Undo(); } else if (!strcmp("update", status.c_str())) { - update_Clean(); + update_Undo(); } else if (!strcmp("uninstall", status.c_str())) { - unInstall_Clean(); + unInstall_Undo(); + } else if (!strcmp("restore", status.c_str())) { + update_Undo(); } + + if (tac_db) { + rollbackDB(tac_db); + tac_db = NULL; + } + + if (tlc_db) { + rollbackDB(tlc_db); + tlc_db = NULL; + } + return 0; } -void undoStep(std::string tac) +void changeOwnershipTAC(std::string current_tac) +{ + copySmackAndOwnership(__DOTNET_DIR, current_tac); + try { + for (auto& path : bf::recursive_directory_iterator(current_tac)) + copySmackAndOwnership(__DOTNET_DIR, path.path().string()); + } catch (const bf::filesystem_error& error) { + _ERR("Failed to recursive directory: %s", error.what()); + } +} + +void cleanStep(std::string tac) { std::string current_tac = concatPath(__DOTNET_DIR, tac.substr(0, tac.find('/'))); try { for (auto& bck : bf::recursive_directory_iterator(current_tac)) { std::string bck_path = bck.path().string(); if (bf::is_directory(bck_path) && strstr(bck_path.c_str(), ".bck") != NULL) { - if (!moveFile(bck_path, bck_path.substr(0, bck_path.rfind(".bck")))) { - _ERR("Failed to move %s", bck_path.c_str()); + if (!removeAll(bck_path)) { + _ERR("Failed to remove of %s", bck_path.c_str()); } break; } } + + bool isExist = false; + for (auto& bck : bf::recursive_directory_iterator(current_tac)) { + std::string bck_path = bck.path().string(); + if (exist(bck_path) && bf::is_directory(bck_path) && strstr(bck_path.c_str(), ".bck") == NULL) { + isExist = true; + break; + } + } + if (!isExist) { + if (!removeAll(current_tac)) { + _ERR("Failed to remove of %s", current_tac.c_str()); + } + } } catch (const bf::filesystem_error& error) { _ERR("Failed to recursive directory: %s", error.what()); return; } + + ///// TLC ///// + auto convert = [](const std::string& path, const std::string& filename) { + if (filename.rfind(".bck") != std::string::npos) { + if (!removeFile(path)) { + _ERR("Failed to remove of %s", path.c_str()); + } + } + }; + + scanFilesInDirectory(concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR), convert, 0); } -void install_Undo() +void install_Clean() { for (auto& cd : createDirectories) { - if (!removeAll(cd)) { - _ERR("Failed to remove of %s", cd.c_str()); - } + changeOwnershipTAC(cd); + } + + for (auto& cl : createLibraries) { + changeOwnershipTAC(cl); } } -void unInstall_Undo() +void unInstall_Clean() { for (auto& unp : updateTac) { - undoStep(unp); + cleanStep(unp); } } -void update_Undo() +void update_Clean() { - install_Undo(); + install_Clean(); if (!tacDB.empty()) { for (auto& np : tacDB) { - undoStep(np); + cleanStep(np); + changeOwnershipTAC(concatPath(__DOTNET_DIR, np.substr(0, np.find('/')))); } } - unInstall_Undo(); + unInstall_Clean(); } -extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, GList *list) +extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId, GList *list) { - _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNDO =====]"); + if (!strcmp("restore", status.c_str())) { + disableTACPackage(pkgId); + + std::string rootPath = getRootPath(std::string(pkgId)); + if (!rootPath.empty()) { + std::string binPath = concatPath(rootPath, "bin"); + removeAll(concatPath(binPath, TAC_SYMLINK_SUB_DIR)); + } + + std::string runtimesDir = concatPath(rootPath, "bin/runtimes"); + if (exist(runtimesDir)) { + char buffer[128]; + sprintf(buffer, "(tizen|linux|unix|base|any)(.\\d.\\d.\\d)?(-%s)?", ARCHITECTURE_IDENTIFIER); + std::regex pattern(buffer); + + try { + for (auto& path : bf::recursive_directory_iterator(runtimesDir)) { + std::string symPath = path.path().string(); + if (isDirectory(symPath) || !bf::is_symlink(symPath)) + continue; + std::string targetDir = symPath.substr(symPath.rfind("/runtimes/") + 10); + if (!std::regex_match(targetDir.substr(0, targetDir.find('/')), pattern)) + continue; + if (symPath.rfind(".so") == std::string::npos) + continue; + copyFile(bf::read_symlink(symPath).string(), symPath); + } + } catch (const bf::filesystem_error& error) { + _ERR("Failed to recursive directory: %s", error.what()); + } + } + + return PKGMGR_MDPARSER_PLUGIN_UNDO(pkgId, appId, list); + } + + _DBG("[===== PKGMGR_MDPARSER_PLUGIN_CLEAN =====]"); _INFO("PackageID : %s", pkgId); // Can be multiple apps in one package if (tacPluginFinished) { - _INFO("TAC plugin already finished(UNDO)"); + _INFO("TAC plugin already finished(CLEAN)"); return 0; } tacPluginFinished = true; - if (tac_db) { - dbRollback(tac_db); - tac_db = NULL; - } if (!strcmp("install", status.c_str())) { - install_Undo(); + install_Clean(); } else if (!strcmp("update", status.c_str())) { - update_Undo(); + update_Clean(); } else if (!strcmp("uninstall", status.c_str())) { - unInstall_Undo(); + unInstall_Clean(); + } + + if (tac_db) { + closeDB(tac_db); + tac_db = NULL; + copySmackAndOwnership(__DOTNET_DIR, TAC_APP_LIST_DB); + copySmackAndOwnership(__DOTNET_DIR, TAC_APP_LIST_DB + std::string("-journal")); } + + if (tlc_db) { + closeDB(tlc_db); + tlc_db = NULL; + copySmackAndOwnership(__DOTNET_DIR, TLC_APP_LIST_DB); + copySmackAndOwnership(__DOTNET_DIR, TLC_APP_LIST_DB + std::string("-journal")); + } + return 0; }