From: 최종헌/Common Platform Lab(SR)/Engineer/삼성전자 Date: Wed, 5 Aug 2020 05:53:19 +0000 (+0900) Subject: Support for TLC(Tizen Library cache) (#260) X-Git-Tag: submit/tizen/20200807.080009~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=841d1afb8f4f1541dc5e2a85adba3749ce290d34;p=platform%2Fcore%2Fdotnet%2Flauncher.git Support for TLC(Tizen Library cache) (#260) Change-Id: I4f65011e89af4b3d4fcd4b9890c2d83ea3b983f1 --- diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index c23d325..11945bf 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -205,7 +205,7 @@ SET(${DOTNETTOOL}_SOURCE_FILES ) ADD_EXECUTABLE(${DOTNETTOOL} ${${DOTNETTOOL}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${DOTNETTOOL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE}) -TARGET_LINK_LIBRARIES(${DOTNETTOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON}) +TARGET_LINK_LIBRARIES(${DOTNETTOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON} ${TAC_COMMON}) SET(PREFER_DOTNET_AOT_PLUGIN "prefer_dotnet_aot_plugin") SET(${PREFER_DOTNET_AOT_PLUGIN}_SOURCE_FILES diff --git a/NativeLauncher/inc/db_manager.h b/NativeLauncher/inc/db_manager.h index 1eb5b24..0622e57 100644 --- a/NativeLauncher/inc/db_manager.h +++ b/NativeLauncher/inc/db_manager.h @@ -27,6 +27,10 @@ NUGET TEXT,\ NAME TEXT,\ VERSION TEXT);" +#define CREATE_TLC_DB_TABLE "CREATE TABLE IF NOT EXISTS TLC(\ + ID INTEGER PRIMARY KEY AUTOINCREMENT,\ + PKGID TEXT,\ + LIBRARY TEXT);" sqlite3* dbCreate(std::string path, std::string query); sqlite3* dbOpen(std::string path); diff --git a/NativeLauncher/inc/launcher_env.h b/NativeLauncher/inc/launcher_env.h index c295f2c..c752d5c 100644 --- a/NativeLauncher/inc/launcher_env.h +++ b/NativeLauncher/inc/launcher_env.h @@ -27,9 +27,24 @@ #define TAC_SHA_256_INFO ".SHA256.info" #define TAC_APP_LIST_DB "/opt/usr/dotnet/.TAC.App.list.db" #define TAC_APP_LIST_RESTORE_DB "/opt/usr/dotnet/.TAC.App.list.restore.db" +#define TLC_APP_LIST_DB "/opt/usr/dotnet/.TLC.App.list.db" +#define TLC_APP_LIST_RESTORE_DB "/opt/usr/dotnet/.TLC.App.list.restore.db" +#define TLC_LIBRARIES_DIR "Libraries" #define TIZEN_DOTNET_NUGET "Tizen.NET" #define TIZEN_DOTNET_SDK_NUGET "Tizen.NET.Sdk" #define NET_STANDARD_LIBRARY_NUGET "NETStandard.Library" #define PLATFORM_TPA_CACHE "/usr/share/dotnet.tizen/lib/platform_tpa_cache" +#if defined (__aarch64__) +#define ARCHITECTURE_IDENTIFIER "arm64" +#elif defined (__arm__) +#define ARCHITECTURE_IDENTIFIER "armel" +#elif defined (__x86_64__) +#define ARCHITECTURE_IDENTIFIER "x64" +#elif defined (__i386__) +#define ARCHITECTURE_IDENTIFIER "x86" +#else +#error "Unknown target" +#endif + #endif //__LAUNCHER_ENV_H_ \ No newline at end of file diff --git a/NativeLauncher/inc/path_manager.h b/NativeLauncher/inc/path_manager.h index 264d4b6..3de0d7b 100644 --- a/NativeLauncher/inc/path_manager.h +++ b/NativeLauncher/inc/path_manager.h @@ -52,7 +52,7 @@ * Therefore, it has a temporary location before the AppRootPath is set up, * and has the actual location after the setAppRootPath() function is called. */ -class PathManager +class PathManager { public: /** diff --git a/NativeLauncher/inc/tac_common.h b/NativeLauncher/inc/tac_common.h index aa09464..771e4ab 100644 --- a/NativeLauncher/inc/tac_common.h +++ b/NativeLauncher/inc/tac_common.h @@ -57,4 +57,17 @@ tac_error_e enableTACPackage(const std::string& pkgId); */ std::vector depsJsonParser(const std::string& rootPath, const std::string& execName); +/** + * @brief get library info in application + * @param[in] root path + * @return std::vector filepath and sha256 value + */ +std::vector getLibrariesInfo(const std::string& rootPath); + +/** + * @brief restore database of TLC + * @return tac_error_e + */ +tac_error_e restoreTLCDB(); + #endif /* __TAC_COMMON_H__ */ diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index 3c4e758..2633024 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -228,4 +228,11 @@ void setCmdName(const std::string& name); */ std::string getFileName(const std::string& path); +/** + * @brief Generates a representation called a message digest + * @param[in] file path + * @return message digest + */ +std::string SHA256(const std::string& path); + #endif /* __UTILS_H__ */ diff --git a/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc b/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc index 71d5dd1..c0bf094 100644 --- a/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc +++ b/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc @@ -27,8 +27,6 @@ #include #include #include -#include -#include #ifdef LOG_TAG #undef LOG_TAG @@ -44,43 +42,14 @@ static const char* __DOTNET_DIR = __STR(DOTNET_DIR); std::vector nugetPackagesAssembliesSha; std::vector tacDB; std::vector createDirectories; +std::vector createLibraries; std::vector updateTac; std::string status = ""; static sqlite3 *tac_db = NULL; +static sqlite3 *tlc_db = NULL; bool tacPluginInstalled = false; bool tacPluginFinished = false; -static 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); -} - static void createSHA256Info(std::string sha256Info, std::string nugetPackage) { std::ofstream ofs(sha256Info, std::ios::app); @@ -99,7 +68,7 @@ static void createSHA256Info(std::string sha256Info, std::string nugetPackage) ofs.close(); } -static 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; @@ -127,20 +96,13 @@ static 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; } -static int copyNCreateSymlink(std::string binPath, std::string tacVersionDir, std::string nugetPackage, bool isCreateTacDir) +static int copyNCreateTacSymlink(std::string binPath, std::string tacVersionDir, std::string nugetPackage, bool isCreateTacDir) { - uid_t g_uid = 0; - const 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()); @@ -160,10 +122,6 @@ static int copyNCreateSymlink(std::string binPath, std::string tacVersionDir, st } } 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; - } if (!removeFile(concatPath(binPath, assembly))) { _ERR("Failed to remove of %s", assembly.c_str()); return -1; @@ -174,16 +132,58 @@ static int copyNCreateSymlink(std::string binPath, std::string tacVersionDir, st return 0; } +static void copyNCreateTlcSymlink(const char* pkgId, std::vector LibrariesInfo, std::string tlcDir) +{ + if (LibrariesInfo.empty()) { + _INFO("Not exist data for TLC in %s", pkgId); + 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 (!bf::exists(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); + + char *sql = sqlite3_mprintf("INSERT INTO TLC (PKGID, LIBRARY) VALUES (%Q, %Q);", pkgId, fileSha.c_str()); + if (!dbInsert(tlc_db, TLC_APP_LIST_DB, sql)) { + _ERR("Sqlite insert error"); + sqlite3_free(sql); + copyFile(concatPath(tlcDir, fileSha), library); + if (fileCopied) { + removeFile(concatPath(tlcDir, fileSha)); + } + continue; + } + sqlite3_free(sql); + } +} + static void depsJsonCheck(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()); @@ -223,8 +223,16 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app status = "install"; tac_db = dbCreate(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); if (!tac_db) { - _ERR("Sqlite create error"); - return 0; + _ERR("Sqlite create error. So restore the database."); + if (restoreTACDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return 0; + } + tac_db = dbCreate(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); + if (!tac_db) { + _ERR("Sqlite create error"); + return 0; + } } if (tacDB.empty()) { @@ -254,7 +262,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app return -1; } - if (copyNCreateSymlink(binPath, tac_version_dir, np, true) < 0) { + if (copyNCreateTacSymlink(binPath, tac_version_dir, np, true) < 0) { _ERR("Failed to create symlink"); return -1; } @@ -268,7 +276,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str()); if (!bf::is_symlink(sha256_info)) { if (compareSHA256Info(sha256_info, np)) { - if (copyNCreateSymlink(binPath, tac_version_dir, np, false) < 0) { + if (copyNCreateTacSymlink(binPath, tac_version_dir, np, false) < 0) { _ERR("Failed to create symlink"); return -1; } @@ -292,6 +300,30 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app } } } + + ///// TLC ///// + std::string tlcDir = concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR); + if (!createDir(tlcDir)) { + _ERR("Cannot create directory: %s", tlcDir.c_str()); + return 0; + } + + tlc_db = dbCreate(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error. So restore the database."); + if (restoreTLCDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return 0; + } + tlc_db = dbCreate(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error"); + return 0; + } + } + + copyNCreateTlcSymlink(pkgId, getLibrariesInfo(rootPath), tlcDir); + return 0; } @@ -332,6 +364,35 @@ static int updateTacDB(sqlite3 *sqlite) return 0; } +static void updateTlcDB(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); + } +} + extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *appId, GList *list) { _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UPGRADE =====]"); @@ -371,14 +432,23 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app status = "update"; tac_db = dbCreate(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 (restoreTACDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return 0; + } + tac_db = dbCreate(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE); + if (!tac_db) { + _ERR("Sqlite create error"); + return 0; + } } char *sql = sqlite3_mprintf("SELECT * FROM TAC WHERE PKGID = %Q;", pkgId); updateTac = dbSelect(tac_db, TAC_APP_LIST_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); @@ -386,8 +456,8 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app if (updateTacDB(tac_db) < 0) { return -1; } + skipTLC = true; _INFO("Not exist data for TAC in %s", pkgId); - return 0; } else { for (auto& np : tacDB) { std::string tac_name = np.substr(0, np.find('/')); @@ -411,7 +481,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app return -1; } - if (copyNCreateSymlink(binPath, tac_version_dir, np, true) < 0) { + if (copyNCreateTacSymlink(binPath, tac_version_dir, np, true) < 0) { _ERR("Failed to create symlink"); return -1; } @@ -443,7 +513,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str()); if (!bf::is_symlink(sha256_info)) { if (compareSHA256Info(sha256_info, np)) { - if (copyNCreateSymlink(binPath, tac_version_dir, np, false) < 0) { + if (copyNCreateTacSymlink(binPath, tac_version_dir, np, false) < 0) { _ERR("Failed to create symlink"); return -1; } @@ -503,6 +573,45 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app return -1; } } + + ///// TLC ///// + std::string tlcDir = concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR); + if (!createDir(tlcDir)) { + _ERR("Cannot create directory: %s", tlcDir.c_str()); + return 0; + } + + tlc_db = dbCreate(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error. So restore the database."); + if (restoreTLCDB() != TAC_ERROR_NONE) { + _ERR("Sqlite create error"); + return 0; + } + tlc_db = dbCreate(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + _ERR("Sqlite create error"); + return 0; + } + } + + sql = sqlite3_mprintf("SELECT * FROM TLC WHERE PKGID = %Q;", pkgId); + std::vector updateTlc = dbSelect(tlc_db, TLC_APP_LIST_DB, sql); + sqlite3_free(sql); + + sql = sqlite3_mprintf("DELETE FROM TLC WHERE PKGID = %Q;", pkgId); + dbDelete(tlc_db, TLC_APP_LIST_DB, sql); + sqlite3_free(sql); + + std::vector librariesInfo = getLibrariesInfo(rootPath); + if (skipTLC) { + librariesInfo.clear(); + } + + copyNCreateTlcSymlink(pkgId, librariesInfo, tlcDir); + + updateTlcDB(tlc_db, updateTlc, tlcDir); + return 0; } @@ -521,8 +630,16 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *a status = "uninstall"; tac_db = dbOpen(TAC_APP_LIST_DB); if (!tac_db) { - _ERR("Sqlite open error"); - return 0; + _ERR("Sqlite open error. So restore the database."); + if (restoreTACDB() != TAC_ERROR_NONE) { + _ERR("Sqlite open error"); + return 0; + } + tac_db = dbOpen(TAC_APP_LIST_DB); + if (!tac_db) { + _ERR("Sqlite open error"); + return 0; + } } char *sql = sqlite3_mprintf("SELECT * FROM TAC WHERE PKGID = %Q;", pkgId); @@ -536,6 +653,32 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *a if (updateTacDB(tac_db) < 0) { return -1; } + + ///// TLC ///// + tlc_db = dbOpen(TLC_APP_LIST_DB); + if (!tlc_db) { + _ERR("Sqlite open error. So restore the database."); + if (restoreTLCDB() != TAC_ERROR_NONE) { + _ERR("Sqlite open error"); + return 0; + } + tlc_db = dbOpen(TLC_APP_LIST_DB); + if (!tlc_db) { + _ERR("Sqlite open error"); + return 0; + } + } + + sql = sqlite3_mprintf("SELECT * FROM TLC WHERE PKGID = %Q;", pkgId); + std::vector updateTlc = dbSelect(tlc_db, TLC_APP_LIST_DB, sql); + sqlite3_free(sql); + + sql = sqlite3_mprintf("DELETE FROM TLC WHERE PKGID = %Q;", pkgId); + dbDelete(tlc_db, TLC_APP_LIST_DB, sql); + sqlite3_free(sql); + + updateTlcDB(tlc_db, updateTlc, concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR)); + return 0; } @@ -580,6 +723,17 @@ void cleanStep(std::string tac) _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_Clean() @@ -616,10 +770,6 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId } tacPluginFinished = true; - if (tac_db) { - dbClose(tac_db); - tac_db = NULL; - } if (!strcmp("install", status.c_str())) { install_Clean(); } else if (!strcmp("update", status.c_str())) { @@ -627,6 +777,17 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId } else if (!strcmp("uninstall", status.c_str())) { unInstall_Clean(); } + + if (tac_db) { + dbClose(tac_db); + tac_db = NULL; + } + + if (tlc_db) { + dbClose(tlc_db); + tlc_db = NULL; + } + return 0; } @@ -647,6 +808,17 @@ void undoStep(std::string tac) _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_Undo() @@ -656,6 +828,12 @@ void install_Undo() _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_Undo() @@ -688,10 +866,6 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, } tacPluginFinished = true; - if (tac_db) { - dbRollback(tac_db); - tac_db = NULL; - } if (!strcmp("install", status.c_str())) { install_Undo(); } else if (!strcmp("update", status.c_str())) { @@ -699,5 +873,16 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, } else if (!strcmp("uninstall", status.c_str())) { unInstall_Undo(); } + + if (tac_db) { + dbRollback(tac_db); + tac_db = NULL; + } + + if (tlc_db) { + dbRollback(tlc_db); + tlc_db = NULL; + } + return 0; -} +} \ No newline at end of file diff --git a/NativeLauncher/tool/dotnettool.cc b/NativeLauncher/tool/dotnettool.cc index 57f4a7a..7ff16df 100644 --- a/NativeLauncher/tool/dotnettool.cc +++ b/NativeLauncher/tool/dotnettool.cc @@ -232,6 +232,10 @@ int main(int argc, char* argv[]) if (ret != TAC_ERROR_NONE) { fprintf(stderr, "Failed to restore TAC db\n"); } + ret = restoreTLCDB(); + if (ret != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to restore TLC db\n"); + } } //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ... else if (cmd == "--tac-enable-pkg") { diff --git a/NativeLauncher/tool/tac_common.cc b/NativeLauncher/tool/tac_common.cc index 75c636b..2714b26 100644 --- a/NativeLauncher/tool/tac_common.cc +++ b/NativeLauncher/tool/tac_common.cc @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -23,7 +24,6 @@ #include "utils.h" #include "tac_common.h" #include "db_manager.h" -#include "path_manager.h" #ifdef LOG_TAG #undef LOG_TAG @@ -37,7 +37,9 @@ static const char* __DOTNET_DIR = __STR(DOTNET_DIR); #undef __XSTR static sqlite3 *tac_db = NULL; +static sqlite3 *tlc_db = NULL; std::vector restore_nuget; +std::vector restore_library; static void cleanupDirectory() { @@ -47,8 +49,9 @@ static void cleanupDirectory() bool isExist = false; std::string nugetPath = nuget.path().string(); for (auto& restore : restore_nuget) { - if (!bf::is_directory(nugetPath)) { + if (!bf::is_directory(nugetPath) || nugetPath.find(TLC_LIBRARIES_DIR) != std::string::npos) { isExist = true; + break; } if (!strcmp(nugetPath.c_str(), restore.c_str()) || !strcmp(nugetPath.c_str(), restore.substr(0, restore.rfind('/')).c_str())) { @@ -74,7 +77,7 @@ static void cleanupDirectory() } // callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" -static int restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData) +static int restoreTACDBCb(pkgmgrinfo_appinfo_h handle, void *userData) { char *pkgId = NULL; char *root = NULL; @@ -95,7 +98,7 @@ static int restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData) fprintf(stderr, "Failed to get root path\n"); return -1; } - rootPath = root; + rootPath = std::string(root); ret = pkgmgrinfo_appinfo_get_exec(handle, &exec); if (ret != PMINFO_R_OK) { @@ -164,7 +167,7 @@ tac_error_e restoreTACDB() return TAC_ERROR_UNKNOWN; } - ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, restoreDBCb, NULL); + ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, restoreTACDBCb, NULL); if (ret != PMINFO_R_OK) { fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n"); pkgmgrinfo_appinfo_metadata_filter_destroy(handle); @@ -422,3 +425,175 @@ std::vector depsJsonParser(const std::string& rootPath, const std:: } return parserData; } + +std::vector getLibrariesInfo(const std::string& rootPath) +{ + std::vector LibrariesInfo; + std::vector unusedDir; + std::string runtimesDir = concatPath(rootPath, "bin/runtimes"); + if (!bf::exists(runtimesDir)) + return LibrariesInfo; + + 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 filepath = path.path().string(); + std::size_t pos = filepath.rfind("/runtimes/"); + if (pos != std::string::npos) { + std::string targetDir = filepath.substr(pos + 10); + if (!std::regex_match(targetDir.substr(0, targetDir.find('/')), pattern)) { + if (isDirectory(filepath)) + unusedDir.push_back(filepath); + continue; + } + } + if (filepath.rfind(".so") == std::string::npos) + continue; + + std::string buffer = SHA256(filepath); + LibrariesInfo.push_back(filepath + ":" + buffer); + _INFO("Library : [%s] / SHA256 : [%s]", filepath.substr(filepath.rfind('/') + 1).c_str(), buffer.c_str()); + } + } catch (const bf::filesystem_error& error) { + _ERR("Failed to recursive directory: %s", error.what()); + } + + for (auto& path : unusedDir) { + if (!removeAll(path)) { + _ERR("Failed to remove of %s", path.c_str()); + } + } + unusedDir.clear(); + + return LibrariesInfo; +} + +// callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" +static int restoreTLCDBCb(pkgmgrinfo_appinfo_h handle, void *userData) +{ + char *pkgId = NULL; + char *root = NULL; + std::string rootPath; + + int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId); + if (ret != PMINFO_R_OK) { + fprintf(stderr, "Failed to get pkgid\n"); + return -1; + } + + ret = pkgmgrinfo_appinfo_get_root_path(handle, &root); + if (ret != PMINFO_R_OK) { + fprintf(stderr, "Failed to get root path\n"); + return -1; + } + rootPath = std::string(root); + + for (auto& librarySha : getLibrariesInfo(rootPath)) { + std::string library = librarySha.substr(0, librarySha.find(':')); + if (bf::exists(library)) { + std::string fileSha = library.substr(library.rfind('/') + 1) + ".." + librarySha.substr(librarySha.find(':') + 1); + char *sql = sqlite3_mprintf("INSERT INTO TLC (PKGID, LIBRARY) VALUES (%Q, %Q);", pkgId, fileSha.c_str()); + dbInsert(tlc_db, TLC_APP_LIST_RESTORE_DB, sql); + restore_library.push_back(fileSha); + sqlite3_free(sql); + } + } + return 0; +} + +tac_error_e restoreTLCDB() +{ + if (!removeFile(TLC_APP_LIST_RESTORE_DB)) { + fprintf(stderr, "Failed to remove of %s\n", TLC_APP_LIST_RESTORE_DB); + return TAC_ERROR_UNKNOWN; + } + + std::string dbRestoreJournal = TLC_APP_LIST_RESTORE_DB + std::string("-journal"); + if (!removeFile(dbRestoreJournal)) { + fprintf(stderr, "Failed to remove of %s\n", dbRestoreJournal.c_str()); + return TAC_ERROR_UNKNOWN; + } + + tlc_db = dbCreate(TLC_APP_LIST_RESTORE_DB, CREATE_TLC_DB_TABLE); + if (!tlc_db) { + fprintf(stderr, "Sqlite create error\n"); + return TAC_ERROR_UNKNOWN; + } + + pkgmgrinfo_appinfo_metadata_filter_h handle; + int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle); + if (ret != PMINFO_R_OK) { + return TAC_ERROR_UNKNOWN; + } + + ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); + return TAC_ERROR_UNKNOWN; + } + + ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, restoreTLCDBCb, NULL); + if (ret != PMINFO_R_OK) { + fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n"); + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); + return TAC_ERROR_UNKNOWN; + } + fprintf(stdout, "Success pkgmgrinfo_appinfo_metadata_filter_foreach\n"); + + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); + + if (tlc_db) { + dbClose(tlc_db); + tlc_db = NULL; + } + + const uid_t g_uid = 301; // app_fw + const gid_t g_gid = 301; // app_fw + + if (!copyFile(TLC_APP_LIST_RESTORE_DB, TLC_APP_LIST_DB)) { + fprintf(stderr, "Failed to copy of %s\n", TLC_APP_LIST_DB); + return TAC_ERROR_UNKNOWN; + } + if (!removeFile(TLC_APP_LIST_RESTORE_DB)) { + fprintf(stderr, "Failed to remove of %s\n", TLC_APP_LIST_RESTORE_DB); + return TAC_ERROR_UNKNOWN; + } + if (chown(TLC_APP_LIST_DB, g_uid, g_gid) == -1) { + fprintf(stderr, "Failed to change owner and group name\n"); + } + + std::string dbJournal = TLC_APP_LIST_DB + std::string("-journal"); + if (!copyFile(dbRestoreJournal, dbJournal)) { + fprintf(stderr, "Failed to copy of %s\n", dbJournal.c_str()); + return TAC_ERROR_UNKNOWN; + } + if (!removeFile(dbRestoreJournal)) { + fprintf(stderr, "Failed to remove of %s\n", dbRestoreJournal.c_str()); + return TAC_ERROR_UNKNOWN; + } + if (chown(dbJournal.c_str(), g_uid, g_gid) == -1) { + fprintf(stderr, "Failed to change owner and group name\n"); + } + + auto convert = [](const std::string& path, const std::string& filename) { + bool isExist = false; + for (auto& library : restore_library) { + if (!strcmp(filename.c_str(), library.c_str())) { + isExist = true; + break; + } + } + if (!isExist) { + if (!removeFile(path)) { + _ERR("Failed to remove of %s", path.c_str()); + } + } + }; + + scanFilesInDirectory(concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR), convert, 0); + + return TAC_ERROR_NONE; +} diff --git a/NativeLauncher/util/db_manager.cc b/NativeLauncher/util/db_manager.cc index d42c066..0e05814 100644 --- a/NativeLauncher/util/db_manager.cc +++ b/NativeLauncher/util/db_manager.cc @@ -14,11 +14,10 @@ * limitations under the License. */ -#include - -#include "db_manager.h" #include "log.h" -#include "tac_common.h" +#include "db_manager.h" + +#include #ifdef LOG_TAG #undef LOG_TAG @@ -46,11 +45,7 @@ sqlite3* dbCreate(std::string path, std::string query) int ret = sqlite3_open(path.c_str(), &sqlite); if (ret != SQLITE_OK) { _INFO("DB file is corrupted, start to recover corrupted db"); - if (restoreTACDB() != TAC_ERROR_NONE) { - _ERR("Sqlite error : [%d, %s]", ret, path.c_str()); - return NULL; - } - return dbCreate(path, query); + return sqlite; } ret = sqlite3_exec(sqlite, "PRAGMA journal_mode = PERSIST", NULL, NULL, NULL); if (ret != SQLITE_OK) { @@ -69,13 +64,9 @@ sqlite3* dbCreate(std::string path, std::string query) ret = sqlite3_exec(sqlite, "PRAGMA integrity_check", dbIntegrityCheckCb, &is_db_corrupted, NULL); if (ret == SQLITE_CORRUPT || is_db_corrupted) { _INFO("DB file is corrupted, start to recover corrupted db"); - if (restoreTACDB() != TAC_ERROR_NONE) { - _ERR("Sqlite error : [%d, %s]", ret, path.c_str()); - sqlite3_close(sqlite); - sqlite = NULL; - return sqlite; - } - return dbCreate(path, query); + sqlite3_close(sqlite); + sqlite = NULL; + return sqlite; } return sqlite; } @@ -87,22 +78,14 @@ sqlite3* dbOpen(std::string path) int ret = sqlite3_open(path.c_str(), &sqlite); if (ret != SQLITE_OK) { _INFO("DB file is corrupted, start to recover corrupted db"); - if (restoreTACDB() != TAC_ERROR_NONE) { - _ERR("Sqlite error : [%d, %s]", ret, path.c_str()); - return NULL; - } - return dbOpen(path); + return sqlite; } ret = sqlite3_exec(sqlite, "PRAGMA integrity_check", dbIntegrityCheckCb, &is_db_corrupted, NULL); if (ret == SQLITE_CORRUPT || is_db_corrupted) { _INFO("DB file is corrupted, start to recover corrupted db"); - if (restoreTACDB() != TAC_ERROR_NONE) { - _ERR("Sqlite error : [%d, %s]", ret, path.c_str()); - sqlite3_close(sqlite); - sqlite = NULL; - return sqlite; - } - return dbOpen(path); + sqlite3_close(sqlite); + sqlite = NULL; + return sqlite; } return sqlite; } diff --git a/NativeLauncher/util/path_manager.cc b/NativeLauncher/util/path_manager.cc index 072db9e..04efda1 100644 --- a/NativeLauncher/util/path_manager.cc +++ b/NativeLauncher/util/path_manager.cc @@ -36,26 +36,9 @@ static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version"; static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR); static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR); static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR); - #undef __STR #undef __XSTR -#if defined (__aarch64__) -#define ARCHITECTURE_IDENTIFIER "arm64" - -#elif defined (__arm__) -#define ARCHITECTURE_IDENTIFIER "armel" - -#elif defined (__x86_64__) -#define ARCHITECTURE_IDENTIFIER "x64" - -#elif defined (__i386__) -#define ARCHITECTURE_IDENTIFIER "x86" - -#else -#error "Unknown target" -#endif - // The sequence of RID_FALLBACK graphs must be: // 1. Tizen + Version + Architecture // 2. Tizen + Version @@ -79,7 +62,7 @@ static std::string getExtraNativeLibDirs(const std::string& appRoot) std::vector RID_FALLBACK_OS = {"tizen", "linux", "unix"}; for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) { - RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" + ARCHITECTURE_IDENTIFIER)); + RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" + ARCHITECTURE_IDENTIFIER)); RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i])); } RID_FALLBACK_GRAPH.push_back("any"); diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index ac43df8..2864a6f 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include "log.h" #include "utils.h" @@ -651,3 +653,39 @@ std::string getFileName(const std::string& path) size_t index = ret.find_last_of(PATH_SEPARATOR); return index == std::string::npos ? ret : ret.substr(index + 1); } + +std::string SHA256(const std::string& path) +{ + std::string output = ""; + FILE *file = fopen(path.c_str(), "rb"); + if (!file) { + return output; + } + + 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 output; + } + + while ((bytesRead = fread(buffer, 1, bufSize, file))) { + SHA256_Update(&sha256, buffer, bytesRead); + } + SHA256_Final(hash, &sha256); + + std::stringstream ss; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i]; + } + output = ss.str(); + + fclose(file); + free(buffer); + + return output; +} \ No newline at end of file