MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
INCLUDE(FindPkgConfig)
-PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul pkgmgr-info pkgmgr-installer dlog ecore bundle dlog liblaunchpad glib-2.0 libsmack capi-appfw-app-common storage)
+PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul pkgmgr-info pkgmgr-installer dlog ecore bundle dlog liblaunchpad glib-2.0 libsmack capi-appfw-app-common storage jsoncpp openssl sqlite3)
FOREACH(flag ${${PROJECT_NAME}_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNATIVE_LIB_DIR=${NATIVE_LIB_DIR}")
ENDIF(DEFINED NATIVE_LIB_DIR)
+IF(DEFINED TAC_DIR)
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DTAC_DIR=${TAC_DIR}")
+ENDIF(DEFINED TAC_DIR)
+
OPTION(NOT_USE_FUNCTION "Remove build warning" OFF)
IF(NOT_USE_FUNCTION)
ADD_DEFINITIONS("-DNOT_USE_FUNCTION")
util/plugin_manager.cc
util/path_manager.cc
util/log_manager.cc
+ util/db_manager.cc
)
ADD_LIBRARY(${DOTNET_LAUNCHER_UTIL} SHARED ${${DOTNET_LAUNCHER_UTIL}_SOURCE_FILES})
SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER_UTIL} PROPERTIES COMPILE_FLAGS "-fPIC")
-TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_UTIL} ${${PROJECT_NAME}_LDFLAGS} "-ldl")
+TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER_UTIL} ${${PROJECT_NAME}_LDFLAGS} "-ldl" boost_filesystem boost_system)
SET(DOTNET_LAUNCHER "dotnet-launcher")
SET(${DOTNET_LAUNCHER}_SOURCE_FILES
SET(NI_COMMON "ni_common")
SET(${NI_COMMON}_SOURCE_FILES
- installer-plugin/ni_common.cc
+ tool/ni_common.cc
)
ADD_LIBRARY(${NI_COMMON} SHARED ${${NI_COMMON}_SOURCE_FILES})
SET_TARGET_PROPERTIES(${NI_COMMON} PROPERTIES COMPILE_FLAGS "-fPIC")
SET(NITOOL "nitool")
SET(${NITOOL}_SOURCE_FILES
- installer-plugin/nitool.cc
+ tool/nitool.cc
)
ADD_EXECUTABLE(${NITOOL} ${${NITOOL}_SOURCE_FILES})
SET_TARGET_PROPERTIES(${NITOOL} PROPERTIES COMPILE_FLAGS "-fPIE")
SET(TPATOOL "tpatool")
SET(${TPATOOL}_SOURCE_FILES
- installer-plugin/tpatool.cc
+ tool/tpatool.cc
)
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
+)
+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})
+
#SET(INSTALLER_PLUGIN "ui-application")
#SET(${INSTALLER_PLUGIN}_SOURCE_FILES
# util/utils.cc
#SET_TARGET_PROPERTIES(${INSTALLER_PLUGIN} PROPERTIES COMPILE_FLAGS "-fPIC")
#TARGET_LINK_LIBRARIES(${INSTALLER_PLUGIN} ${${PROJECT_NAME}_LDFLAGS})
-
SET(PREFER_DOTNET_AOT_PLUGIN "prefer_dotnet_aot_plugin")
SET(${PREFER_DOTNET_AOT_PLUGIN}_SOURCE_FILES
installer-plugin/prefer_dotnet_aot_plugin.cc
SET_TARGET_PROPERTIES(${PREFER_DOTNET_AOT_PLUGIN} PROPERTIES COMPILE_FLAGS "-fPIC")
TARGET_LINK_LIBRARIES(${PREFER_DOTNET_AOT_PLUGIN} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON})
+SET(PREFER_NUGET_CACHE_PLUGIN "prefer_nuget_cache_plugin")
+SET(${PREFER_NUGET_CACHE_PLUGIN}_SOURCE_FILES
+ installer-plugin/prefer_nuget_cache_plugin.cc
+)
+ADD_LIBRARY(${PREFER_NUGET_CACHE_PLUGIN} SHARED ${${PREFER_NUGET_CACHE_PLUGIN}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${PREFER_NUGET_CACHE_PLUGIN} PROPERTIES COMPILE_FLAGS "-fPIC")
+TARGET_LINK_LIBRARIES(${PREFER_NUGET_CACHE_PLUGIN} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON})
+
CONFIGURE_FILE(dotnet-launcher.pc.in dotnet-launcher.pc @ONLY)
INSTALL(TARGETS ${DOTNET_LAUNCHER_UTIL} DESTINATION ${LIBDIR})
INSTALL(TARGETS ${NI_COMMON} DESTINATION ${LIBDIR})
INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR})
INSTALL(TARGETS ${TPATOOL} DESTINATION ${BINDIR})
+INSTALL(TARGETS ${TACTOOL} 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})
INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR})
INSTALL(FILES dotnet.launcher DESTINATION ${LOADERDIR})
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 installer-plugin/ni_common.h DESTINATION ${INCLUDEDIR})
+INSTALL(FILES inc/ni_common.h DESTINATION ${INCLUDEDIR})
INSTALL(FILES ../dotnet-launcher.pc DESTINATION ${LIBDIR}/pkgconfig)
+INSTALL(FILES dotnet-launcher.info DESTINATION /usr/share/parser-plugins)
--- /dev/null
+type="metadata";name="http://tizen.org/metadata/prefer_nuget_cache";path="/etc/package-manager/parserlib/metadata/libprefer_nuget_cache_plugin.so"\r
+type="metadata";name="http://tizen.org/metadata/prefer_dotnet_aot";path="/etc/package-manager/parserlib/metadata/libprefer_dotnet_aot_plugin.so"\r
--- /dev/null
+/*
+ * 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 __DB_MANAGER_H__
+#define __DB_MANAGER_H__
+
+#include <string>
+#include <sqlite3.h>
+#include <vector>
+
+#define CREATE_TAC_DB_TABLE "CREATE TABLE IF NOT EXISTS TAC(\
+ ID INTEGER PRIMARY KEY AUTOINCREMENT,\
+ PKGID TEXT,\
+ NUGET TEXT,\
+ NAME TEXT,\
+ VERSION TEXT);"
+#define QUERY_MAX_LEN 4096
+
+sqlite3* dbCreate(std::string path);
+bool dbOpen(sqlite3 *tac_db, std::string path);
+void dbClose(sqlite3 *tac_db);
+void dbRollback(sqlite3 *tac_db);
+bool dbUpdate(sqlite3 *tac_db, std::string path, std::string query);
+bool dbInsert(sqlite3 *tac_db, std::string path, std::string query);
+std::vector<std::string> dbSelect(sqlite3 *tac_db, std::string path, std::string query);
+bool dbDelete(sqlite3 *tac_db, std::string path, std::string query);
+
+#endif /* __DB_MANAGER_H__ */
int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr doc, const char* pkgId);
int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr doc, const char* pkgId);
int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr doc, const char* pkgId);
+ int PKGMGR_PARSER_PLUGIN_REMOVED(xmlDocPtr doc, const char* pkgId);
+ int PKGMGR_PARSER_PLUGIN_CLEAN(xmlDocPtr doc, const char* pkgId);
+ int PKGMGR_PARSER_PLUGIN_UNDO(xmlDocPtr doc, const char* pkgId);
int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char *pkgId);
int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char *pkgId);
#include <string>
#include <vector>
#include <functional>
+#include <boost/filesystem.hpp>
#include <launcher_env.h>
#define PATH_SEPARATOR '/'
#endif
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+enum FSFlag : int {
+ FS_NONE = 0,
+ FS_MERGE_SKIP = (1 << 0),
+ FS_MERGE_OVERWRITE = (1 << 1),
+ FS_COMMIT_COPY_FILE = (1 << 2),
+ FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS = (1 << 3)
+};
+
+bool cmdOptionExists(char** begin, char** end, const std::string& option);
+
/**
* @brief get current executable path
* return std::string path
std::string baseName(const std::string& path);
/**
+ * @brief get root path
+ * @param[in] package id
+ * @param[out] root path
+ */
+int getRootPath(std::string pkgId, std::string& rootPath);
+
+/**
* @brief split path with ":" delimiter and put that in the vector
* @param[in] source path
* @param[out] string vector
*/
void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth);
+/**
+ * @brief create the new directory.
+ * @param[in] source path
+ * @return return true when the directory was created.
+ */
+bool createDir(const bf::path& path);
+
+/**
+ * @brief copy the directory.
+ * @param[in] path to the source directory
+ * @param[in] path to the target directory
+ * @param[in] filesystem flag
+ * @return return true when the directory was copied.
+ */
+bool copyDir(const bf::path& path1, const bf::path& path2, FSFlag flags = FS_NONE);
+
+/**
+ * @brief copy the file.
+ * @param[in] path to the source file
+ * @param[in] path to the target file
+ * @return return true when the file was copied.
+ */
+bool copyFile(const bf::path& path1, const bf::path& path2);
+
+/**
+ * @brief moves of renames the file or directory.
+ * @param[in] path to the source file
+ * @param[in] path to the target file
+ * @return return true when the file was moved.
+ */
+bool moveFile(const bf::path& path1, const bf::path& path2);
+
+/**
+ * @brief removes the file or empty directory.
+ * @param[in] source path
+ * @return return true when the file was deleted.
+ */
+bool removeFile(const bf::path& path);
+
+/**
+ * @brief removes the file or directory and all its contents.
+ * @param[in] source path
+ * @return return true when the file or directory was deleted.
+ */
+bool removeAll(const bf::path& path);
+
#endif /* __UTILS_H__ */
{
return PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgId, appId, list);
}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *appId, GList *list)
+{
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_REMOVED(const char *pkgId, const char *appId, GList *list)
+{
+ return PKGMGR_MDPARSER_PLUGIN_UPGRADE(pkgId, appId, list);
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId, GList *list)
+{
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, GList *list)
+{
+ return 0;
+}
--- /dev/null
+/*
+ * 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 "ni_common.h"
+#include "utils.h"
+#include "db_manager.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "DOTNET_INSTALLER_PLUGIN"
+
+#include <cstring>
+#include <fstream>
+#include <sstream>
+#include <vector>
+#include <boost/filesystem.hpp>
+#include <glib.h>
+#include <json/json.h>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+#include <openssl/sha.h>
+
+typedef struct Metadata {
+ const char *key;
+ const char *value;
+} Metadata;
+
+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 mTacRelease = ".TAC.Release";
+const std::string mDepsJson = ".deps.json";
+const std::string mBackup = ".bck";
+const std::string mdValue = "true";
+const std::string mdKey = "http://tizen.org/metadata/prefer_nuget_cache";
+const std::string tacAppListDB = mOptUsrDotnet + "/.TAC.App.list.db";
+
+std::vector<std::string> nugetPackagesAssembliesShaR2R;
+std::vector<std::string> tacDB;
+std::vector<std::string> createDirectories;
+std::vector<std::string> updateTac;
+std::string status = "";
+std::string rootPath;
+std::string execName;
+bf::path binPath;
+bool isCreateDirectory = false;
+static sqlite3 *tac_db = NULL;
+
+int metadataCheck(GList *list)
+{
+ GList *tag = NULL;
+ Metadata *mdInfo = NULL;
+ tag = g_list_first(list);
+ mdInfo = (Metadata*)tag->data;
+ if (mdInfo->key == mdKey && mdInfo->value == mdValue) {
+ _DBG("Prefer nuget cache set TRUE");
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+int appTypeCheck(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;
+ }
+
+ bool isDotnetAppType = false;
+ auto dotnetAppCounter = [] (pkgmgrinfo_appinfo_h handle, void *userData) -> int {
+ char* type = nullptr;
+ bool* dotnet = static_cast<bool*>(userData);
+ if (pkgmgrinfo_appinfo_get_apptype(handle, &type) != PMINFO_R_OK) {
+ _ERR("Failed to get app type : %s", type);
+ return 0;
+ }
+ if (strcmp(type, "dotnet") == 0) {
+ *dotnet = true;
+ }
+ return 0;
+ };
+
+ if (pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, dotnetAppCounter, &isDotnetAppType, uid) != PMINFO_R_OK) {
+ _ERR("Failed to get list of app in pkg : %s", pkgId.c_str());
+ return -1;
+ }
+
+ 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])
+{
+ FILE *file = fopen(path.c_str(), "rb");
+ if (!file) {
+ return -1;
+ }
+
+ 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 -1;
+ }
+
+ 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++) {
+ sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
+ }
+ outputBuffer[64] = 0;
+
+ fclose(file);
+ free(buffer);
+ return 0;
+}
+
+int depsJsonParser()
+{
+ std::string deps_json_name = execName.substr(0, execName.rfind(".dll")) + mDepsJson;
+ if (bf::exists(rootPath + "/" + deps_json_name)) {
+ std::string deps_json_path = rootPath + "/" + deps_json_name;
+ std::ifstream ifs(deps_json_path);
+ 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 -1;
+ }
+ 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"];
+ std::string r2r = "";
+ for (auto& dependency : dependencies.getMemberNames()) {
+ if (strstr(dependency.c_str(), mTizenNET.c_str()) != NULL ||
+ strstr(dependency.c_str(), mNETStandardLibrary.c_str()) != NULL) {
+ continue;
+ } else {
+ r2r = "--r2r";
+ }
+ }
+ if (strcmp(r2r.c_str(), "--r2r")) {
+ tacDB.push_back(nuget);
+ _INFO("Nuget package : %s", nuget.c_str());
+ for (auto& assembly : assemblies.getMemberNames()) {
+ std::string assembly_name = assembly.substr(assembly.rfind('/') + 1);
+ char buffer[65];
+ SHA256((binPath / assembly_name).string(), buffer);
+ nugetPackagesAssembliesShaR2R.push_back(nuget + "/" + assembly_name + "/" + buffer + "/" + r2r);
+ _INFO("Assembly / SHA256 : %s / %s", assembly_name.c_str(), buffer);
+ }
+ }
+ }
+ }
+ }
+ ifs.close();
+ }
+ }
+ return 0;
+}
+
+int createSymlink(bf::path tac_version_dir, std::string np)
+{
+ bs::error_code error;
+ uid_t uid = 0;
+ 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);
+ std::string ni_assembly = assembly.substr(0, assembly.rfind(".dll")) + ".ni.dll";
+ if (!strcmp(nuget_package.c_str(), np.c_str())) {
+ if (bf::exists(binPath / assembly)) {
+ if (isCreateDirectory) {
+ std::string command = "nitool --dll " + binPath.string() + "/" + assembly + " " + r2r;
+ if (system(command.c_str()) != 0) {
+ _ERR("Failed to create ni dll [%s]", command.c_str());
+ return -1;
+ }
+ if (!copyFile(binPath / ni_assembly, tac_version_dir / ni_assembly)) {
+ _ERR("Failed to move of %s", ni_assembly.c_str());
+ return -1;
+ }
+ if (!copyFile(binPath / assembly, tac_version_dir / assembly)) {
+ _ERR("Failed to move of %s", assembly.c_str());
+ return -1;
+ }
+ }
+ if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
+ _ERR("Failed to get UID");
+ return -1;
+ }
+ bf::create_symlink(tac_version_dir / ni_assembly, binPath / mTacRelease / ni_assembly, error);
+ if (error) {
+ _ERR("Failed to create symlink");
+ return -1;
+ }
+ bf::create_symlink(tac_version_dir / assembly, binPath / mTacRelease / assembly, error);
+ if (error) {
+ _ERR("Failed to create symlink");
+ return -1;
+ }
+ if (lchown((binPath / mTacRelease / ni_assembly).c_str(), uid, 0)) {
+ _ERR("Failed to change owner of: %s", (binPath / mTacRelease / ni_assembly).c_str());
+ return -1;
+ }
+ if (lchown((binPath / mTacRelease / assembly).c_str(), uid, 0)) {
+ _ERR("Failed to change owner of: %s", (binPath / mTacRelease / 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);
+ std::string ni_assembly = assembly.substr(0, assembly.rfind(".dll")) + ".ni.dll";
+ if (bf::exists(binPath / assembly)) {
+ if (!removeFile(binPath / assembly)) {
+ _ERR("Failed to remove of %s", assembly.c_str());
+ return -1;
+ }
+ }
+ if (bf::exists(binPath / ni_assembly)) {
+ if (!removeFile(binPath / ni_assembly)) {
+ _ERR("Failed to remove of %s", ni_assembly.c_str());
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *appId, GList *list)
+{
+ _DBG("[===== PKGMGR_MDPARSER_PLUGIN_INSTALL =====]");
+ _INFO("PackageID : %s", pkgId);
+
+ if (!appTypeCheck(std::string(pkgId))) {
+ _INFO("App type is not dotnet");
+ return 0;
+ }
+ if (getExecName(std::string(pkgId)) < 0) {
+ return 0;
+ }
+ if (getRootPath(std::string(pkgId), rootPath) < 0) {
+ return 0;
+ } else {
+ binPath = rootPath / bf::path("bin");
+ }
+ if (!metadataCheck(list)) {
+ if (depsJsonParser()) {
+ return 0;
+ }
+ }
+
+ status = "install";
+ tac_db = dbCreate(tacAppListDB);
+ if (tac_db) {
+ if (!dbOpen(tac_db, tacAppListDB)) {
+ return 0;
+ }
+ } else {
+ _ERR("Sqlite create error");
+ return 0;
+ }
+
+ if (tacDB.empty()) {
+ _ERR("Not exist .deps.json file");
+ return 0;
+ }
+ if (!bf::exists(binPath / mTacRelease)) {
+ if (!createDir(binPath / mTacRelease)) {
+ _INFO("Cannot create directory: %s", (binPath / mTacRelease).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 = bf::path(mOptUsrDotnet) / np;
+ isCreateDirectory = false;
+ if (!bf::exists(tac_version_dir)) {
+ _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str());
+ if (!createDir(tac_version_dir)) {
+ _ERR("Cannot create directory: %s", tac_version_dir.c_str());
+ return 0;
+ }
+ isCreateDirectory = true;
+ createDirectories.push_back(tac_version_dir.string());
+ std::string sha256_info = (tac_version_dir / bf::path("SHA256.info")).string();
+ std::ofstream ofs(sha256_info, std::ios::app);
+ int assembly_count = 0;
+ 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 (!strcmp(nuget_package.c_str(), np.c_str())) {
+ ofs << assembly << ";" << sha << std::endl;
+ assembly_count++;
+ }
+ }
+ ofs << assembly_count << std::endl;
+ ofs.close();
+
+ if (createSymlink(tac_version_dir, np)) {
+ _ERR("Failed to create symlink");
+ return 0;
+ }
+ std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
+ "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
+ dbInsert(tac_db, tacAppListDB, sql);
+ } else {
+ _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str());
+ int compare_count = 0;
+ int assembly_count = 0;
+ std::string sha256_count = "0";
+ for (auto& 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 (!strcmp(nuget_package.c_str(), np.c_str())) {
+ assembly_count++;
+ std::string sha256_info = (tac_version_dir / bf::path("SHA256.info")).string();
+ std::ifstream ifs(sha256_info);
+ std::string get_str;
+ if (ifs.is_open()) {
+ while (getline(ifs, get_str)) {
+ if (!strcmp(get_str.c_str(), (assembly + ";" + sha).c_str())) {
+ compare_count++;
+ }
+ sha256_count = get_str;
+ }
+ ifs.close();
+ }
+ }
+ }
+ if (!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;
+ }
+ std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
+ "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
+ dbInsert(tac_db, tacAppListDB, sql);
+ } else {
+ _INFO("Different : %s", tac_name.c_str());
+ }
+ }
+ }
+ if (removeOriginalAssembly()) {
+ return 0;
+ }
+ return 0;
+}
+
+static int sqliteCb(void *count, int argc, char **argv, char **azColName) {
+ int *c = (int*)count;
+ *c = atoi(argv[0]);
+ return 0;
+}
+
+int updateTacDB(const char *pkgId)
+{
+ for (auto& unp : updateTac) {
+ char *error = 0;
+ int ret;
+ int count = 0;
+ if (tac_db) {
+ if (!dbOpen(tac_db, tacAppListDB)) {
+ return 0;
+ }
+ } else {
+ _ERR("Sqlite create error");
+ return 0;
+ }
+ std::string sql = "SELECT COUNT(NUGET) FROM TAC WHERE NUGET = '" + unp + "';";
+ ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, &error);
+ if (ret != SQLITE_OK) {
+ _ERR("SQL error: %s", error);
+ sqlite3_free(error);
+ }
+ if (count < 1) {
+ bf::path tac_version_dir_prev = bf::path(mOptUsrDotnet) / unp;
+ bf::path tac_version_dir_backup = bf::path(mOptUsrDotnet) / (unp + mBackup);
+ 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;
+ }
+ if (!removeAll(tac_version_dir_prev)) {
+ _ERR("Failed to remove of %s", tac_version_dir_prev.c_str());
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *appId, GList *list)
+{
+ _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UPGRADE =====]");
+ _INFO("PackageID : %s", pkgId);
+
+ if (!appTypeCheck(std::string(pkgId))) {
+ _INFO("App type is not dotnet");
+ return 0;
+ }
+ if (getExecName(std::string(pkgId)) < 0) {
+ return 0;
+ }
+ if (getRootPath(std::string(pkgId), rootPath) < 0) {
+ return 0;
+ } else {
+ binPath = rootPath / bf::path("bin");
+ }
+ if (!strcmp("removed", status.c_str())) {
+ _INFO("Skipped to parse of deps.json");
+ } else {
+ if (!metadataCheck(list)) {
+ if (depsJsonParser()) {
+ return 0;
+ }
+ }
+ }
+
+ status = "update";
+ tac_db = dbCreate(tacAppListDB);
+ if (tac_db) {
+ if (!dbOpen(tac_db, tacAppListDB)) {
+ return 0;
+ }
+ } else {
+ _ERR("Sqlite create error");
+ return 0;
+ }
+
+ std::string sql = "SELECT * FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
+ updateTac = dbSelect(tac_db, tacAppListDB, sql);
+
+ if (tacDB.empty()) {
+ sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
+ dbDelete(tac_db, tacAppListDB, sql);
+ if (updateTacDB(pkgId)) {
+ return 0;
+ }
+ } else {
+ if (!bf::exists(binPath / mTacRelease)) {
+ if (!createDir(binPath / mTacRelease)) {
+ _INFO("Cannot create directory: %s", (binPath / mTacRelease).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 = bf::path(mOptUsrDotnet) / np;
+ isCreateDirectory = false;
+ if (!bf::exists(tac_version_dir)) {
+ _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str());
+ if (!createDir(tac_version_dir)) {
+ _ERR("Cannot create directory: %s", tac_version_dir.c_str());
+ return 0;
+ }
+ isCreateDirectory = true;
+ createDirectories.push_back(tac_version_dir.string());
+ std::string sha256_info = (tac_version_dir / bf::path("SHA256.info")).string();
+ std::ofstream ofs2(sha256_info, std::ios::app);
+ int assembly_count = 0;
+ 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 (!strcmp(nuget_package.c_str(), np.c_str())) {
+ ofs2 << assembly << ";" << sha << std::endl;
+ assembly_count++;
+ }
+ }
+ ofs2 << assembly_count << std::endl;
+ ofs2.close();
+ if (createSymlink(tac_version_dir, np)) {
+ return 0;
+ }
+
+ char *error = 0;
+ int count = 0;
+ 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);
+ if (ret != SQLITE_OK) {
+ _ERR("SQL error: %s", error);
+ sqlite3_free(error);
+ }
+
+ 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, tacAppListDB, sql);
+ } else {
+ sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
+ "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
+ dbInsert(tac_db, tacAppListDB, sql);
+ }
+ } else {
+ _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str());
+ int compare_count = 0;
+ int assembly_count = 0;
+ std::string sha256_count = "0";
+ for (auto& 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 (!strcmp(nuget_package.c_str(), np.c_str())) {
+ assembly_count++;
+ std::string sha256_info = (tac_version_dir / bf::path("SHA256.info")).string();
+ std::ifstream ifs2(sha256_info);
+ std::string get_str;
+ if (ifs2.is_open()) {
+ while (getline(ifs2, get_str)) {
+ if (!strcmp(get_str.c_str(), (assembly + ";" + sha).c_str())) {
+ compare_count++;
+ }
+ sha256_count = get_str;
+ }
+ ifs2.close();
+ }
+ }
+ }
+
+ 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;
+ }
+
+ char *error = 0;
+ int count = 0;
+ 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);
+ if (ret != SQLITE_OK) {
+ _ERR("SQL error: %s", error);
+ sqlite3_free(error);
+ }
+
+ 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, tacAppListDB, sql);
+ } else {
+ sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
+ "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
+ dbInsert(tac_db, tacAppListDB, sql);
+ }
+ } else {
+ _INFO("Different : %s", tac_name.c_str());
+ }
+ }
+ }
+ for (auto& unp : updateTac) {
+ bool isExits = false;
+ for (auto& np : tacDB) {
+ if (!strcmp(unp.c_str(), np.c_str())) {
+ isExits = true;
+ break;
+ }
+ }
+
+ if (!isExits) {
+ std::string sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "' AND NUGET = '" + unp + "';";
+ dbDelete(tac_db, tacAppListDB, sql);
+ }
+ }
+
+ if (removeOriginalAssembly()) {
+ return 0;
+ }
+ if (updateTacDB(pkgId)) {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *appId, GList *list)
+{
+ _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNINSTALL =====]");
+ _INFO("PackageID : %s", pkgId);
+
+ status = "uninstall";
+ tac_db = dbCreate(tacAppListDB);
+ if (tac_db) {
+ if (!dbOpen(tac_db, tacAppListDB)) {
+ return 0;
+ }
+ } else {
+ _ERR("Sqlite create error");
+ return 0;
+ }
+
+ std::string sql = "SELECT * FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
+ updateTac = dbSelect(tac_db, tacAppListDB, sql);
+
+ sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
+ dbDelete(tac_db, tacAppListDB, sql);
+
+ if (updateTacDB(pkgId)) {
+ return 0;
+ }
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_REMOVED(const char *pkgId, const char *appId, GList *list)
+{
+ _DBG("[===== PKGMGR_MDPARSER_PLUGIN_REMOVED =====]");
+ status = "removed";
+
+ PKGMGR_MDPARSER_PLUGIN_UPGRADE(pkgId, appId, list);
+ return 0;
+}
+
+int install_Clean()
+{
+ return 0;
+}
+
+int unInstall_Clean()
+{
+ for (auto& unp : updateTac) {
+ bf::path current_tac = bf::path(mOptUsrDotnet) / unp.substr(0, unp.find('/'));
+ std::vector<std::string> 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(), mBackup.c_str()) != 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(), mBackup.c_str()) == 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();
+ }
+ }
+ return 0;
+}
+
+int update_Clean()
+{
+ if (!tacDB.empty()) {
+ for (auto& np : tacDB) {
+ bf::path current_tac = bf::path(mOptUsrDotnet) / np.substr(0, np.find('/'));
+ std::vector<std::string> 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(), mBackup.c_str()) != 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(), mBackup.c_str()) == 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();
+ }
+ }
+ }
+ unInstall_Clean();
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId, GList *list)
+{
+ _DBG("[===== PKGMGR_MDPARSER_PLUGIN_CLEAN =====]");
+
+ if (tac_db) {
+ dbClose(tac_db);
+ tac_db = NULL;
+ }
+ if (!strcmp("install", status.c_str())) {
+ install_Clean();
+ } else if (!strcmp("update", status.c_str())) {
+ update_Clean();
+ } else if (!strcmp("uninstall", status.c_str())) {
+ unInstall_Clean();
+ }
+ return 0;
+}
+
+int 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()
+{
+ for (auto& unp : updateTac) {
+ for (auto& bck : bf::recursive_directory_iterator(bf::path(mOptUsrDotnet) / unp.substr(0, unp.find('/')))) {
+ if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), mBackup.c_str()) != NULL) {
+ if (!moveFile(bck.path(), bck.path().string().substr(0, bck.path().string().rfind(mBackup.c_str())))) {
+ _ERR("Failed to move %s to %s",
+ bck.path().c_str(), bck.path().string().substr(0, bck.path().string().rfind(mBackup.c_str())).c_str());
+ return 0;
+ }
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+int update_Undo()
+{
+ for (auto& cd : createDirectories) {
+ if (!removeAll(cd)) {
+ _ERR("Failed to remove of %s", cd.c_str());
+ return 0;
+ }
+ }
+ if (!tacDB.empty()) {
+ for (auto& np : tacDB) {
+ for (auto& bck : bf::recursive_directory_iterator(bf::path(mOptUsrDotnet) / np.substr(0, np.find('/')))) {
+ if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), mBackup.c_str()) != NULL) {
+ if (!moveFile(bck.path(), bck.path().string().substr(0, bck.path().string().rfind(mBackup.c_str())))) {
+ _ERR("Failed to move %s to %s",
+ bck.path().c_str(), bck.path().string().substr(0, bck.path().string().rfind(mBackup.c_str())).c_str());
+ return 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+ unInstall_Undo();
+ return 0;
+}
+
+extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, GList *list)
+{
+ _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNDO =====]");
+
+ if (tac_db) {
+ dbRollback(tac_db);
+ tac_db = NULL;
+ }
+ if (!strcmp("install", status.c_str())) {
+ install_Undo();
+ } else if (!strcmp("update", status.c_str())) {
+ update_Undo();
+ } else if (!strcmp("uninstall", status.c_str())) {
+ unInstall_Undo();
+ }
+ return 0;
+}
std::string appRoot = std::string("/proc/self/fd/") + std::to_string(fd);
std::string appBin = concatPath(appRoot, "bin");
std::string appLib = concatPath(appRoot, "lib");
- std::string probePath = appBin + ":" + appLib;
- std::string NIprobePath = appBin + APP_NI_SUB_DIR + ":" + appLib + APP_NI_SUB_DIR;
+ std::string appTAC = concatPath(appBin, ".TAC.Release");
+ std::string NIprobePath = appBin + APP_NI_SUB_DIR + ":" + appLib + APP_NI_SUB_DIR + ":" + appTAC;
std::string tpa = getTPA();
std::string nativeLibPath = getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib + ":" + __nativeLibDirectory;
std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid());
{
struct stat sb;
if (stat(ELEMENTARY_PATH, &sb) != 0) {
- _ERR("[candidate] libelememantary is not exist. skip precreation");
+ _ERR("[candidate] libelementary is not exist. skip precreation");
return;
}
}
}
-ni_error_e createNiUnderPkgRoot(const std::string& pkgName, bool enableR2R)
+ni_error_e createNiUnderPkgRoot(const std::string& pkgId, bool enableR2R)
{
std::string pkgRoot;
- if (getRootPath(pkgName, pkgRoot) != NI_ERROR_NONE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkgName.c_str());
+ if (getRootPath(pkgId, pkgRoot) != NI_ERROR_NONE) {
+ 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 paths[] = {binDir, libDir};
+ std::string appTAC = concatPath(binDir, ".TAC.Release");
+ std::string paths[] = {binDir, libDir, appTAC};
- createNiUnderDirs(paths, 2, enableR2R, true);
+ createNiUnderDirs(paths, 3, enableR2R, true);
return NI_ERROR_NONE;
}
-ni_error_e createNiDllUnderPkgRoot(const std::string& pkgName, const std::string& dllPath, bool enableR2R)
+ni_error_e createNiDllUnderPkgRoot(const std::string& pkgId, const std::string& dllPath, bool enableR2R)
{
std::string pkgRoot;
- if (getRootPath(pkgName, pkgRoot) < 0) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkgName.c_str());
+ if (getRootPath(pkgId, pkgRoot) < 0) {
+ fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str());
return NI_ERROR_INVALID_PACKAGE;
}
void removeNiUnderDirs(const std::string rootPaths[], int count)
{
auto convert = [](const std::string& path, std::string name) {
- std::string ni;
if (isNativeImage(path)) {
if (remove(path.c_str())) {
fprintf(stderr, "Failed to remove %s\n", path.c_str());
scanFilesInDir(rootPaths[i], convert, -1);
}
-ni_error_e removeNiUnderPkgRoot(const std::string& pkgName)
+ni_error_e removeNiUnderPkgRoot(const std::string& pkgId)
{
std::string pkgRoot;
- if (getRootPath(pkgName, pkgRoot) < 0) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkgName.c_str());
+ if (getRootPath(pkgId, pkgRoot) < 0) {
+ fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str());
return NI_ERROR_INVALID_PACKAGE;
}
pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
return NI_ERROR_NONE;
}
-
* limitations under the License.
*/
+#include "utils.h"
#include "ni_common.h"
#include <cstdio>
return list;
}
-bool cmdOptionExists(char** begin, char** end, const std::string& option)
-{
- return std::find(begin, end, option) != end;
-}
-
static void help(const char *argv0)
{
const char* helpDesc =
--- /dev/null
+/*
+ * 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 <algorithm>
+#include <cstdio>
+#include <cstring>
+#include <fstream>
+#include <vector>
+
+#include <json/json.h>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+
+#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<std::string> restoreNuget;
+
+static void help(const char *argv0)
+{
+ const char* helpDesc =
+ "Usage: %s [args] <root paths or pkg name>\n"
+ " --help - Display this screen\n"
+ " --restore-db - Restore TAC Database\n"
+ "\n";
+ printf(helpDesc, argv0, argv0, argv0, argv0, argv0);
+}
+
+void cleanupDirectory()
+{
+ std::vector<std::string> 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;
+}
std::ofstream out(__PLATFORM_TPA_CACHE);
out << tpaList;
out.close();
-
+
return 0;
}
--- /dev/null
+/*
+ * 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 "db_manager.h"
+#include "log.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "DOTNET_INSTALLER_PLUGIN"
+
+sqlite3* dbCreate(std::string path)
+{
+ sqlite3 *sqlite = NULL;
+ int ret = sqlite3_open(path.c_str(), &sqlite);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%d] : path [%s]", ret, path.c_str());
+ return NULL;
+ }
+ ret = sqlite3_exec(sqlite, "PRAGMA journal_mode = PERSIST", NULL, NULL, NULL);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%d]", ret);
+ return NULL;
+ }
+ ret = sqlite3_exec(sqlite, CREATE_TAC_DB_TABLE, NULL, NULL, NULL);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%d] : path [%s]", ret, path.c_str());
+ return NULL;
+ }
+ return sqlite;
+}
+
+bool dbOpen(sqlite3 *tac_db, std::string path)
+{
+ if (!tac_db) {
+ int ret = sqlite3_open(path.c_str(), &tac_db);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%d] : path [%s]", ret, path.c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+void dbFinalize(sqlite3_stmt *stmt)
+{
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ stmt = NULL;
+ }
+}
+
+void dbClose(sqlite3 *tac_db)
+{
+ if (tac_db) {
+ sqlite3_exec(tac_db, "COMMIT;", NULL, NULL, NULL);
+ sqlite3_close(tac_db);
+ tac_db = NULL;
+ }
+}
+
+void dbRollback(sqlite3 *tac_db)
+{
+ if (tac_db) {
+ sqlite3_exec(tac_db, "ROLLBACK;", NULL, NULL, NULL);
+ sqlite3_close(tac_db);
+ tac_db = NULL;
+ }
+}
+
+bool dbUpdate(sqlite3 *tac_db, std::string path, std::string query)
+{
+ sqlite3_stmt *stmt = NULL;
+ if (!dbOpen(tac_db, path)) {
+ return false;
+ }
+ int ret = sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
+ ret = sqlite3_prepare(tac_db, query.c_str(), QUERY_MAX_LEN , &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%s, %s]", query.c_str(), sqlite3_errmsg(tac_db));
+ dbClose(tac_db);
+ return false;
+ }
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE && ret != SQLITE_ROW && ret != SQLITE_OK) {
+ _ERR("Sqlite error [%d]", ret);
+ dbFinalize(stmt);
+ dbClose(tac_db);
+ return false;
+ }
+ dbFinalize(stmt);
+ return true;
+}
+
+bool dbInsert(sqlite3 *tac_db, std::string path, std::string query)
+{
+ sqlite3_stmt *stmt = NULL;
+ if (!dbOpen(tac_db, path)) {
+ return false;
+ }
+ int ret = sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
+ ret = sqlite3_prepare(tac_db, query.c_str(), QUERY_MAX_LEN , &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%s,%s]", query.c_str(), sqlite3_errmsg(tac_db));
+ dbClose(tac_db);
+ return false;
+ }
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE && ret != SQLITE_ROW && ret != SQLITE_OK) {
+ _ERR("Sqlite error [%d]", ret);
+ dbFinalize(stmt);
+ dbClose(tac_db);
+ return false;
+ }
+ dbFinalize(stmt);
+ return true;
+}
+
+std::vector<std::string> dbSelect(sqlite3 *tac_db, std::string path, std::string query)
+{
+ std::vector<std::string> updateDB;
+ sqlite3_stmt* stmt = NULL;
+ const char* str = NULL;
+ if (!dbOpen(tac_db, path)) {
+ return updateDB;
+ }
+ int ret = sqlite3_prepare_v2(tac_db, query.c_str(), strlen(query.c_str()), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%s,%s]", query.c_str(), sqlite3_errmsg(tac_db));
+ dbClose(tac_db);
+ return updateDB;
+ }
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ str = (const char *) sqlite3_column_text(stmt, 2);
+ _DBG("Nuget : %s", (!str || !strlen(str)) ? NULL : strdup(str));
+ updateDB.push_back((!str || !strlen(str)) ? NULL : strdup(str));
+ }
+ dbFinalize(stmt);
+ return updateDB;
+}
+
+bool dbDelete(sqlite3 *tac_db, std::string path, std::string query)
+{
+ sqlite3_stmt *stmt = NULL;
+ if (!dbOpen(tac_db, path)) {
+ return false;
+ }
+ int ret = sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
+ ret = sqlite3_prepare(tac_db, query.c_str(), QUERY_MAX_LEN , &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _ERR("Sqlite error : [%s,%s]", query.c_str(), sqlite3_errmsg(tac_db));
+ dbClose(tac_db);
+ return false;
+ }
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE && ret != SQLITE_ROW && ret != SQLITE_OK) {
+ _ERR("Sqlite error [%d]", ret);
+ dbFinalize(stmt);
+ dbClose(tac_db);
+ return false;
+ }
+ dbFinalize(stmt);
+ return true;
+}
*/
#include <dirent.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <strings.h>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <map>
+#include "log.h"
#include "utils.h"
#include "path_manager.h"
return iCompare(fileName, fileName.size()-7, ".ni", 0, 3);
}
+bool cmdOptionExists(char** begin, char** end, const std::string& option)
+{
+ return std::find(begin, end, option) != end;
+}
+
std::string readSelfPath()
{
char buff[PATH_MAX];
return absPath;
}
+int getRootPath(std::string pkgId, std::string& rootPath)
+{
+ int ret = 0;
+ char *path = 0;
+ uid_t uid = 0;
+
+ if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
+ _ERR("Failed to get UID");
+ return -1;
+ }
+
+ pkgmgrinfo_pkginfo_h handle;
+ if (uid == 0) {
+ ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle);
+ if (ret != PMINFO_R_OK) {
+ return -1;
+ }
+ } else {
+ ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle);
+ if (ret != PMINFO_R_OK) {
+ return -1;
+ }
+ }
+
+ ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return -1;
+ }
+ rootPath = path;
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return 0;
+}
+
std::string baseName(const std::string& path)
{
auto pos = path.find_last_of(PATH_SEPARATOR);
struct dirent* entry;
bool isDir;
+ if (strstr(directory.c_str(), ".TAC.Release") != NULL)
+ return; // skip nitool --regen-all-app (--r2r)
+
dir = opendir(directory.c_str());
if (dir == nullptr)
if (depth != 0)
for (auto& d : innerDirectories)
- scanFilesInDir(d.c_str(), reader, depth-1);
+ scanFilesInDir(d.c_str(), reader, depth - 1);
closedir(dir);
}
+static bool setOwnership(const bf::path& path, uid_t uid, gid_t gid) {
+ int fd = open(path.c_str(), O_RDONLY);
+ if (fd < 0) {
+ _ERR("Can't open directory: %s", path.c_str());
+ return false;
+ }
+ int ret = fchown(fd, uid, gid);
+ close(fd);
+ if (ret != 0) {
+ _ERR("Failed to change owner of: %s", path.c_str());
+ return false;
+ }
+ return true;
+}
+
+static bool setDirPermissions(const bf::path& path, bf::perms permissions) {
+ bs::error_code error;
+ bf::permissions(path, permissions, error);
+ if (error) {
+ _ERR("Failed to set permissions for directory: %s, %s", path.c_str(), error.message().c_str());
+ return false;
+ }
+ return true;
+}
+
+static bool setDirOwnershipAndPermissions(const bf::path& path, bf::perms permissions, uid_t uid, gid_t gid) {
+ if (!setOwnership(path, uid, gid)) {
+ _ERR("Failed to change owner: %s, (uid: %d, gid: %d)", path.c_str(), uid, gid);
+ return false;
+ }
+ if (!setDirPermissions(path, permissions)) {
+ _ERR("Failed to change permission: %s, (%d)", path.c_str(), permissions);
+ return false;
+ }
+ return true;
+}
+
+static bool copyOwnershipAndPermissions(const bf::path& path, const bf::path& path2) {
+ if (!bf::exists(path)) {
+ _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str());
+ return false;
+ }
+ bf::perms permissions = bf::status(path).permissions();
+ struct stat stats;
+ if (stat(path.c_str(), &stats) != 0) {
+ return false;
+ }
+ if (!setDirOwnershipAndPermissions(path2, permissions, stats.st_uid, stats.st_gid)) {
+ _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str());
+ return false;
+ }
+ return true;
+}
+
+bool createDir(const bf::path& path) {
+ if (bf::exists(path)) {
+ return true;
+ }
+ bs::error_code error;
+ bf::create_directories(path, error);
+ if (error) {
+ _ERR("Failed to create directory: %s", error.message().c_str());
+ return false;
+ }
+ return true;
+}
+
+bool copyDir(const bf::path& path1, const bf::path& path2, FSFlag flags) {
+ try {
+ // Check whether the function call is valid
+ if (!bf::exists(path1) || !bf::is_directory(path1)) {
+ _ERR("Source directory %s does not exist or is not a directory", path1.c_str());
+ return false;
+ }
+ if (!bf::exists(path2)) {
+ // Create the destination directory
+ if (!createDir(path2)) {
+ _ERR("Unable to create destination directory %s", path2.c_str());
+ return false;
+ }
+ if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) {
+ copyOwnershipAndPermissions(path1, path2);
+ }
+ } else {
+ if (!(flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE))) {
+ _ERR("Destination directory %s already exists", path2.c_str());
+ return false;
+ }
+ if (flags & (FS_MERGE_OVERWRITE | FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS)) {
+ copyOwnershipAndPermissions(path1, path2);
+ }
+ }
+ } catch (const bf::filesystem_error& error) {
+ _ERR("Failed to copy directory: %s", error.what());
+ return false;
+ }
+
+ // Iterate through the source directory
+ for (bf::directory_iterator file(path1); file != bf::directory_iterator(); ++file) {
+ try {
+ bf::path current(file->path());
+ bf::path target = path2 / current.filename();
+ if (bf::is_symlink(symlink_status(current))) {
+ if ((flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE)) && bf::exists(target)) {
+ continue;
+ }
+ bs::error_code error;
+ bf::copy_symlink(current, target, error);
+ if (error) {
+ _ERR("Failed to copy symlink: %s, %s", current.c_str(), error.message().c_str());
+ return false;
+ }
+ } else if (bf::is_directory(current)) {
+ // Found directory: Recursion
+ if (!copyDir(current, target, flags)) {
+ return false;
+ }
+ } else {
+ if ((flags & FS_MERGE_SKIP) && bf::exists(target)) {
+ continue;
+ }
+ bf::path destination = target;
+ if (flags & FS_COMMIT_COPY_FILE) {
+ destination = bf::unique_path(target.parent_path() / "%%%%-%%%%-%%%%-%%%%");
+ }
+ if (flags & FS_MERGE_OVERWRITE) {
+ bf::copy_file(current, destination, bf::copy_option::overwrite_if_exists);
+ } else {
+ bf::copy_file(current, destination);
+ }
+ if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) {
+ copyOwnershipAndPermissions(current, destination);
+ }
+ if (flags & FS_COMMIT_COPY_FILE) {
+ if (flags & FS_MERGE_OVERWRITE) {
+ bf::remove(target);
+ }
+ bf::rename(destination, target);
+ }
+ }
+ } catch (const bf::filesystem_error& error) {
+ _ERR("Failed to copy directory: %s", error.what());
+ return false;
+ }
+ }
+ return true;
+}
+
+bool copyFile(const bf::path& path1, const bf::path& path2) {
+ bs::error_code error;
+ 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());
+ return false;
+ }
+ return true;
+}
+
+bool moveFile(const bf::path& path1, const bf::path& path2) {
+ if (bf::exists(path2)) {
+ return false;
+ }
+ bs::error_code error;
+ bf::rename(path1, path2, error);
+ if (error) {
+ _ERR("Cannot move file: %s. Will copy/remove... with error [%s]", path1.c_str(), error.message().c_str());
+ bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error);
+ if (error) {
+ _ERR("Cannot copy file %s due to error [%s]", path1.c_str(), error.message().c_str());
+ return false;
+ }
+ bf::remove_all(path1, error);
+ if (error) {
+ _ERR("Cannot remove old file when coping: %s with error [%s]", path1.c_str(), error.message().c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+bool removeFile(const bf::path& path) {
+ if (!bf::exists(path)) {
+ return true;
+ }
+ bs::error_code error;
+ bf::remove(path, error);
+ if (error) {
+ _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str());
+ return false;
+ }
+ return true;
+}
+
+bool removeAll(const bf::path& path) {
+ if (!exists(path)) {
+ return true;
+ }
+ bs::error_code error;
+ bf::remove_all(path, error);
+ if (error) {
+ _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str());
+ return false;
+ }
+ return true;
+}
\ No newline at end of file
<request>
<domain name="_"/>
</request>
+ <assign>
+ <filesystem path="/opt/usr/dotnet" label="System::Shared" type="transmutable" />
+ </assign>
</manifest>
Name: dotnet-launcher
Summary: Launchpad plugin for dotnet apps
-Version: 2.1.0
+Version: 3.0.0
Release: 1
Group: Application Framework/Application State Management
License: Apache-2.0
BuildRequires: pkgconfig(libsmack)
BuildRequires: pkgconfig(capi-appfw-app-common)
BuildRequires: pkgconfig(storage)
+BuildRequires: pkgconfig(jsoncpp)
+BuildRequires: pkgconfig(openssl)
+BuildRequires: sqlite-devel
+BuildRequires: boost-devel
BuildRequires: aul-devel
BuildRequires: dotnet-build-tools
%define _framework_dir /usr/share/dotnet.tizen/framework
%define _install_mdplugin_dir /etc/package-manager/parserlib/metadata
%define _native_lib_dir /usr/share/dotnet.tizen/lib
+%define _tac_dir /opt/usr/dotnet
ExcludeArch: aarch64
-DRUNTIME_DIR=%{_runtime_dir} \
-DCROSSGEN_PATH=%{_runtime_dir}/crossgen \
-DINSTALL_MDPLUGIN_DIR=%{_install_mdplugin_dir} \
+ -DTAC_DIR=%{_tac_dir} \
-DVERSION=%{version} \
-DNATIVE_LIB_DIR=%{_native_lib_dir} \
NativeLauncher
mv Init/bin/Release/Tizen.Init.dll %{buildroot}%{_framework_dir}
+mkdir -p %{buildroot}%{_tac_dir}
mkdir -p %{buildroot}%{_native_lib_dir}
ln -sf %{_libdir}/libsqlite3.so.0 %{buildroot}%{_native_lib_dir}/libsqlite3.so
%{_native_lib_dir}/libsqlite3.so
%{_bindir}/nitool
%{_bindir}/tpatool
+%{_bindir}/tactool
+%{_install_mdplugin_dir}/libprefer_nuget_cache_plugin.so
%{_install_mdplugin_dir}/libprefer_dotnet_aot_plugin.so
%{_bindir}/dotnet-launcher
%{_libdir}/libdotnet_launcher_util.so
%{_libdir}/libni_common.so
/etc/tmpfiles.d/%{name}.conf
+/usr/share/parser-plugins/dotnet-launcher.info
%{_framework_dir}/Tizen.Init.dll
%files devel