X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=NativeLauncher%2Finstaller-plugin%2Fprefer_nuget_cache_plugin.cc;h=30518b12f5a51a882aea4ae6cd0d5c0c064f71cf;hb=ebad648f17029c908403b945f4c04631a25e4312;hp=8d15f6beb0a2a246fe84fd99de65a730e2661a72;hpb=0009fc7f35998596dbb0e631d0075f19245bdbe6;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 8d15f6b..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 @@ -39,166 +36,170 @@ #define __XSTR(x) #x #define __STR(x) __XSTR(x) -static const char* __TAC_DIR = __STR(TAC_DIR); +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) +static void createSHA256Info(std::string sha256Info, std::string nugetPackage) { - 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; + std::ofstream ofs(sha256Info, std::ios::app); + int assembly_count = 0; + 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); + std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1); + if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) { + ofs << assembly << ":" << sha << std::endl; + assembly_count++; } - return true; } - return false; + ofs << assembly_count << std::endl; + ofs.close(); } -bool appTypeCheck(std::string pkgId) +static bool compareSHA256Info(std::string sha256Info, std::string nugetPackage) { - 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; + int compare_count = 0; + int assembly_count = 0; + std::string sha256_count = "0"; + 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); + std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1); + if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) { + assembly_count++; + std::ifstream ifs(sha256Info); + std::string get_str; + if (ifs.is_open()) { + while (getline(ifs, get_str)) { + if (!strcmp(get_str.c_str(), (assembly + ":" + sha).c_str())) { + compare_count++; + } + sha256_count = get_str; + } + ifs.close(); + } } - 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]); + 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 true; } - outputBuffer[64] = 0; - - fclose(file); - free(buffer); + return false; } -int copyNCreateSymlink(std::string tac_version_dir, std::string np, bool is_create_tac_dir) +static bool copyAssemblyCreateSymlink(std::string binPath, std::string tacDir, std::string nugetPackage, bool isCreateTacDir) { - uid_t uid = 0; - if (pkgmgr_installer_info_get_target_uid(&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(), np.c_str())) { - if (bf::exists(concatPath(binPath, assembly))) { - if (is_create_tac_dir) { + if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) { + if (exist(concatPath(binPath, assembly))) { + if (isCreateTacDir) { 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(tac_version_dir, assembly), concatPath(tac_dir, assembly)); - if (lchown(concatPath(tac_dir, assembly).c_str(), uid, 0)) { - _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())) { - std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':')); - std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1); - tacDB.push_back(nugetPackage); - char buffer[65] = {0}; - SHA256(concatPath(binPath, assemblyName), buffer); - nugetPackagesAssembliesSha.push_back(nugetPackage + ":" + assemblyName + ":" + buffer); - _INFO("Assembly : [%s] / SHA256 : [%s]", assemblyName.c_str(), buffer); +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); + 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.c_str()); } std::sort(tacDB.begin(), tacDB.end()); tacDB.erase(unique(tacDB.begin(), tacDB.end()), tacDB.end()); @@ -209,33 +210,58 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app _DBG("[===== PKGMGR_MDPARSER_PLUGIN_INSTALL =====]"); _INFO("PackageID : %s", pkgId); - if (!appTypeCheck(std::string(pkgId))) { - _INFO("App type is not dotnet"); + // Can be multiple apps in one package + if (tacPluginInstalled) { + _INFO("TAC plugin already installed"); return 0; } - if (getExecName(std::string(pkgId), execName) < 0) { + tacPluginInstalled = true; + + 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"); } - if (metadataCheck(list)) { - depsJsonCheck(); + std::string binPath = concatPath(rootPath, "bin"); + std::string metaValue = getMetadataValue(std::string(pkgId), TAC_METADATA_KEY); + if (metaValue.empty()) { + return 0; + } + if (metaValue == METADATA_VALUE) { + checkDepsJson(rootPath, binPath, execName); } status = "install"; - tac_db = dbCreate(TAC_APP_LIST_DB); - if (!tac_db) { - _ERR("Sqlite create error"); + if (tacDB.empty()) { return 0; } - if (tacDB.empty()) { - _INFO("Not exist .deps.json file"); + 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('/')); @@ -243,115 +269,168 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app _INFO("TAC name : %s", tac_name.c_str()); _INFO("TAC version : %s", tac_version.c_str()); - std::string tac_version_dir = concatPath(__TAC_DIR, np); + 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); - std::ofstream ofs(sha256_info, std::ios::app); - int assembly_count = 0; - 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); - std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1); - if (!strcmp(nuget_package.c_str(), np.c_str())) { - ofs << assembly << ":" << sha << std::endl; - assembly_count++; - } + 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; } - ofs << assembly_count << std::endl; - ofs.close(); - 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()); + if (!insertDB(tac_db, sql)) { + _ERR("Sqlite insert error"); + sqlite3_free(sql); + status = "restore"; return -1; } - std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ - "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');"; - dbInsert(tac_db, TAC_APP_LIST_DB, sql); + sqlite3_free(sql); } else { _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str()); - int compare_count = 0; - int assembly_count = 0; - std::string sha256_count = "0"; - 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); - std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1); - if (!strcmp(nuget_package.c_str(), np.c_str())) { - assembly_count++; - std::ifstream ifs(sha256_info); - std::string get_str; - if (ifs.is_open()) { - while (getline(ifs, get_str)) { - if (!strcmp(get_str.c_str(), (assembly + ":" + sha).c_str())) { - compare_count++; - } - sha256_count = get_str; - } - ifs.close(); + if (!bf::is_symlink(sha256_info)) { + if (compareSHA256Info(sha256_info, np)) { + 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()); + 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; } - } - 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", np.c_str()); - if (copyNCreateSymlink(tac_version_dir, np, false) < 0) { - _ERR("Failed to create symlink"); - return -1; - } - std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ - "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');"; - dbInsert(tac_db, TAC_APP_LIST_DB, sql); } else { - _INFO("Different nuget : %s", np.c_str()); + _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; - std::string sql = "SELECT COUNT(NUGET) FROM TAC WHERE NUGET = '" + unp + "';"; - int ret = sqlite3_exec(sqlite, sql.c_str(), sqliteCb, &count, NULL); + char *sql = sqlite3_mprintf("SELECT COUNT(NUGET) FROM TAC WHERE NUGET = %Q;", unp.c_str()); + int ret = sqlite3_exec(sqlite, sql, sqliteCb, &count, NULL); if (ret != SQLITE_OK) { _ERR("Sqlite select error"); - return -1; + sqlite3_free(sql); + continue; } if (count == 0) { - std::string tac_version_dir_prev = concatPath(__TAC_DIR, unp); + std::string tac_version_dir_prev = concatPath(__DOTNET_DIR, unp); std::string tac_version_dir_backup = tac_version_dir_prev + ".bck"; 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()); - return -1; + sqlite3_free(sql); + continue; } if (!removeAll(tac_version_dir_prev)) { _ERR("Failed to remove of %s", tac_version_dir_prev.c_str()); - return -1; + sqlite3_free(sql); + 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) @@ -359,42 +438,77 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UPGRADE =====]"); _INFO("PackageID : %s", pkgId); - if (!appTypeCheck(std::string(pkgId))) { - _INFO("App type is not dotnet"); + // Can be multiple apps in one package + if (tacPluginInstalled) { + _INFO("TAC plugin already upgraded"); return 0; } - if (getExecName(std::string(pkgId), execName) < 0) { + tacPluginInstalled = true; + + 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); + 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 = selectDB(tac_db, sql); + sqlite3_free(sql); + bool skipTLC = false; if (tacDB.empty()) { - std::string sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';"; - dbDelete(tac_db, TAC_APP_LIST_DB, sql); - if (updateTacDB(tac_db) < 0) { + sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q;", pkgId); + if (!deleteDB(tac_db, sql)) { + _ERR("Sqlite delete error"); + sqlite3_free(sql); return -1; } + sqlite3_free(sql); + + tac_updateDB(tac_db); + + skipTLC = true; } else { - std::string sql = "SELECT * FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';"; - updateTac = dbSelect(tac_db, TAC_APP_LIST_DB, sql); + 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('/')); @@ -402,105 +516,121 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app _INFO("TAC name : %s", tac_name.c_str()); _INFO("TAC version : %s", tac_version.c_str()); - std::string tac_version_dir = concatPath(__TAC_DIR, np); + 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); - std::ofstream ofs(sha256_info, std::ios::app); - int assembly_count = 0; - 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); - std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1); - if (!strcmp(nuget_package.c_str(), np.c_str())) { - ofs << assembly << ":" << sha << std::endl; - assembly_count++; - } + 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; } - ofs << assembly_count << std::endl; - ofs.close(); - 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; } int count = -1; - sql = "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';"; - int ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL); + sql = sqlite3_mprintf( + "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = %Q AND NAME = %Q;", pkgId, tac_name.c_str()); + int ret = sqlite3_exec(tac_db, sql, sqliteCb, &count, NULL); if (ret != SQLITE_OK) { _ERR("Sqlite select error"); + sqlite3_free(sql); + status = "restore"; return -1; } + sqlite3_free(sql); if (count == 1) { - sql = "UPDATE TAC SET NAME = '" + tac_name + "', VERSION = '" + tac_version + "', NUGET = '" + np + "' WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';"; - dbUpdate(tac_db, TAC_APP_LIST_DB, sql); + 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()); + if (!updateDB(tac_db, sql)) { + _ERR("Sqlite update error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } + sqlite3_free(sql); } else if (count == 0) { - sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ - "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');"; - dbInsert(tac_db, TAC_APP_LIST_DB, sql); + 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()); + 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()); - int compare_count = 0; - int assembly_count = 0; - std::string sha256_count = "0"; - 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); - std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1); - if (!strcmp(nuget_package.c_str(), np.c_str())) { - assembly_count++; - std::ifstream ifs(sha256_info); - std::string get_str; - if (ifs.is_open()) { - while (getline(ifs, get_str)) { - if (!strcmp(get_str.c_str(), (assembly + ":" + sha).c_str())) { - compare_count++; - } - sha256_count = get_str; - } - ifs.close(); + if (!bf::is_symlink(sha256_info)) { + if (compareSHA256Info(sha256_info, np)) { + if (copyAssemblyCreateSymlink(binPath, tac_dir, np, false)) { + _ERR("Failed to create symlink"); + status = "restore"; + return -1; } - } - } - - 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", np.c_str()); - if (copyNCreateSymlink(tac_version_dir, np, false) < 0) { - _ERR("Failed to create symlink"); - return -1; - } - int count = -1; - std::string sql = "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';"; - int ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL); - if (ret != SQLITE_OK) { - _ERR("Sqlite select error"); - return -1; - } - if (count == 1) { - sql = "UPDATE TAC SET NAME = '" + tac_name + "', VERSION = '" + tac_version + "', NUGET = '" + np + "' WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';"; - dbUpdate(tac_db, TAC_APP_LIST_DB, sql); - } else if (count == 0) { - sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ - "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');"; - dbInsert(tac_db, TAC_APP_LIST_DB, sql); + int count = -1; + char *sql = sqlite3_mprintf( + "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = %Q AND NAME = %Q;", pkgId, tac_name.c_str()); + int ret = sqlite3_exec(tac_db, sql, sqliteCb, &count, NULL); + if (ret != SQLITE_OK) { + _ERR("Sqlite select error"); + sqlite3_free(sql); + status = "restore"; + return -1; + } + sqlite3_free(sql); + if (count == 1) { + 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()); + 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()); + 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 { - _INFO("Different nuget : %s", np.c_str()); - } - } - if (!bf::exists(sha256_info)) { - if(!removeAll(tac_version_dir)) { - _ERR("Failed to remove of %s", tac_version_dir.c_str()); + _ERR("Failed to create sha256_info. Symbolic link is detected"); + status = "restore"; + return -1; } } } @@ -513,14 +643,63 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app } } if (!isExits) { - std::string sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "' AND NUGET = '" + unp + "';"; - dbDelete(tac_db, TAC_APP_LIST_DB, sql); + char *sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q AND NUGET = %Q;", pkgId, unp.c_str()); + 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; } @@ -529,22 +708,75 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *a _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNINSTALL =====]"); _INFO("PackageID : %s", pkgId); + // Can be multiple apps in one package + if (tacPluginInstalled) { + _INFO("TAC plugin already uninstalled"); + return 0; + } + 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); - std::string sql = "SELECT * FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';"; - updateTac = dbSelect(tac_db, TAC_APP_LIST_DB, sql); + char *sql = sqlite3_mprintf("SELECT * FROM TAC WHERE PKGID = %Q;", pkgId); + updateTac = selectDB(tac_db, sql); + sqlite3_free(sql); - sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';"; - dbDelete(tac_db, TAC_APP_LIST_DB, sql); + sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q;", pkgId); - 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; } @@ -558,141 +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(__TAC_DIR, tac.substr(0, tac.find('/'))); + 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); - if (tac_db) { - dbClose(tac_db); - tac_db = NULL; + // Can be multiple apps in one package + if (tacPluginFinished) { + _INFO("TAC plugin already finished(UNDO)"); + return 0; } + tacPluginFinished = true; + 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) { - std::string current_tac = concatPath(__TAC_DIR, tac.substr(0, tac.find('/'))); + 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); - if (tac_db) { - dbRollback(tac_db); - tac_db = NULL; + // Can be multiple apps in one package + if (tacPluginFinished) { + _INFO("TAC plugin already finished(CLEAN)"); + return 0; } + tacPluginFinished = true; + 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; }