Support for TLC(Tizen Library cache) (#260)
author최종헌/Common Platform Lab(SR)/Engineer/삼성전자 <j-h.choi@samsung.com>
Wed, 5 Aug 2020 05:53:19 +0000 (14:53 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Wed, 5 Aug 2020 05:53:19 +0000 (14:53 +0900)
Change-Id: I4f65011e89af4b3d4fcd4b9890c2d83ea3b983f1

12 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/inc/db_manager.h
NativeLauncher/inc/launcher_env.h
NativeLauncher/inc/path_manager.h
NativeLauncher/inc/tac_common.h
NativeLauncher/inc/utils.h
NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc
NativeLauncher/tool/dotnettool.cc
NativeLauncher/tool/tac_common.cc
NativeLauncher/util/db_manager.cc
NativeLauncher/util/path_manager.cc
NativeLauncher/util/utils.cc

index c23d325..11945bf 100644 (file)
@@ -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
index 1eb5b24..0622e57 100644 (file)
                        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);
index c295f2c..c752d5c 100644 (file)
 #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
index 264d4b6..3de0d7b 100644 (file)
@@ -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:
        /**
index aa09464..771e4ab 100644 (file)
@@ -57,4 +57,17 @@ tac_error_e enableTACPackage(const std::string& pkgId);
  */
 std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName);
 
+/**
+ * @brief get library info in application
+ * @param[in] root path
+ * @return std::vector<std::string> filepath and sha256 value
+ */
+std::vector<std::string> getLibrariesInfo(const std::string& rootPath);
+
+/**
+ * @brief restore database of TLC
+ * @return tac_error_e
+ */
+tac_error_e restoreTLCDB();
+
 #endif /* __TAC_COMMON_H__ */
index 3c4e758..2633024 100644 (file)
@@ -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__ */
index 71d5dd1..c0bf094 100644 (file)
@@ -27,8 +27,6 @@
 #include <glib.h>
 #include <json/json.h>
 #include <pkgmgr-info.h>
-#include <pkgmgr_installer_info.h>
-#include <openssl/sha.h>
 
 #ifdef  LOG_TAG
 #undef  LOG_TAG
@@ -44,43 +42,14 @@ static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
 std::vector<std::string> nugetPackagesAssembliesSha;
 std::vector<std::string> tacDB;
 std::vector<std::string> createDirectories;
+std::vector<std::string> createLibraries;
 std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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
index 57f4a7a..7ff16df 100644 (file)
@@ -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") {
index 75c636b..2714b26 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <fstream>
+#include <regex>
 #include <json/json.h>
 #include <pkgmgr-info.h>
 #include <pkgmgr_installer_info.h>
@@ -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<std::string> restore_nuget;
+std::vector<std::string> 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<std::string> depsJsonParser(const std::string& rootPath, const std::
        }
        return parserData;
 }
+
+std::vector<std::string> getLibrariesInfo(const std::string& rootPath)
+{
+       std::vector<std::string> LibrariesInfo;
+       std::vector<std::string> 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;
+}
index d42c066..0e05814 100644 (file)
  * limitations under the License.
  */
 
-#include <algorithm>
-
-#include "db_manager.h"
 #include "log.h"
-#include "tac_common.h"
+#include "db_manager.h"
+
+#include <algorithm>
 
 #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;
 }
index 072db9e..04efda1 100644 (file)
@@ -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<std::string> 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");
index ac43df8..2864a6f 100644 (file)
@@ -24,6 +24,7 @@
 #include <pkgmgr_installer_info.h>
 #include <sys/smack.h>
 #include <sys/prctl.h>
+#include <openssl/sha.h>
 
 #include <cstdlib>
 #include <cstring>
@@ -34,6 +35,7 @@
 #include <fstream>
 #include <sstream>
 #include <map>
+#include <iomanip>
 
 #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