From 4cbb844e86fac0d3a6edcc75f3c4bd02567d273f Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=B5=9C=EC=A2=85=ED=97=8C/Common=20Platform=20Lab=28SR=29?= =?utf8?q?/Engineer/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Tue, 16 Jul 2019 14:38:38 +0900 Subject: [PATCH] Modify the problem that the original assembly is deleted (#80) --- NativeLauncher/CMakeLists.txt | 16 +- NativeLauncher/inc/tac_common.h | 72 ++++ NativeLauncher/inc/utils.h | 36 +- .../installer-plugin/prefer_dotnet_aot_plugin.cc | 14 +- .../installer-plugin/prefer_nuget_cache_plugin.cc | 390 +++++++----------- NativeLauncher/tool/dotnettool.cc | 246 ++++++++++++ NativeLauncher/tool/ni_common.cc | 54 ++- NativeLauncher/tool/nitool.cc | 26 +- NativeLauncher/tool/tac_common.cc | 444 +++++++++++++++++++++ NativeLauncher/tool/tactool.cc | 268 ------------- NativeLauncher/util/utils.cc | 118 +++++- packaging/dotnet-launcher.spec | 5 +- 12 files changed, 1107 insertions(+), 582 deletions(-) create mode 100644 NativeLauncher/inc/tac_common.h create mode 100644 NativeLauncher/tool/dotnettool.cc create mode 100644 NativeLauncher/tool/tac_common.cc delete mode 100644 NativeLauncher/tool/tactool.cc diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index b5c2a38..fbf61f5 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -114,6 +114,7 @@ SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} SET(NI_COMMON "ni_common") SET(${NI_COMMON}_SOURCE_FILES tool/ni_common.cc + tool/tac_common.cc ) ADD_LIBRARY(${NI_COMMON} SHARED ${${NI_COMMON}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${NI_COMMON} PROPERTIES COMPILE_FLAGS "-fPIC") @@ -135,13 +136,13 @@ ADD_EXECUTABLE(${TPATOOL} ${${TPATOOL}_SOURCE_FILES}) SET_TARGET_PROPERTIES(${TPATOOL} PROPERTIES COMPILE_FLAGS "-fPIE") TARGET_LINK_LIBRARIES(${TPATOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL}) -SET(TACTOOL "tactool") -SET(${TACTOOL}_SOURCE_FILES - tool/tactool.cc +SET(DOTNETTOOL "dotnettool") +SET(${DOTNETTOOL}_SOURCE_FILES + tool/dotnettool.cc ) -ADD_EXECUTABLE(${TACTOOL} ${${TACTOOL}_SOURCE_FILES}) -SET_TARGET_PROPERTIES(${TACTOOL} PROPERTIES COMPILE_FLAGS "-fPIE") -TARGET_LINK_LIBRARIES(${TACTOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON}) +ADD_EXECUTABLE(${DOTNETTOOL} ${${DOTNETTOOL}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${DOTNETTOOL} PROPERTIES COMPILE_FLAGS "-fPIE") +TARGET_LINK_LIBRARIES(${DOTNETTOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON}) #SET(INSTALLER_PLUGIN "ui-application") #SET(${INSTALLER_PLUGIN}_SOURCE_FILES @@ -176,7 +177,7 @@ INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR}) INSTALL(TARGETS ${NI_COMMON} DESTINATION ${LIBDIR}) INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR}) INSTALL(TARGETS ${TPATOOL} DESTINATION ${BINDIR}) -INSTALL(TARGETS ${TACTOOL} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${DOTNETTOOL} DESTINATION ${BINDIR}) #INSTALL(TARGETS ${INSTALLER_PLUGIN} DESTINATION ${INSTALL_PLUGIN_DIR}) INSTALL(TARGETS ${PREFER_DOTNET_AOT_PLUGIN} DESTINATION ${INSTALL_MDPLUGIN_DIR}) INSTALL(TARGETS ${PREFER_NUGET_CACHE_PLUGIN} DESTINATION ${INSTALL_MDPLUGIN_DIR}) @@ -186,5 +187,6 @@ INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR}) INSTALL(FILES inc/coreclr_host.h DESTINATION ${INCLUDEDIR}) INSTALL(FILES inc/dotnet_launcher_plugin.h DESTINATION ${INCLUDEDIR}) INSTALL(FILES inc/ni_common.h DESTINATION ${INCLUDEDIR}) +INSTALL(FILES inc/tac_common.h DESTINATION ${INCLUDEDIR}) INSTALL(FILES ../dotnet-launcher.pc DESTINATION ${LIBDIR}/pkgconfig) INSTALL(FILES dotnet-launcher.info DESTINATION /usr/share/parser-plugins) diff --git a/NativeLauncher/inc/tac_common.h b/NativeLauncher/inc/tac_common.h new file mode 100644 index 0000000..e18f4a7 --- /dev/null +++ b/NativeLauncher/inc/tac_common.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TAC_COMMON_H__ +#define __TAC_COMMON_H__ + +#include + +typedef enum { + TAC_ERROR_NONE = 0, + TAC_ERROR_INVALID_PARAMETER = -1, + TAC_ERROR_ALREADY_EXIST = -2, + TAC_ERROR_NO_SUCH_FILE = -3, + TAC_ERROR_INVALID_PACKAGE = -4, + TAC_ERROR_NOT_SUPPORTED = -5, + TAC_ERROR_UNKNOWN = -9 +} tac_error_e; + +/** + * @brief restore database of TAC + * @return tac_error_e + */ +tac_error_e restoreTACDB(); + +/** + * @brief remove a symbolic link file, the native images of TAC for specific package. + * @param[i] pkgId package ID + * @return tac_error_e + */ +tac_error_e resetTACPackage(const std::string& pkgId); + +/** + * @brief creates a symbolic link file, the native image of TAC for specific package. + * @param[i] pkgId package ID + * @return tac_error_e + */ +tac_error_e createTACPackage(const std::string& pkgId); + +/** + * @brief regenerate native image of TAC for all shared assembly. + * @return tac_error_e + */ +tac_error_e regenerateTAC(); + +/** + * @brief disable tac feature. + * @param[i] pkgId package ID + * @return tac_error_e + */ +tac_error_e disableTACPackage(const std::string& pkgId); + +/** + * @brief enable tac feature. + * @param[i] pkgId package ID + * @return tac_error_e + */ +tac_error_e enableTACPackage(const std::string& pkgId); + +#endif /* __TAC_COMMON_H__ */ diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index c8843b5..d0bb588 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -39,6 +39,12 @@ enum FSFlag : int { FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS = (1 << 3) }; +/** + * @brief an iterator to the begin element in the range that compares equal to option + * @param[in] begin element + * @param[in] end elment + * return return true when elements match + */ bool cmdOptionExists(char** begin, char** end, const std::string& option); /** @@ -77,6 +83,21 @@ std::string baseName(const std::string& path); int getRootPath(std::string pkgId, std::string& rootPath); /** + * @brief get exec name + * @param[in] package id + * @param[out] exec name + */ +int getExecName(std::string pkgId, std::string& execName); + +/** + * @brief get metadata value + * @param[in] package id + * @param[in] metadata key + * @param[out] metadata value + */ +int getMetadataValue(std::string pkgId, std::string metadataKey, std::string& metadataValue); + +/** * @brief split path with ":" delimiter and put that in the vector * @param[in] source path * @param[out] string vector @@ -133,6 +154,14 @@ typedef std::function FileReader; void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth); /** + * @brief update assembly file info. + * @param[in] get path + * @param[in] set path + * @param[in] symbolic link + */ +void updateAssemblyInfo(const std::string& getPath, const std::string& setPath, bool isSymlink = false); + +/** * @brief create the new directory. * @param[in] source path * @return return true when the directory was created. @@ -140,13 +169,6 @@ void scanFilesInDir(const std::string& directory, FileReader reader, unsigned in bool createDir(const bf::path& path); /** - * @brief update assembly file info. - * @param[in] get path - * @param[in] set path - */ -void updateAssemblyInfo(const std::string& getPath, const std::string& setPath); - -/** * @brief copy the directory. * @param[in] path to the source directory * @param[in] path to the target directory diff --git a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc index 1c1968f..494dddc 100644 --- a/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc +++ b/NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc @@ -56,7 +56,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app return -1; } - if (createNiUnderPkgRoot(pkgId, false) != 0) { + if (createNiUnderPkgRoot(pkgId, false) != NI_ERROR_NONE) { _ERR("Failed to get root path from [%s]", pkgId); return -1; } else { @@ -65,8 +65,8 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app std::string pkgRoot; if (getRootPath(pkgId, pkgRoot) < 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId); - return -1; + _ERR("Failed to get root path from [%s]", pkgId); + return 0; } std::string binDir = concatPath(pkgRoot, "bin"); @@ -75,23 +75,23 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app uid_t uid = 0; if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { _ERR("Failed to get UID"); - return -1; + return 0; } - for (auto& symlinkAssembly : bf::recursive_directory_iterator(bf::path(tacDir))) { + for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) { std::string symPath = symlinkAssembly.path().string(); if (!isNativeImage(symPath)) { std::string originPath = bf::read_symlink(symPath).string(); std::string originNiPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll"; if (!bf::exists(originNiPath)) { if(createNiDll(originPath, false, false) != NI_ERROR_NONE) { - _ERR("Failed to create NI file [%s]\n", originPath.c_str()); + _ERR("Failed to create NI file [%s]", originPath.c_str()); return -1; } } std::string setNiPath = symPath.substr(0, symPath.rfind(".dll")) + ".ni.dll"; if (!bf::exists(setNiPath)) { bf::create_symlink(originNiPath, setNiPath); - fprintf(stderr, "%s symbolic link file generated successfully.\n", setNiPath.c_str()); + _ERR("%s symbolic link file generated successfully.", setNiPath.c_str()); if (lchown(setNiPath.c_str(), uid, 0)) { _ERR("Failed to change owner of: %s", setNiPath.c_str()); return -1; diff --git a/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc b/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc index c5d6a2f..6e3e2c3 100644 --- a/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc +++ b/NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc @@ -57,7 +57,7 @@ std::string binPath; bool isCreateDirectory = false; static sqlite3 *tac_db = NULL; -int metadataCheck(GList *list) +bool metadataCheck(GList *list) { GList *tag = NULL; Metadata *mdInfo = NULL; @@ -68,27 +68,26 @@ int metadataCheck(GList *list) NiCommonOption option = {std::string(), std::string(), std::string()}; if (initNICommon(&option) < 0) { _ERR("Fail to initialize NI Common"); - return -1; + return false; } - return 0; - } else { - return -1; + return true; } + return false; } -int appTypeCheck(std::string pkgId) +bool appTypeCheck(std::string pkgId) { uid_t uid = 0; if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { _ERR("Failed to get UID"); - return 0; + 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 0; + return false; } bool isDotnetAppType = false; @@ -97,7 +96,7 @@ int appTypeCheck(std::string pkgId) bool* dotnet = static_cast(userData); if (pkgmgrinfo_appinfo_get_apptype(handle, &type) != PMINFO_R_OK) { _ERR("Failed to get app type : %s", type); - return 0; + return -1; } if (strcmp(type, "dotnet") == 0) { *dotnet = true; @@ -107,52 +106,19 @@ int appTypeCheck(std::string pkgId) 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()); - return -1; + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return false; } pkgmgrinfo_pkginfo_destroy_pkginfo(handle); return isDotnetAppType; } -int getExecName(std::string pkgId) -{ - uid_t uid = 0; - if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { - _ERR("Failed to get UID"); - return 0; - } - - 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 0; - } - - auto dotnetAppCounter = [] (pkgmgrinfo_appinfo_h handle, void *userData) -> int { - char* exec = nullptr; - if (pkgmgrinfo_appinfo_get_exec(handle, &exec) != PMINFO_R_OK) { - _ERR("Failed to get exec : %s", exec); - return 0; - } - execName = std::string(exec).substr(std::string(exec).rfind('/') + 1); - return 0; - }; - - if (pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, dotnetAppCounter, NULL, uid) != PMINFO_R_OK) { - _ERR("Failed to get list of app in pkg : %s", pkgId.c_str()); - return -1; - } - - pkgmgrinfo_pkginfo_destroy_pkginfo(handle); - return 0; -} - -int SHA256(std::string path, char outputBuffer[65]) +void SHA256(std::string path, char outputBuffer[65]) { FILE *file = fopen(path.c_str(), "rb"); if (!file) { - return -1; + return; } unsigned char hash[SHA256_DIGEST_LENGTH]; @@ -163,7 +129,7 @@ int SHA256(std::string path, char outputBuffer[65]) char *buffer = (char*)malloc(bufSize); if (!buffer) { fclose(file); - return -1; + return; } while ((bytesRead = fread(buffer, 1, bufSize, file))) { @@ -177,7 +143,6 @@ int SHA256(std::string path, char outputBuffer[65]) fclose(file); free(buffer); - return 0; } int depsJsonParser() @@ -191,13 +156,12 @@ int depsJsonParser() std::string error; if (ifs.is_open()) { if (!Json::parseFromStream(reader, ifs, &root, &error)) { - _INFO("Failed to parse of deps.json"); + _ERR("Failed to parse of deps.json"); ifs.close(); return -1; } const Json::Value runtimeTargetName = root["runtimeTarget"]["name"]; - std::string runtimeTarget_name = runtimeTargetName.asString(); - const Json::Value nugetPackages = root["targets"][runtimeTarget_name.c_str()]; + const Json::Value nugetPackages = root["targets"][runtimeTargetName.asString().c_str()]; for (auto& nuget : nugetPackages.getMemberNames()) { if (strstr(nuget.c_str(), TIZEN_DOTNET_NUGET) != NULL || strstr(nuget.c_str(), TIZEN_DOTNET_SDK_NUGET) != NULL || @@ -222,7 +186,7 @@ int depsJsonParser() _INFO("Nuget package : %s", nuget.c_str()); for (auto& assembly : assemblies.getMemberNames()) { std::string assembly_name = assembly.substr(assembly.rfind('/') + 1); - char buffer[65]; + char buffer[65] = {0}; SHA256(concatPath(binPath, assembly_name), buffer); nugetPackagesAssembliesShaR2R.push_back(nuget + "/" + assembly_name + "/" + buffer + "/" + r2r); _INFO("Assembly / SHA256 : %s / %s", assembly_name.c_str(), buffer); @@ -237,10 +201,15 @@ int depsJsonParser() return 0; } -int createSymlink(bf::path tac_version_dir, std::string np) +int createSymlink(std::string tac_version_dir, std::string np) { - bs::error_code error; uid_t uid = 0; + std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR); + if (!createDir(tac_dir)) { + _INFO("Cannot create directory: %s", tac_dir.c_str()); + return -1; + } + for (auto& npAssemblyShaR2R : nugetPackagesAssembliesShaR2R) { std::string nuget_package_assembly_sha = npAssemblyShaR2R.substr(0, npAssemblyShaR2R.rfind('/')); std::string sha = nuget_package_assembly_sha.substr(nuget_package_assembly_sha.rfind('/') + 1); @@ -251,7 +220,7 @@ int createSymlink(bf::path tac_version_dir, std::string np) if (!strcmp(nuget_package.c_str(), np.c_str())) { if (bf::exists(concatPath(binPath, assembly))) { if (isCreateDirectory) { - if (!copyFile(concatPath(binPath, assembly), tac_version_dir / assembly)) { + if (!copyFile(concatPath(binPath, assembly), concatPath(tac_version_dir, assembly))) { _ERR("Failed to move of %s", assembly.c_str()); return -1; } @@ -260,34 +229,15 @@ int createSymlink(bf::path tac_version_dir, std::string np) _ERR("Failed to get UID"); return -1; } - std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR); - bf::create_symlink(tac_version_dir / assembly, concatPath(tac_dir, assembly), error); - if (error) { - _ERR("Failed to create symlink"); - return -1; - } + 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; } - } - } - } - return 0; -} - -int removeOriginalAssembly() { - for (auto& npAssemblyShaR2R : nugetPackagesAssembliesShaR2R) { - std::string nuget_package_assembly_sha = npAssemblyShaR2R.substr(0, npAssemblyShaR2R.rfind('/')); - std::string sha = nuget_package_assembly_sha.substr(nuget_package_assembly_sha.rfind('/') + 1); - std::string nuget_package_assembly = nuget_package_assembly_sha.substr(0, nuget_package_assembly_sha.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 r2r = npAssemblyShaR2R.substr(npAssemblyShaR2R.rfind('/') + 1); - if (bf::exists(concatPath(binPath, assembly))) { - if (!removeFile(concatPath(binPath, assembly))) { - _ERR("Failed to remove of %s", assembly.c_str()); - return -1; + if (!removeFile(concatPath(binPath, assembly))) { + _ERR("Failed to remove of %s", assembly.c_str()); + return -1; + } } } } @@ -303,7 +253,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app _INFO("App type is not dotnet"); return 0; } - if (getExecName(std::string(pkgId)) < 0) { + if (getExecName(std::string(pkgId), execName) < 0) { return 0; } if (getRootPath(std::string(pkgId), rootPath) < 0) { @@ -311,8 +261,8 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app } else { binPath = concatPath(rootPath, "bin"); } - if (!metadataCheck(list)) { - if (depsJsonParser()) { + if (metadataCheck(list)) { + if (depsJsonParser() < 0) { return 0; } } @@ -321,6 +271,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app tac_db = dbCreate(TAC_APP_LIST_DB); if (tac_db) { if (!dbOpen(tac_db, TAC_APP_LIST_DB)) { + _ERR("Sqlite open error"); return 0; } } else { @@ -332,13 +283,6 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app _ERR("Not exist .deps.json file"); return 0; } - std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR); - if (!bf::exists(tac_dir)) { - if (!createDir(tac_dir)) { - _INFO("Cannot create directory: %s", tac_dir.c_str()); - return 0; - } - } for (auto& np : tacDB) { std::string tac_name = np.substr(0, np.find('/')); @@ -346,7 +290,8 @@ 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()); - bf::path tac_version_dir = concatPath(__TAC_DIR, np); + std::string tac_version_dir = concatPath(__TAC_DIR, np); + std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO); isCreateDirectory = false; if (!bf::exists(tac_version_dir)) { _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str()); @@ -355,8 +300,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app return 0; } isCreateDirectory = true; - createDirectories.push_back(tac_version_dir.string()); - std::string sha256_info = (tac_version_dir / TAC_SHA_256_INFO).string(); + createDirectories.push_back(tac_version_dir); std::ofstream ofs(sha256_info, std::ios::app); int assembly_count = 0; for (auto& npAssemblyShaR2R : nugetPackagesAssembliesShaR2R) { @@ -374,9 +318,9 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app ofs << assembly_count << std::endl; ofs.close(); - if (createSymlink(tac_version_dir, np)) { + if (createSymlink(tac_version_dir, np) < 0) { _ERR("Failed to create symlink"); - return 0; + return -1; } std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');"; @@ -395,7 +339,6 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app std::string r2r = npAssemblyShaR2R.substr(npAssemblyShaR2R.rfind('/') + 1); if (!strcmp(nuget_package.c_str(), np.c_str())) { assembly_count++; - std::string sha256_info = (tac_version_dir / TAC_SHA_256_INFO).string(); std::ifstream ifs(sha256_info); std::string get_str; if (ifs.is_open()) { @@ -412,8 +355,9 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app 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 : %s", tac_name.c_str()); - if (createSymlink(tac_version_dir, np)) { - return 0; + if (createSymlink(tac_version_dir, np) < 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 + "');"; @@ -422,9 +366,11 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app _INFO("Different : %s", tac_name.c_str()); } } - } - if (removeOriginalAssembly()) { - return 0; + if (!bf::exists(sha256_info)) { + if(!removeAll(tac_version_dir)) { + _ERR("Failed to remove of %s", tac_version_dir.c_str()); + } + } } return 0; } @@ -438,26 +384,26 @@ static int sqliteCb(void *count, int argc, char **argv, char **azColName) { int updateTacDB(const char *pkgId) { for (auto& unp : updateTac) { - char *error = 0; int ret; - int count = 0; + int count = -1; if (tac_db) { if (!dbOpen(tac_db, TAC_APP_LIST_DB)) { - return 0; + _ERR("Sqlite open error"); + return -1; } } else { _ERR("Sqlite create error"); - return 0; + return -1; } std::string sql = "SELECT COUNT(NUGET) FROM TAC WHERE NUGET = '" + unp + "';"; - ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, &error); + ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL); if (ret != SQLITE_OK) { - _ERR("SQL error: %s", error); - sqlite3_free(error); + _ERR("Sqlite select error"); + return -1; } - if (count < 1) { - bf::path tac_version_dir_prev = concatPath(__TAC_DIR, unp); - bf::path tac_version_dir_backup = concatPath(__TAC_DIR, unp) + ".bck"; + if (count == 0) { + std::string tac_version_dir_prev = concatPath(__TAC_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; @@ -480,7 +426,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app _INFO("App type is not dotnet"); return 0; } - if (getExecName(std::string(pkgId)) < 0) { + if (getExecName(std::string(pkgId), execName) < 0) { return 0; } if (getRootPath(std::string(pkgId), rootPath) < 0) { @@ -491,8 +437,8 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app if (!strcmp("removed", status.c_str())) { _INFO("Skipped to parse of deps.json"); } else { - if (!metadataCheck(list)) { - if (depsJsonParser()) { + if (metadataCheck(list)) { + if (depsJsonParser() < 0) { return 0; } } @@ -502,6 +448,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app tac_db = dbCreate(TAC_APP_LIST_DB); if (tac_db) { if (!dbOpen(tac_db, TAC_APP_LIST_DB)) { + _ERR("Sqlite open error"); return 0; } } else { @@ -515,25 +462,18 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app if (tacDB.empty()) { sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';"; dbDelete(tac_db, TAC_APP_LIST_DB, sql); - if (updateTacDB(pkgId)) { - return 0; + if (updateTacDB(pkgId) < 0) { + return -1; } } else { - std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR); - if (!bf::exists(tac_dir)) { - if (!createDir(tac_dir)) { - _INFO("Cannot create directory: %s", tac_dir.c_str()); - return 0; - } - } - for (auto& np : tacDB) { std::string tac_name = np.substr(0, np.find('/')); std::string tac_version = np.substr(np.rfind('/') + 1); _INFO("TAC name : %s", tac_name.c_str()); _INFO("TAC version : %s", tac_version.c_str()); - bf::path tac_version_dir = concatPath(__TAC_DIR, np); + std::string tac_version_dir = concatPath(__TAC_DIR, np); + std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO); isCreateDirectory = false; if (!bf::exists(tac_version_dir)) { _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str()); @@ -542,8 +482,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app return 0; } isCreateDirectory = true; - createDirectories.push_back(tac_version_dir.string()); - std::string sha256_info = (tac_version_dir / TAC_SHA_256_INFO).string(); + createDirectories.push_back(tac_version_dir); std::ofstream ofs2(sha256_info, std::ios::app); int assembly_count = 0; for (auto& npAssemblyShaR2R : nugetPackagesAssembliesShaR2R) { @@ -560,23 +499,22 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app } ofs2 << assembly_count << std::endl; ofs2.close(); - if (createSymlink(tac_version_dir, np)) { - return 0; + if (createSymlink(tac_version_dir, np) < 0) { + _ERR("Failed to create symlink"); + return -1; } - char *error = 0; - int count = 0; + 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, &error); + int ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL); if (ret != SQLITE_OK) { - _ERR("SQL error: %s", error); - sqlite3_free(error); + _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 { + } 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); @@ -595,7 +533,6 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app std::string r2r = npAssemblyShaR2R.substr(npAssemblyShaR2R.rfind('/') + 1); if (!strcmp(nuget_package.c_str(), np.c_str())) { assembly_count++; - std::string sha256_info = (tac_version_dir / TAC_SHA_256_INFO).string(); std::ifstream ifs2(sha256_info); std::string get_str; if (ifs2.is_open()) { @@ -613,23 +550,22 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app 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 : %s", tac_name.c_str()); - if (createSymlink(tac_version_dir, np)) { - return 0; + if (createSymlink(tac_version_dir, np) < 0) { + _ERR("Failed to create symlink"); + return -1; } - char *error = 0; - int count = 0; + 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, &error); + int ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL); if (ret != SQLITE_OK) { - _ERR("SQL error: %s", error); - sqlite3_free(error); + _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 { + } 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); @@ -638,6 +574,11 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app _INFO("Different : %s", tac_name.c_str()); } } + if (!bf::exists(sha256_info)) { + if(!removeAll(tac_version_dir)) { + _ERR("Failed to remove of %s", tac_version_dir.c_str()); + } + } } for (auto& unp : updateTac) { bool isExits = false; @@ -653,12 +594,8 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app dbDelete(tac_db, TAC_APP_LIST_DB, sql); } } - - if (removeOriginalAssembly()) { - return 0; - } - if (updateTacDB(pkgId)) { - return 0; + if (updateTacDB(pkgId) < 0) { + return -1; } } return 0; @@ -673,6 +610,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *a tac_db = dbCreate(TAC_APP_LIST_DB); if (tac_db) { if (!dbOpen(tac_db, TAC_APP_LIST_DB)) { + _ERR("Sqlite open error"); return 0; } } else { @@ -686,8 +624,8 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *a sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';"; dbDelete(tac_db, TAC_APP_LIST_DB, sql); - if (updateTacDB(pkgId)) { - return 0; + if (updateTacDB(pkgId) < 0) { + return -1; } return 0; } @@ -699,85 +637,61 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_REMOVED(const char *pkgId, const char *app status = "removed"; - PKGMGR_MDPARSER_PLUGIN_UPGRADE(pkgId, appId, list); - return 0; -} - -int install_Clean() -{ - return 0; + return PKGMGR_MDPARSER_PLUGIN_UPGRADE(pkgId, appId, list); } -int unInstall_Clean() +void cleanStep(std::string tac) { - for (auto& unp : updateTac) { - bf::path current_tac = bf::path(__TAC_DIR) / unp.substr(0, unp.find('/')); - std::vector exist_directory_name; - for (auto& bck : bf::recursive_directory_iterator(current_tac)) { - if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) { - if (!removeAll(bck.path().string())) { - _ERR("Failed to remove of %s", bck.path().c_str()); - return 0; - } - break; + std::string current_tac = concatPath(__TAC_DIR, tac.substr(0, tac.find('/'))); + for (auto& bck : bf::recursive_directory_iterator(current_tac)) { + if (bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) { + if (!removeAll(bck.path().string())) { + _ERR("Failed to remove of %s", bck.path().c_str()); } + break; } - for (auto& bck : bf::recursive_directory_iterator(current_tac)) { - if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") == NULL) { - exist_directory_name.push_back(bck.path().string()); - break; - } + } + + bool isExist = false; + for (auto& bck : bf::recursive_directory_iterator(current_tac)) { + if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") == NULL) { + isExist = true; + break; } - if (exist_directory_name.empty()) { - if (!removeAll(current_tac)) { - _ERR("Failed to remove of %s", current_tac.c_str()); - return 0; - } - } else { - exist_directory_name.clear(); + } + if (!isExist) { + if (!removeAll(current_tac)) { + _ERR("Failed to remove of %s", current_tac.c_str()); } } - return 0; } -int update_Clean() +void install_Clean() +{ + return; +} + +void unInstall_Clean() +{ + for (auto& unp : updateTac) { + cleanStep(unp); + } +} + +void update_Clean() { if (!tacDB.empty()) { for (auto& np : tacDB) { - bf::path current_tac = bf::path(__TAC_DIR) / np.substr(0, np.find('/')); - std::vector exist_directory_name; - for (auto& bck : bf::recursive_directory_iterator(current_tac)) { - if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) { - if (!removeAll(bck.path().string())) { - _ERR("Failed to remove of %s", bck.path().c_str()); - return 0; - } - break; - } - } - for (auto& bck : bf::recursive_directory_iterator(current_tac)) { - if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") == NULL) { - exist_directory_name.push_back(bck.path().string()); - break; - } - } - if (exist_directory_name.empty()) { - if (!removeAll(current_tac)) { - _ERR("Failed to remove of %s", current_tac.c_str()); - return 0; - } - } else { - exist_directory_name.clear(); - } + cleanStep(np); } } unInstall_Clean(); - return 0; } extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId, GList *list) { _DBG("[===== PKGMGR_MDPARSER_PLUGIN_CLEAN =====]"); + _INFO("PackageID : %s", pkgId); if (tac_db) { dbClose(tac_db); @@ -793,63 +707,51 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId return 0; } -int install_Undo() +void undoStep(std::string tac) +{ + std::string current_tac = concatPath(__TAC_DIR, tac.substr(0, tac.find('/'))); + for (auto& bck : bf::recursive_directory_iterator(current_tac)) { + if (bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) { + if (!moveFile(bck.path(), bck.path().string().substr(0, bck.path().string().rfind(".bck")))) { + _ERR("Failed to move %s to %s", + bck.path().c_str(), bck.path().string().substr(0, bck.path().string().rfind(".bck")).c_str()); + } + break; + } + } +} + +void install_Undo() { for (auto& cd : createDirectories) { if (!removeAll(cd)) { _ERR("Failed to remove of %s", cd.c_str()); - return 0; } } - return 0; } -int unInstall_Undo() +void unInstall_Undo() { for (auto& unp : updateTac) { - for (auto& bck : bf::recursive_directory_iterator(bf::path(__TAC_DIR) / unp.substr(0, unp.find('/')))) { - if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) { - if (!moveFile(bck.path(), bck.path().string().substr(0, bck.path().string().rfind(".bck")))) { - _ERR("Failed to move %s to %s", - bck.path().c_str(), bck.path().string().substr(0, bck.path().string().rfind(".bck")).c_str()); - return 0; - } - break; - } - } + undoStep(unp); } - return 0; } -int update_Undo() +void update_Undo() { - for (auto& cd : createDirectories) { - if (!removeAll(cd)) { - _ERR("Failed to remove of %s", cd.c_str()); - return 0; - } - } + install_Undo(); if (!tacDB.empty()) { for (auto& np : tacDB) { - for (auto& bck : bf::recursive_directory_iterator(bf::path(__TAC_DIR) / np.substr(0, np.find('/')))) { - if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) { - if (!moveFile(bck.path(), bck.path().string().substr(0, bck.path().string().rfind(".bck")))) { - _ERR("Failed to move %s to %s", - bck.path().c_str(), bck.path().string().substr(0, bck.path().string().rfind(".bck")).c_str()); - return 0; - } - break; - } - } + undoStep(np); } } unInstall_Undo(); - return 0; } extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, GList *list) { _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNDO =====]"); + _INFO("PackageID : %s", pkgId); if (tac_db) { dbRollback(tac_db); diff --git a/NativeLauncher/tool/dotnettool.cc b/NativeLauncher/tool/dotnettool.cc new file mode 100644 index 0000000..76ed563 --- /dev/null +++ b/NativeLauncher/tool/dotnettool.cc @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "log.h" +#include "utils.h" +#include "db_manager.h" +#include "ni_common.h" +#include "tac_common.h" + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "DOTNET_INSTALLER_PLUGIN" + +std::vector getCmdArgs(char** begin, char** end) +{ + std::vector list; + for (char** itr = begin+1; itr != end; itr++) { + if (strncmp(*itr, "--", 2) != 0) { + list.push_back(*itr); + } + } + return list; +} + +static void help(const char *argv0) +{ + const char* helpDesc = + "Usage: %s [args] \n" + " --help - Display this screen\n" + " --ni-system - Create NI under System DLLs\n" + " --ni-dll - Create NI for DLL\n" + " --ni-pkg - Create NI for package\n" + " --ni-pkg-dll - Create NI for DLL in package\n" + " --ni-dir - Create NI for directory\n" + " --r2r - Use ready-to-run option (default: FNV)\n" + " (This option should be used with other options)\n" + " --ni-reset-system - Remove System NI files\n" + " --ni-reset-pkg - Remove App NI files\n" + " --ni-regen-all-app - Re-generate All App NI files\n" + " --tac-regen-all - Re-generate All TAC files\n" + " --tac-restore-db - Restore TAC Database\n" + " --tac-disable-pkg - Disable TAC for package\n" + " --tac-enable-pkg - Enable TAC for package\n" + "\n" + "Example:\n" + "1. Create native image for dlls and exes under platform directories\n" + " # %s --ni-system\n" + "2. Create native image for dll\n" + " # %s --ni-dll /usr/bin/Tizen.Runtime.dll\n" + "3. Create native image under the package's bin and lib directory\n" + " # %s --ni-pkg org.tizen.FormsGallery\n" + "4. Regenerate native images for all installed .net packages with ready-to-run option\n" + " # %s --r2r --ni-regen-all-app\n\n"; + printf(helpDesc, argv0, argv0, argv0, argv0, argv0); +} + +int main(int argc, char* argv[]) +{ + bool pkgMode = false; + bool dllMode = false; + bool dirMode = false; + bool rmPkgMode = false; + bool enableR2R = false; + bool pkgDllMode = false; + bool disableTacMode = false; + bool enableTacMode = false; + + bool doGenUniqueBaseSystem = true; + + NiCommonOption option = {std::string(), std::string(), std::string()}; + if (initNICommon(&option) != NI_ERROR_NONE) { + fprintf(stderr, "Fail to initialize NI Common\n"); + return -1; + } + + if (cmdOptionExists(argv, argv+argc, "--r2r")) { + enableR2R = true; + } + + if (cmdOptionExists(argv, argv+argc, "--help")) { + help(argv[0]); + return 0; + } else if (cmdOptionExists(argv, argv+argc, "--ni-system")) { + createNiPlatform(enableR2R, doGenUniqueBaseSystem); + return 0; + } else if (cmdOptionExists(argv, argv+argc, "--ni-dll")) { + dllMode = true; + } else if (cmdOptionExists(argv, argv+argc, "--ni-pkg")) { + pkgMode = true; + } else if (cmdOptionExists(argv, argv+argc, "--ni-dir")) { + dirMode = true; + } else if (cmdOptionExists(argv, argv+argc, "--ni-reset-system")) { + removeNiPlatform(); + return 0; + } else if (cmdOptionExists(argv, argv+argc, "--ni-reset-pkg")) { + rmPkgMode = true; + } else if (cmdOptionExists(argv, argv+argc, "--ni-pkg-dll")) { + pkgDllMode = true; + } else if (cmdOptionExists(argv, argv+argc, "--ni-regen-all-app")) { + regenerateAppNI(enableR2R); + return 0; + } else if (cmdOptionExists(argv, argv+argc, "--tac-regen-all")) { + regenerateTAC(); + return 0; + } else if (cmdOptionExists(argv, argv+argc, "--tac-restore-db")) { + restoreTACDB(); + return 0; + } else if (cmdOptionExists(argv, argv+argc, "--tac-disable-pkg")) { + disableTacMode = true; + } else if (cmdOptionExists(argv, argv+argc, "--tac-enable-pkg")) { + enableTacMode = true; + } else { + help(argv[0]); + return 0; + } + + std::vector args = getCmdArgs(argv, argv+argc); + + if (args.size() < 1) { + if (pkgMode || rmPkgMode || disableTacMode || enableTacMode) { + fprintf(stderr, "Package name is missed\n"); + } else if (dllMode) { + fprintf(stderr, "DLL path is missed\n"); + } + help(argv[0]); + return 1; + } else if (args.size() < 2) { + if (pkgDllMode) { + fprintf(stderr, "Package name or DLL path is missed\n"); + help(argv[0]); + return 1; + } + } + + if (pkgMode) { + for (const std::string pkg : args) { + // if there is AOTed dlls under package root, that is skiped. + int ret = createNiUnderPkgRoot(pkg, enableR2R); + if (ret == NI_ERROR_INVALID_PACKAGE) { + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; + } else if (ret != NI_ERROR_NONE) { + fprintf(stderr, "Failed to generate NI file [%s]\n", pkg.c_str()); + return -1; + } + ret = createTACPackage(pkg); + if (ret == TAC_ERROR_INVALID_PACKAGE) { + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; + } else if (ret != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkg.c_str()); + return -1; + } + } + } else if (pkgDllMode) { + int ret = createNiDllUnderPkgRoot(args[0], args[1], enableR2R); + if (ret == NI_ERROR_INVALID_PACKAGE) { + fprintf(stderr, "Failed to get root path from [%s]\n", args[0].c_str()); + return -1; + } else if (ret == NI_ERROR_ALREADY_EXIST) { + // skip for already exist case + return -1; + } else if (ret != NI_ERROR_NONE) { + fprintf(stderr, "Failed to generate NI file [%s]\n", args[1].c_str()); + return -1; + } + } else if (rmPkgMode) { + for (const std::string pkg : args) { + int ret = removeNiUnderPkgRoot(pkg); + if (ret == NI_ERROR_INVALID_PACKAGE) { + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; + } else if (ret != NI_ERROR_NONE) { + fprintf(stderr, "Failed to remove dlls for given package [%s]\n", pkg.c_str()); + return -1; + } + ret = resetTACPackage(pkg); + if (ret == TAC_ERROR_INVALID_PACKAGE) { + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; + } else if (ret != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkg.c_str()); + return -1; + } + } + } else if (dllMode) { + // donot return error code for generation failure. + // we have to run crossgen for all input dlls. + for (const std::string dll : args) { + int ret = createNiDll(dll, enableR2R, doGenUniqueBaseSystem); + if (ret == NI_ERROR_ALREADY_EXIST) { + // skip for already exist case + } else if (ret != NI_ERROR_NONE) { + fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str()); + } + } + } else if (dirMode) { + createNiUnderDirs(args.data(), args.size(), enableR2R, doGenUniqueBaseSystem); + } else if (disableTacMode) { + for (const std::string pkg : args) { + int ret = disableTACPackage(pkg); + if (ret == TAC_ERROR_INVALID_PACKAGE) { + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; + } else if (ret != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to disable tac [%s]\n", pkg.c_str()); + return -1; + } + } + } else if (enableTacMode) { + for (const std::string pkg : args) { + int ret = enableTACPackage(pkg); + if (ret == TAC_ERROR_INVALID_PACKAGE) { + fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); + return -1; + } else if (ret != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to enable tac [%s]\n", pkg.c_str()); + return -1; + } + } + } + return 0; +} diff --git a/NativeLauncher/tool/ni_common.cc b/NativeLauncher/tool/ni_common.cc index 88fbb28..309f1cd 100644 --- a/NativeLauncher/tool/ni_common.cc +++ b/NativeLauncher/tool/ni_common.cc @@ -36,6 +36,7 @@ #include #include "ni_common.h" +#include "tac_common.h" #include "path_manager.h" #include "plugin_manager.h" @@ -323,19 +324,31 @@ static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) return -1; } - if (removeNiUnderPkgRoot(pkgId) != 0) { + if (removeNiUnderPkgRoot(pkgId) != NI_ERROR_NONE) { fprintf(stderr, "Failed to remove previous dlls from [%s]\n", pkgId); return -1; } + if (resetTACPackage(pkgId) != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkgId); + return -1; + } + // Regenerate ni files with R2R mode forcibiliy. (there is no way to now which option is used) - if (createNiUnderPkgRoot(pkgId, *enableR2R) != 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId); + if (createNiUnderPkgRoot(pkgId, *enableR2R) != NI_ERROR_NONE) { + fprintf(stderr, "Failed to generate NI file [%s]\n", pkgId); return -1; } else { fprintf(stderr, "Complete make application to native image\n"); } + if (createTACPackage(pkgId) != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkgId); + return -1; + }else { + fprintf(stderr, "Complete make symbolic link file to tac\n"); + } + return 0; } @@ -488,8 +501,7 @@ void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R, ni_error_e createNiUnderPkgRoot(const std::string& pkgId, bool enableR2R) { std::string pkgRoot; - if (getRootPath(pkgId, pkgRoot) != NI_ERROR_NONE) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str()); + if (getRootPath(pkgId, pkgRoot) < 0) { return NI_ERROR_INVALID_PACKAGE; } @@ -507,16 +519,37 @@ ni_error_e createNiDllUnderPkgRoot(const std::string& pkgId, const std::string& { std::string pkgRoot; if (getRootPath(pkgId, pkgRoot) < 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str()); return NI_ERROR_INVALID_PACKAGE; } std::string binDir = concatPath(pkgRoot, "bin"); std::string libDir = concatPath(pkgRoot, "lib"); - std::string appTAC = concatPath(binDir, ".TAC.Release"); - std::string paths = binDir + ":" + libDir + ":" + appTAC; - - return crossgen(dllPath, paths, enableR2R, 0, true); + std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR); + std::string paths = binDir + ":" + libDir + ":" + tacDir; + + if (bf::is_symlink(dllPath)) { + if (bf::exists(tacDir)) { + if (!isNativeImage(dllPath)) { + std::string originPath = bf::read_symlink(dllPath).string(); + std::string originNiPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll"; + if (!bf::exists(originNiPath)) { + if(createNiDll(originPath, false, false) != NI_ERROR_NONE) { + fprintf(stderr, "Failed to create NI file [%s]\n", originPath.c_str()); + return NI_ERROR_UNKNOWN; + } + } + std::string setNiPath = dllPath.substr(0, dllPath.rfind(".dll")) + ".ni.dll"; + if (!bf::exists(setNiPath)) { + bf::create_symlink(originNiPath, setNiPath); + fprintf(stderr, "%s symbolic link file generated successfully.\n", setNiPath.c_str()); + updateAssemblyInfo(tacDir.c_str(), setNiPath.c_str(), true); + } + } + } + return NI_ERROR_NONE; + } else { + return crossgen(dllPath, paths, enableR2R, 0, true); + } } void removeNiPlatform() @@ -567,7 +600,6 @@ ni_error_e removeNiUnderPkgRoot(const std::string& pkgId) { std::string pkgRoot; if (getRootPath(pkgId, pkgRoot) < 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str()); return NI_ERROR_INVALID_PACKAGE; } diff --git a/NativeLauncher/tool/nitool.cc b/NativeLauncher/tool/nitool.cc index cadb864..53c5016 100644 --- a/NativeLauncher/tool/nitool.cc +++ b/NativeLauncher/tool/nitool.cc @@ -36,28 +36,10 @@ std::vector getCmdArgs(char** begin, char** end) static void help(const char *argv0) { const char* helpDesc = - "Usage: %s [args] \n" - " --help - Display this screen\n" - " --system - Create NI under System DLLs\n" - " --dll - Create NI for DLL\n" - " --pkg - Create NI for package\n" - " --dir - Create NI for directory\n" - " --r2r - Use ready-to-run option (default: FNV)\n" - " (This option should be used with other options)\n" - " --reset-system - Remove System NI files\n" - " --reset-pkg - Remove App NI files\n" - " --regen-all-app - Re-generate All App NI files\n" - "\n" + "%s is deprecated. Please use dotnettool instead.\n" "Example:\n" - "1. Create native image for dlls and exes under platform directories\n" - " # %s --system\n" - "2. Create native image for dll\n" - " # %s --dll /usr/bin/Tizen.Runtime.dll\n" - "3. Create native image under the package's bin and lib directory\n" - " # %s --pkg org.tizen.FormsGallery\n" - "4. Regenerate native images for all installed .net packages with ready-to-run option\n" - " # %s --r2r --regen-all-app\n\n"; - printf(helpDesc, argv0, argv0, argv0, argv0, argv0); + " # dotnettool --help\n\n"; + printf(helpDesc, argv0); } int main(int argc, char* argv[]) @@ -127,7 +109,7 @@ int main(int argc, char* argv[]) fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str()); return -1; } else if (ret != NI_ERROR_NONE) { - fprintf(stderr, "Failed to generate NI file [%s]\n", args[1].c_str()); + fprintf(stderr, "Failed to generate NI file [%s]\n", pkg.c_str()); return -1; } } diff --git a/NativeLauncher/tool/tac_common.cc b/NativeLauncher/tool/tac_common.cc new file mode 100644 index 0000000..3c401ec --- /dev/null +++ b/NativeLauncher/tool/tac_common.cc @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "log.h" +#include "utils.h" +#include "ni_common.h" +#include "tac_common.h" +#include "db_manager.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "DOTNET_INSTALLER_PLUGIN" + +#define __XSTR(x) #x +#define __STR(x) __XSTR(x) +static const char* __TAC_DIR = __STR(TAC_DIR); +#undef __STR +#undef __XSTR + +static sqlite3 *tac_db = NULL; +std::vector restoreNuget; +std::vector enableNuget; + +void cleanupDirectory() +{ + std::vector removeNuget; + for (auto& nuget : bf::recursive_directory_iterator(__TAC_DIR)) { + bool isExist = false; + for (auto& restore : restoreNuget) { + if (!bf::is_directory(nuget.path())) { + isExist = true; + } + if (strstr(nuget.path().c_str(), restore.c_str()) != NULL) { + isExist = true; + break; + } + } + if (!isExist) { + removeNuget.push_back(nuget.path().string()); + } + } + + for (auto& rm : removeNuget) { + if (!removeAll(rm)) { + _ERR("Failed to remove of %s", rm.c_str()); + } + } + removeNuget.clear(); +} + +void depsJsonParser(std::string pkgId, std::string depsJsonPath, std::string execName, bool isRestore) +{ + std::ifstream ifs(depsJsonPath); + Json::CharReaderBuilder reader; + Json::Value root; + std::string error; + if (ifs.is_open()) { + if (!Json::parseFromStream(reader, ifs, &root, &error)) { + _INFO("Failed to parse of deps.json"); + ifs.close(); + return; + } + const Json::Value runtimeTargetName = root["runtimeTarget"]["name"]; + const Json::Value nugetPackages = root["targets"][runtimeTargetName.asString().c_str()]; + for (auto& nuget : nugetPackages.getMemberNames()) { + if (strstr(nuget.c_str(), TIZEN_DOTNET_NUGET) != NULL || + strstr(nuget.c_str(), TIZEN_DOTNET_SDK_NUGET) != NULL || + strstr(nuget.c_str(), (execName.substr(0, execName.find(".Tizen."))).c_str()) != NULL || + strstr(nuget.c_str(), (execName.substr(0, execName.find(".dll"))).c_str()) != NULL) { + continue; + } else { + const Json::Value assemblies = nugetPackages[nuget.c_str()]["runtime"]; + if (assemblies != Json::nullValue) { + const Json::Value dependencies = nugetPackages[nuget.c_str()]["dependencies"]; + bool isDependency = false; + for (auto& dependency : dependencies.getMemberNames()) { + if (strstr(dependency.c_str(), TIZEN_DOTNET_NUGET) != NULL || + strstr(dependency.c_str(), NET_STANDARD_LIBRARY_NUGET) != NULL) { + continue; + } else { + isDependency = true; + } + } + if (!isDependency) { + _INFO("PackageId : [%s] / Nuget package : [%s]", pkgId.c_str(), nuget.c_str()); + std::string name = nuget.substr(0, nuget.find('/')); + std::string version = nuget.substr(nuget.rfind('/') + 1); + std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ + "VALUES ('" + pkgId + "', '" + nuget + "', '" + name + "', '" + version + "');"; + if (isRestore) { + if (tac_db) { + dbInsert(tac_db, TAC_APP_LIST_RESTORE_DB, sql); + restoreNuget.push_back(concatPath(__TAC_DIR, name)); + } + } else { + std::string nugetPath = concatPath(__TAC_DIR, nuget); + if (bf::exists(nugetPath)) { + for (auto& assembly : assemblies.getMemberNames()) { + std::string assemblyName = assembly.substr(assembly.rfind('/') + 1); + std::string originPath = concatPath(nugetPath, assemblyName); + if (bf::exists(originPath)) { + enableNuget.push_back(originPath); + } + } + } + } + } + } + } + } + ifs.close(); + } +} + +// callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach" +static int restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData) +{ + char *pkgId = NULL; + char *root = NULL; + char *exec = NULL; + std::string rootPath; + std::string execName; + + 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 = root; + + ret = pkgmgrinfo_appinfo_get_exec(handle, &exec); + if (ret != PMINFO_R_OK) { + fprintf(stderr, "Failed to get exec name\n"); + return -1; + } + execName = std::string(exec).substr(std::string(exec).rfind('/') + 1); + + std::string depsJsonName = execName.substr(0, execName.rfind(".dll")) + ".deps.json"; + std::string depsJsonPath = concatPath(rootPath, depsJsonName); + if (bf::exists(depsJsonPath)) { + depsJsonParser(pkgId, depsJsonPath, execName, true); + } + return 0; +} + +tac_error_e restoreTACDB() +{ + if (!removeFile(TAC_APP_LIST_RESTORE_DB)) { + fprintf(stderr, "Failed to remove of %s", TAC_APP_LIST_RESTORE_DB); + return TAC_ERROR_UNKNOWN; + } + + std::string dbRestoreJournal = TAC_APP_LIST_RESTORE_DB + std::string("-journal"); + if (!removeFile(dbRestoreJournal)) { + fprintf(stderr, "Failed to remove of %s", dbRestoreJournal.c_str()); + return TAC_ERROR_UNKNOWN; + } + + tac_db = dbCreate(TAC_APP_LIST_RESTORE_DB); + if (tac_db) { + if (!dbOpen(tac_db, TAC_APP_LIST_RESTORE_DB)) { + return TAC_ERROR_UNKNOWN; + } + } else { + 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, restoreDBCb, 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(stderr, "Success pkgmgrinfo_appinfo_metadata_filter_foreach\n"); + + pkgmgrinfo_appinfo_metadata_filter_destroy(handle); + + if (tac_db) { + dbClose(tac_db); + tac_db = NULL; + } + + if (!copyFile(TAC_APP_LIST_RESTORE_DB, TAC_APP_LIST_DB)) { + fprintf(stderr, "Failed to move of %s", TAC_APP_LIST_DB); + return TAC_ERROR_UNKNOWN; + } + if (!removeFile(TAC_APP_LIST_RESTORE_DB)) { + fprintf(stderr, "Failed to remove of %s", TAC_APP_LIST_RESTORE_DB); + return TAC_ERROR_UNKNOWN; + } + + std::string dbJournal = TAC_APP_LIST_DB + std::string("-journal"); + if (!copyFile(dbRestoreJournal, dbJournal)) { + fprintf(stderr, "Failed to move of %s", dbJournal.c_str()); + return TAC_ERROR_UNKNOWN; + } + if (!removeFile(dbRestoreJournal)) { + fprintf(stderr, "Failed to remove of %s", dbRestoreJournal.c_str()); + return TAC_ERROR_UNKNOWN; + } + + cleanupDirectory(); + return TAC_ERROR_NONE; +} + +tac_error_e resetTACPackage(const std::string& pkgId) +{ + std::string pkgRoot; + if (getRootPath(pkgId, pkgRoot) < 0) { + return TAC_ERROR_INVALID_PACKAGE; + } + + std::vector tacNativeImage; + std::string binDir = concatPath(pkgRoot, "bin"); + std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR); + if (bf::exists(tacDir)) { + for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) { + std::string symPath = symlinkAssembly.path().string(); + if (bf::is_symlink(symPath)) { + if (isNativeImage(symPath)) { + tacNativeImage.push_back(symPath); + } + } + } + for (auto& path : tacNativeImage) { + if (!removeFile(path)) { + fprintf(stderr, "Failed to remove of %s", path.c_str()); + return TAC_ERROR_UNKNOWN; + } + } + } + tacNativeImage.clear(); + return TAC_ERROR_NONE; +} + +tac_error_e createTACPackage(const std::string& pkgId) +{ + std::string pkgRoot; + if (getRootPath(pkgId, pkgRoot) < 0) { + return TAC_ERROR_INVALID_PACKAGE; + } + + std::string binDir = concatPath(pkgRoot, "bin"); + std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR); + std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR); + if (bf::exists(tacDir)) { + for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) { + std::string symPath = symlinkAssembly.path().string(); + if (bf::is_symlink(symPath)) { + if (!isNativeImage(symPath)) { + std::string originPath = bf::read_symlink(symPath).string(); + std::string originNiPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll"; + if (!bf::exists(originNiPath)) { + if(createNiDll(originPath, false, false) != NI_ERROR_NONE) { + fprintf(stderr, "Failed to create NI file [%s]\n", originPath.c_str()); + return TAC_ERROR_UNKNOWN; + } + } + std::string symNIPath = symPath.substr(0, symPath.rfind(".dll")) + ".ni.dll"; + if (!bf::exists(symNIPath)) { + bf::create_symlink(originNiPath, symNIPath); + fprintf(stderr, "%s symbolic link file generated successfully.\n", symNIPath.c_str()); + updateAssemblyInfo(tacDir.c_str(), symNIPath.c_str(), true); + + std::string NIFileName = symNIPath.substr(symNIPath.rfind('/') + 1); + if (!removeFile(concatPath(binNIDir, NIFileName))) { + fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, NIFileName).c_str()); + return TAC_ERROR_UNKNOWN; + } + } + } + } + } + } + return TAC_ERROR_NONE; +} + +tac_error_e regenerateTAC() +{ + const std::string tacDir[] = {__TAC_DIR}; + removeNiUnderDirs(tacDir, 1); + + auto convert = [](const std::string& path, std::string name) { + if (strstr(path.c_str(), TAC_APP_LIST_DB) != NULL || + strstr(path.c_str(), TAC_APP_LIST_RESTORE_DB) != NULL || + strstr(path.c_str(), TAC_SHA_256_INFO) != NULL) + return; + if(createNiDll(path, false, false) != NI_ERROR_NONE) { + fprintf(stderr, "Failed to create NI file [%s]\n", path.c_str()); + return; + } + }; + scanFilesInDir(tacDir[0], convert, -1); + return TAC_ERROR_NONE; +} + +tac_error_e disableTACPackage(const std::string& pkgId) +{ + std::string pkgRoot; + if (getRootPath(pkgId, pkgRoot) < 0) { + return TAC_ERROR_INVALID_PACKAGE; + } + + std::string binDir = concatPath(pkgRoot, "bin"); + std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR); + std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR); + if (bf::exists(tacDir)) { + for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) { + std::string symPath = symlinkAssembly.path().string(); + std::string fileName = symlinkAssembly.path().filename().string(); + if (bf::is_symlink(symPath)) { + std::string originPath = bf::read_symlink(symPath).string(); + if (!isNativeImage(symPath)) { + if (!copyFile(originPath, concatPath(binDir, fileName))) { + fprintf(stderr, "Failed to copy of %s\n", concatPath(binDir, fileName).c_str()); + return TAC_ERROR_UNKNOWN; + } + updateAssemblyInfo(binDir.c_str(), concatPath(binDir, fileName).c_str()); + } else { + if (!copyFile(originPath, concatPath(binNIDir, fileName))) { + fprintf(stderr, "Failed to copy of %s\n", concatPath(binNIDir, fileName).c_str()); + return TAC_ERROR_UNKNOWN; + } + updateAssemblyInfo(binDir.c_str(), concatPath(binNIDir, fileName).c_str()); + } + } + } + } + if (!removeAll(tacDir)) { + fprintf(stderr, "Failed to remove of %s\n", tacDir.c_str()); + return TAC_ERROR_UNKNOWN; + } + return TAC_ERROR_NONE; +} + +tac_error_e enableTACPackage(const std::string& pkgId) +{ + std::string pkgRoot; + if (getRootPath(pkgId, pkgRoot) < 0) { + return TAC_ERROR_INVALID_PACKAGE; + } + + std::string execName; + if (getExecName(pkgId, execName) < 0) { + return TAC_ERROR_INVALID_PACKAGE; + } + + std::string metaValue; + if (getMetadataValue(pkgId, TAC_METADATA_KEY, metaValue) < 0) { + return TAC_ERROR_INVALID_PACKAGE; + } + + if (!strcmp(metaValue.c_str(), "true")) { + std::string binDir = concatPath(pkgRoot, "bin"); + std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR); + std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR); + if (!bf::exists(tacDir)) { + if (!createDir(tacDir)) { + fprintf(stderr, "Cannot create directory: %s\n", tacDir.c_str()); + return TAC_ERROR_UNKNOWN; + } + updateAssemblyInfo(binDir.c_str(), tacDir.c_str()); + + std::string depsJsonName = execName.substr(0, execName.rfind(".dll")) + ".deps.json"; + std::string depsJsonPath = concatPath(pkgRoot, depsJsonName); + if (bf::exists(depsJsonPath)) { + depsJsonParser(pkgId, depsJsonPath, execName, false); + } + + for (auto& originPath : enableNuget) { + if (bf::exists(originPath)) { + std::string fileName = originPath.substr(originPath.rfind('/') + 1); + std::string NIFileName = fileName.substr(0, fileName.rfind(".dll")) + ".ni.dll"; + if (bf::exists(binNIDir)) { + std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll"; + if (bf::exists(originNIPath)) { + bf::create_symlink(originNIPath, concatPath(tacDir, NIFileName)); + fprintf(stderr, "%s symbolic link file generated successfully.\n", concatPath(tacDir, NIFileName).c_str()); + updateAssemblyInfo(tacDir.c_str(), concatPath(tacDir, NIFileName).c_str(), true); + + if (!removeFile(concatPath(binNIDir, NIFileName))) { + fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, NIFileName).c_str()); + return TAC_ERROR_UNKNOWN; + } + } + } + bf::create_symlink(originPath, concatPath(tacDir, fileName)); + fprintf(stderr, "%s symbolic link file generated successfully.\n", concatPath(tacDir, fileName).c_str()); + updateAssemblyInfo(tacDir.c_str(), concatPath(tacDir, fileName).c_str(), true); + + if (!removeFile(concatPath(binDir, fileName))) { + fprintf(stderr, "Failed to remove of %s\n", concatPath(binDir, fileName).c_str()); + return TAC_ERROR_UNKNOWN; + } + } + } + if (enableNuget.empty()) { + if (!removeAll(tacDir)) { + _ERR("Failed to remove of %s", tacDir.c_str()); + } + } + } + } else { + fprintf(stderr, "The metadata key is missing or the metadata value is false of [%s]\n", pkgId.c_str()); + } + return TAC_ERROR_NONE; +} diff --git a/NativeLauncher/tool/tactool.cc b/NativeLauncher/tool/tactool.cc deleted file mode 100644 index 25e150c..0000000 --- a/NativeLauncher/tool/tactool.cc +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "log.h" -#include "utils.h" -#include "db_manager.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "DOTNET_INSTALLER_PLUGIN" - -const std::string mOptUsrDotnet = "/opt/usr/dotnet"; -const std::string mTizenNET = "Tizen.NET"; -const std::string mTizenNETSdk = "Tizen.NET.Sdk"; -const std::string mNETStandardLibrary = "NETStandard.Library"; -const std::string mDepsJson = ".deps.json"; -const std::string tacAppListDB = mOptUsrDotnet + "/.TAC.App.list.db"; -const std::string tacAppListDBJournal = mOptUsrDotnet + "/.TAC.App.list.db-journal"; -const std::string tacAppListRestoreDB = mOptUsrDotnet + "/.TAC.App.list.restore.db"; -const std::string tacAppListRestoreDBJournal = mOptUsrDotnet + "/.TAC.App.list.restore.db-journal"; -const std::string mdKey = "http://tizen.org/metadata/prefer_nuget_cache"; -const std::string mdValue = "true"; - -static sqlite3 *tac_db = NULL; -std::vector restoreNuget; - -static void help(const char *argv0) -{ - const char* helpDesc = - "Usage: %s [args] \n" - " --help - Display this screen\n" - " --restore-db - Restore TAC Database\n" - "\n"; - printf(helpDesc, argv0, argv0, argv0, argv0, argv0); -} - -void cleanupDirectory() -{ - std::vector removeNuget; - for (auto& nuget : bf::recursive_directory_iterator(bf::path(mOptUsrDotnet))) { - bool isExist = false; - for (auto& restore : restoreNuget) { - if (!bf::is_directory(nuget.path())) { - isExist = true; - } - if (strstr(nuget.path().c_str(), restore.c_str()) != NULL) { - isExist = true; - break; - } - } - if (!isExist) { - removeNuget.push_back(nuget.path().string()); - } - } - - for (auto& rm : removeNuget) { - if (bf::exists(rm)) { - if (!removeAll(rm)) { - _ERR("Failed to remove of %s", rm.c_str()); - } - } - } - removeNuget.clear(); -} - -void restoreTACDB(std::string pkgId, std::string depsJsonPath, std::string execName) -{ - std::ifstream ifs(depsJsonPath); - Json::CharReaderBuilder reader; - Json::Value root; - std::string error; - if (ifs.is_open()) { - if (!Json::parseFromStream(reader, ifs, &root, &error)) { - _INFO("Failed to parse of deps.json"); - ifs.close(); - return; - } - const Json::Value runtimeTargetName = root["runtimeTarget"]["name"]; - std::string runtimeTarget_name = runtimeTargetName.asString(); - const Json::Value nugetPackages = root["targets"][runtimeTarget_name.c_str()]; - for (auto& nuget : nugetPackages.getMemberNames()) { - if (strstr(nuget.c_str(), mTizenNET.c_str()) != NULL || - strstr(nuget.c_str(), mTizenNETSdk.c_str()) != NULL || - strstr(nuget.c_str(), (execName.substr(0, execName.find(".Tizen."))).c_str()) != NULL || - strstr(nuget.c_str(), (execName.substr(0, execName.find(".dll"))).c_str()) != NULL) { - continue; - } else { - const Json::Value assemblies = nugetPackages[nuget.c_str()]["runtime"]; - if (assemblies != Json::nullValue) { - const Json::Value dependencies = nugetPackages[nuget.c_str()]["dependencies"]; - bool isDependency = false; - for (auto& dependency : dependencies.getMemberNames()) { - if (strstr(dependency.c_str(), mTizenNET.c_str()) != NULL || - strstr(dependency.c_str(), mNETStandardLibrary.c_str()) != NULL) { - continue; - } else { - isDependency = true; - } - } - if (!isDependency) { - _INFO("PackageId : [%s] / Nuget package : [%s]", pkgId.c_str(), nuget.c_str()); - std::string name = nuget.substr(0, nuget.find('/')); - std::string version = nuget.substr(nuget.rfind('/') + 1); - std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \ - "VALUES ('" + pkgId + "', '" + nuget + "', '" + name + "', '" + version + "');"; - dbInsert(tac_db, tacAppListRestoreDB, sql); - restoreNuget.push_back(mOptUsrDotnet + "/" + name); - } - } - } - } - ifs.close(); - } -} - -static int restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData) -{ - int ret = 0; - char *pkgId = NULL; - char *root = NULL; - char *exec = NULL; - std::string rootPath; - std::string execName; - - 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 = root; - - ret = pkgmgrinfo_appinfo_get_exec(handle, &exec); - if (ret != PMINFO_R_OK) { - fprintf(stderr, "Failed to get exec name\n"); - return -1; - } - execName = std::string(exec).substr(std::string(exec).rfind('/') + 1); - - std::string depsJsonName = execName.substr(0, execName.rfind(".dll")) + mDepsJson; - std::string depsJsonPath = rootPath + "/" + depsJsonName; - if (bf::exists(depsJsonPath)) { - restoreTACDB(pkgId, depsJsonPath, execName); - } - return 0; -} - -int restoreDB() -{ - if (bf::exists(tacAppListRestoreDB)) { - if (!removeFile(tacAppListRestoreDB)) { - _ERR("Failed to remove of %s", tacAppListRestoreDB.c_str()); - return -1; - } - } - if (bf::exists(tacAppListRestoreDBJournal)) { - if (!removeFile(tacAppListRestoreDBJournal)) { - _ERR("Failed to remove of %s", tacAppListRestoreDBJournal.c_str()); - return -1; - } - } - - tac_db = dbCreate(tacAppListRestoreDB); - if (tac_db) { - if (!dbOpen(tac_db, tacAppListRestoreDB)) { - return 0; - } - } else { - return 0; - } - - int ret = 0; - pkgmgrinfo_appinfo_metadata_filter_h handle; - - ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle); - if (ret != PMINFO_R_OK) { - return -1; - } - - ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, mdKey.c_str(), mdValue.c_str()); - if (ret != PMINFO_R_OK) { - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return -1; - } - - ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, restoreDBCb, NULL); - if (ret != PMINFO_R_OK) { - fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n"); - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - return -1; - } - pkgmgrinfo_appinfo_metadata_filter_destroy(handle); - - if (tac_db) { - dbClose(tac_db); - tac_db = NULL; - } - - if (bf::exists(tacAppListRestoreDB)) { - if (!copyFile(tacAppListRestoreDB, tacAppListDB)) { - _ERR("Failed to move of %s", tacAppListDB.c_str()); - return -1; - } - if (!removeFile(tacAppListRestoreDB)) { - _ERR("Failed to remove of %s", tacAppListRestoreDB.c_str()); - return -1; - } - } - - if (bf::exists(tacAppListRestoreDBJournal)) { - if (!copyFile(tacAppListRestoreDBJournal, tacAppListDBJournal)) { - _ERR("Failed to move of %s", tacAppListDBJournal.c_str()); - return -1; - } - if (!removeFile(tacAppListRestoreDBJournal)) { - _ERR("Failed to remove of %s", tacAppListRestoreDBJournal.c_str()); - return -1; - } - } - - cleanupDirectory(); - return 0; -} - -// step 1. Remove original DB -// step 2. Parsing the .deps.json for all apps -// step 3. Create new DB -// step 4. Cleanup unnecessary TAC directory -int main(int argc, char* argv[]) -{ - if (cmdOptionExists(argv, argv + argc, "--help")) { - help(argv[0]); - } else if (cmdOptionExists(argv, argv + argc, "--restore-db")) { - restoreDB(); - } else { - help(argv[0]); - } - return 0; -} diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index ee22d0a..92075bb 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -142,6 +142,77 @@ int getRootPath(std::string pkgId, std::string& rootPath) return 0; } +int getExecName(std::string pkgId, std::string& execName) +{ + char *exec = NULL; + char *appId = 0; + + pkgmgrinfo_pkginfo_h pkg_handle; + int ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &pkg_handle); + if (ret != PMINFO_R_OK) { + return -1; + } + ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return -1; + } + + pkgmgrinfo_appinfo_h app_handle; + ret = pkgmgrinfo_appinfo_get_appinfo(appId, &app_handle); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return -1; + } + ret = pkgmgrinfo_appinfo_get_exec(app_handle, &exec); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return -1; + } + execName = std::string(exec).substr(std::string(exec).rfind('/') + 1); + + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return 0; +} + +int getMetadataValue(std::string pkgId, std::string metadataKey, std::string& metadataValue) +{ + char *value = NULL; + char *appId = 0; + + pkgmgrinfo_pkginfo_h pkg_handle; + int ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &pkg_handle); + if (ret != PMINFO_R_OK) { + return -1; + } + ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return -1; + } + + pkgmgrinfo_appinfo_h app_handle; + ret = pkgmgrinfo_appinfo_get_appinfo(appId, &app_handle); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return -1; + } + ret = pkgmgrinfo_appinfo_get_metadata_value(app_handle, metadataKey.c_str(), &value); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + //Does not return error because the metadata key may not exist. + return 0; + } + metadataValue = std::string(value); + + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return 0; +} + std::string baseName(const std::string& path) { auto pos = path.find_last_of(PATH_SEPARATOR); @@ -223,7 +294,7 @@ void scanFilesInDir(const std::string& directory, FileReader reader, unsigned in bool isDir; if (strstr(directory.c_str(), TAC_SYMLINK_SUB_DIR) != NULL) - return; // skip nitool --regen-all-app (--r2r) + return; dir = opendir(directory.c_str()); @@ -264,23 +335,39 @@ void scanFilesInDir(const std::string& directory, FileReader reader, unsigned in closedir(dir); } -void updateAssemblyInfo(const std::string& getPath, const std::string& setPath) +void updateAssemblyInfo(const std::string& getPath, const std::string& setPath, bool isSymlink) { char* label = NULL; + struct stat info; - // change smack label - if (smack_getlabel(getPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) { - if (smack_setlabel(setPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) { - fprintf(stderr, "Fail to set smack label\n"); + if (isSymlink) { + // change smack label for symbolic link. + if (smack_lgetlabel(getPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) { + if (smack_lsetlabel(setPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) { + fprintf(stderr, "Fail to set smack label\n"); + } + free(label); } - free(label); - } - // change owner and groups for generated ni file. - struct stat info; - if (!stat(getPath.c_str(), &info)) { - if (chown(setPath.c_str(), info.st_uid, info.st_gid) == -1) - fprintf(stderr, "Failed to change owner and group name\n"); + // change owner and groups for symbolic link. + if (!stat(getPath.c_str(), &info)) { + if (lchown(setPath.c_str(), info.st_uid, info.st_gid) == -1) + fprintf(stderr, "Failed to change owner and group name\n"); + } + } else { + // change smack label + if (smack_getlabel(getPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) { + if (smack_setlabel(setPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) { + fprintf(stderr, "Fail to set smack label\n"); + } + free(label); + } + + // change owner and groups for generated ni file. + if (!stat(getPath.c_str(), &info)) { + if (chown(setPath.c_str(), info.st_uid, info.st_gid) == -1) + fprintf(stderr, "Failed to change owner and group name\n"); + } } } @@ -434,6 +521,9 @@ bool copyDir(const bf::path& path1, const bf::path& path2, FSFlag flags) { bool copyFile(const bf::path& path1, const bf::path& path2) { bs::error_code error; + if (!bf::exists(path1)) { + return false; + } bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error); if (error) { _ERR("copy file %s due to error [%s]", path1.c_str(), error.message().c_str()); @@ -443,7 +533,7 @@ bool copyFile(const bf::path& path1, const bf::path& path2) { } bool moveFile(const bf::path& path1, const bf::path& path2) { - if (bf::exists(path2)) { + if (!bf::exists(path1) || bf::exists(path2)) { return false; } bs::error_code error; diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index ba2c27f..7cfc1c9 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -140,8 +140,8 @@ install -m 0644 %{name}.conf %{buildroot}/etc/tmpfiles.d/%{name}.conf %post mkdir -p /opt/etc/skel/.dotnet chsmack -t -a User::App::Shared /opt/etc/skel/.dotnet -%{_bindir}/nitool --dll %{_runtime_dir}/System.Private.CoreLib.dll chsmack -a _ %{_system_base_addr_file} +%{_bindir}/dotnettool --ni-dll %{_runtime_dir}/System.Private.CoreLib.dll %files %manifest dotnet-launcher.manifest @@ -151,7 +151,7 @@ chsmack -a _ %{_system_base_addr_file} %{_native_lib_dir}/libsqlite3.so %{_bindir}/nitool %{_bindir}/tpatool -%{_bindir}/tactool +%{_bindir}/dotnettool %{_install_mdplugin_dir}/libprefer_nuget_cache_plugin.so %{_install_mdplugin_dir}/libprefer_dotnet_aot_plugin.so %{_bindir}/dotnet-launcher @@ -167,6 +167,7 @@ chsmack -a _ %{_system_base_addr_file} %manifest dotnet-launcher.manifest %defattr(-,root,root,-) %{_includedir}/ni_common.h +%{_includedir}/tac_common.h %{_includedir}/dotnet_launcher_plugin.h %{_includedir}/coreclr_host.h %{_libdir}/libdotnet_launcher_util.so -- 2.7.4