diff options
author | pius.lee <pius.lee@samsung.com> | 2016-11-10 20:26:43 +0900 |
---|---|---|
committer | pius.lee <pius.lee@samsung.com> | 2016-11-11 20:08:33 +0900 |
commit | 8cd6fb2c60ac74259fdce9615836949e9d0ef7fc (patch) | |
tree | d5415eed68a71cb7da9e9f85b1ddbfa731075f59 | |
parent | 419ec3b9aa7b2bf3ebc39d1c38ba27823acf357a (diff) | |
download | launcher-8cd6fb2c60ac74259fdce9615836949e9d0ef7fc.tar.gz launcher-8cd6fb2c60ac74259fdce9615836949e9d0ef7fc.tar.bz2 launcher-8cd6fb2c60ac74259fdce9615836949e9d0ef7fc.zip |
Add installer plugin and tool for create a NI
nitool : native image maker for system dlls and apps
libui-application.so : native image creating plugin for app installer
Fix bug on getting trusted platform dll.
Change-Id: Ie0b18c9fcca2fa0b814d4056d87c2e5d67e4e0e4
-rw-r--r-- | NativeLauncher/CMakeLists.txt | 55 | ||||
-rw-r--r-- | NativeLauncher/inc/utils.h | 8 | ||||
-rw-r--r-- | NativeLauncher/installer-plugin/common.cc | 292 | ||||
-rw-r--r-- | NativeLauncher/installer-plugin/common.h | 13 | ||||
-rw-r--r-- | NativeLauncher/installer-plugin/nitool.cc | 93 | ||||
-rw-r--r-- | NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h | 21 | ||||
-rw-r--r-- | NativeLauncher/installer-plugin/ui-application.cc | 96 | ||||
-rw-r--r-- | NativeLauncher/launcher/dotnet/dotnet_launcher.cc (renamed from NativeLauncher/src/dotnet/dotnet_launcher.cc) | 10 | ||||
-rw-r--r-- | NativeLauncher/launcher/dotnet/dotnet_launcher.h (renamed from NativeLauncher/src/dotnet/dotnet_launcher.h) | 0 | ||||
-rw-r--r-- | NativeLauncher/launcher/launcher.cc (renamed from NativeLauncher/src/launcher.cc) | 0 | ||||
-rw-r--r-- | NativeLauncher/launcher/launcher.h (renamed from NativeLauncher/inc/launcher.h) | 0 | ||||
-rw-r--r-- | NativeLauncher/launcher/main.cc (renamed from NativeLauncher/src/main.cc) | 26 | ||||
-rw-r--r-- | NativeLauncher/launcher/mono/mono_launcher.cc (renamed from NativeLauncher/src/mono/mono_launcher.cc) | 2 | ||||
-rw-r--r-- | NativeLauncher/launcher/mono/mono_launcher.h (renamed from NativeLauncher/src/mono/mono_launcher.h) | 0 | ||||
-rw-r--r-- | NativeLauncher/launcher/waiter/waiter.cc (renamed from NativeLauncher/src/waiter/waiter.cc) | 0 | ||||
-rw-r--r-- | NativeLauncher/launcher/waiter/waiter.h (renamed from NativeLauncher/src/waiter/waiter.h) | 0 | ||||
-rw-r--r-- | NativeLauncher/util/utils.cc (renamed from NativeLauncher/src/utils.cc) | 172 | ||||
-rw-r--r-- | packaging/dotnet-launcher.spec | 7 |
18 files changed, 736 insertions, 59 deletions
diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index 0647e2a..cd273e1 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -1,5 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT("dotnet-launcher") +PROJECT("dotnet-tools") MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") @@ -7,7 +7,7 @@ IF(DEFINED NO_TIZEN) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNO_TIZEN") ELSE(DEFINED NO_TIZEN) INCLUDE(FindPkgConfig) - PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul dlog ecore bundle dlog launchpad) + PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul pkgmgr-info pkgmgr-installer dlog ecore bundle dlog launchpad) ENDIF(DEFINED NO_TIZEN) FOREACH(flag ${${PROJECT_NAME}_CFLAGS}) @@ -34,6 +34,10 @@ IF(DEFINED RUNTIME_DIR) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DRUNTIME_DIR=${RUNTIME_DIR}") ENDIF(DEFINED RUNTIME_DIR) +IF(DEFINED CROSSGEN_PATH) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DCROSSGEN_PATH=${CROSSGEN_PATH}") +ENDIF(DEFINED CROSSGEN_PATH) + IF(DEFINED VERSION) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DVERSION=${VERSION}") ENDIF(DEFINED VERSION) @@ -41,7 +45,7 @@ ENDIF(DEFINED VERSION) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -pthread -std=c++11 -Wl,--no-as-needed -ggdb") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" ) #SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE") +#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64") #SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHING_TIME_MEASURE") @@ -51,19 +55,20 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_RELEASE "-O2") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") -INCLUDE_DIRECTORIES(inc) +#SET(${PROJECT_NAME}_LDFLAGS ${${PROJECT_NAME}_LDFLAGS} "-pie") -SET(DOTNET_LAUNCHER "dotnet-launcher") -SET(MONO_LAUNCHER "mono-launcher") +INCLUDE_DIRECTORIES(inc launcher util) +SET(DOTNET_LAUNCHER "dotnet-launcher") SET(${DOTNET_LAUNCHER}_SOURCE_FILES - src/main.cc - src/utils.cc - src/launcher.cc - src/dotnet/dotnet_launcher.cc - src/mono/mono_launcher.cc + launcher/main.cc + util/utils.cc + launcher/launcher.cc + launcher/dotnet/dotnet_launcher.cc + launcher/mono/mono_launcher.cc ) -ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_SOURCE_FILES}) +ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${DOTNET_LAUNCHER}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES COMPILE_FLAGS "-fPIE") IF(NOT DEFINED NO_TIZEN) TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} aul) @@ -72,11 +77,33 @@ TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl - SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER} PROPERTIES SKIP_BUILD_RPATH TRUE - ) # remove rpath option that is automatically generated by cmake. +) # remove rpath option that is automatically generated by cmake. + +SET(NITOOL "nitool") +SET(${NITOOL}_SOURCE_FILES + util/utils.cc + installer-plugin/common.cc + installer-plugin/nitool.cc +) +ADD_EXECUTABLE(${NITOOL} ${${NITOOL}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${NITOOL} PROPERTIES COMPILE_FLAGS "-fPIE") +TARGET_LINK_LIBRARIES(${NITOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie") + +SET(INSTALLER_PLUGIN "ui-application") +SET(${INSTALLER_PLUGIN}_SOURCE_FILES + util/utils.cc + installer-plugin/common.cc + installer-plugin/ui-application.cc +) +ADD_LIBRARY(${INSTALLER_PLUGIN} SHARED ${${INSTALLER_PLUGIN}_SOURCE_FILES}) +SET_TARGET_PROPERTIES(${INSTALLER_PLUGIN} PROPERTIES COMPILE_FLAGS "-fPIC") +TARGET_LINK_LIBRARIES(${INSTALLER_PLUGIN} ${${PROJECT_NAME}_LDFLAGS}) IF(NOT DEFINED NO_TIZEN) INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR}) + INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR}) + INSTALL(TARGETS ${INSTALLER_PLUGIN} DESTINATION ${INSTALL_PLUGIN_DIR}) INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR}) INSTALL(FILES dotnet.launcher DESTINATION ${LOADERDIR}) - INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR}) + INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR}) ENDIF(NOT DEFINED NO_TIZEN) diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index 145a43d..ed993fa 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -3,11 +3,16 @@ #include <string> #include <vector> +#include <functional> #ifndef PATH_SEPARATOR #define PATH_SEPARATOR '/' #endif +bool ICompare(const std::string& a, const std::string& b); +bool ICompare(const std::string& a, int a_offset, const std::string& b, int b_offset, int length); +bool IsManagedAssembly(const std::string& filename); +bool IsNativeImage(const std::string& filename); std::string ReadSelfPath (); std::string ConcatPath (const std::string& path1, const std::string& path2); void AppendPath (std::string& path1, const std::string& path2); @@ -18,4 +23,7 @@ void AssembliesInDirectory(const std::vector<std::string>& directories, std::str bool FileNotExist(const std::string& path); std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter); +typedef std::function<void (const char*)> FileReader; +void ScanFilesInDir(const char* directory, FileReader reader, unsigned int depth); + #endif // __UTILS_H__ diff --git a/NativeLauncher/installer-plugin/common.cc b/NativeLauncher/installer-plugin/common.cc new file mode 100644 index 0000000..70b963f --- /dev/null +++ b/NativeLauncher/installer-plugin/common.cc @@ -0,0 +1,292 @@ +#include <pkgmgr-info.h> +#include <pkgmgr_installer_info.h> +#include <aul.h> + +#include "log.h" +#include "utils.h" +#include "pkgmgr_parser_plugin_interface.h" + +#include <wait.h> +#include <dirent.h> +#include <sys/stat.h> + +#include <algorithm> +#include <string> + +#include "common.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "NETCORE_INSTALLER_PLUGIN" + +#ifndef DEVICE_API_DIR +#error "DEVICE_API_DIR is missed" +#endif + +#ifndef RUNTIME_DIR +#error "RUNTIME_DIR is missed" +#endif + +#ifndef CROSSGEN_PATH +#error "CROSSGEN_PATH is missed" +#endif + +#define __XSTR(x) #x +#define __STR(x) __XSTR(x) +static const char* DeviceAPIDir = __STR(DEVICE_API_DIR); +static const char* RuntimeDir = __STR(RUNTIME_DIR); +static const char* CrossgenPath = __STR(CROSSGEN_PATH); +static const char* JITPath = __STR(RUNTIME_DIR)"/libclrjit.so"; +#undef __STR +#undef __XSTR + +static void crossgen(const char* dll_path, const char* app_path); +static void smack_(const char* dll_path); + +void create_ni_platform() +{ + std::string corlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.dll"); + std::string nicorlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.ni.dll"); + + if (FileNotExist(nicorlib)) + { + crossgen(corlib.c_str(), nullptr); + smack_(nicorlib.c_str()); + } + + const char* platform_dirs[] = {RuntimeDir, DeviceAPIDir}; + const char* ignores[] = {corlib.c_str()}; + + create_ni_under_dirs(platform_dirs, 2, ignores, 1, [](const char* ni){ + smack_(ni); + }); +} + +static void smack_(const char* dll_path) +{ + static const char* CHKSMACK = "/usr/bin/chsmack"; + pid_t pid = fork(); + if (pid == -1) + { + return; + } + + if (pid > 0) + { + int status; + waitpid(pid, &status, 0); + if (WIFEXITED(status)) + { + return; + } + } + else + { + const char* args[] = { + CHKSMACK, + "-a", "_", + dll_path, + nullptr + }; + for (const char* arg : args) + { + printf("%s ", arg); + } + printf("\n"); + + execv(CHKSMACK, const_cast<char*const*>(args)); + + exit(0); + } +} + +static void crossgen(const char* dll_path, const char* app_path) +{ + //pid_t parent = getpid(); + pid_t pid = fork(); + if (pid == -1) + { + return; + } + + if (pid > 0) + { + int status; + waitpid(pid, &status, 0); + if (WIFEXITED(status)) + { + return; + } + } + else + { + std::vector<std::string> tpaDir = { + RuntimeDir, DeviceAPIDir + }; + std::string tpa; + AssembliesInDirectory(tpaDir, tpa); + + std::vector<const char*> argv = + { + CrossgenPath, + "/Trusted_Platform_Assemblies", tpa.c_str(), + "/JITPath", JITPath, + "/FragileNonVersionable" + }; + if (app_path != nullptr) + { + argv.push_back("/App_Paths"); + argv.push_back(app_path); + } + argv.push_back(dll_path); + argv.push_back(nullptr); + + /* + for (const char* arg : argv) + { + printf("%s ", arg); + } + printf("\n"); + */ + printf("+ %s\n", dll_path); + + execv(CrossgenPath, const_cast<char* const*>(argv.data())); + exit(0); + } +} + +static int get_root_path(const char *pkgid, std::string& root_path) +{ + 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; + } + + _INFO("user id is %d", uid); + + pkgmgrinfo_pkginfo_h handle; + if (uid == 0) + { + ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle); + if (ret != PMINFO_R_OK) + return -1; + } + else + { + ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, 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; + } + root_path = path; + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + + return 0; +} + +static bool NIExist(const std::string& path, std::string& ni) +{ + static const char* possible_exts[] = { + ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL" + }; + std::string fname = path.substr(0, path.size() - 4); + + struct stat sb; + + for (const char* ext : possible_exts) + { + std::string f = fname + ext; + if (stat(f.c_str(), &sb) == 0) + { + ni = f; + return true; + } + } + + return false; +} + +void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb) +{ + std::string app_paths; + for (int i=0; i<count; i++) + { + app_paths += root_paths[i]; + app_paths += ':'; + } + if (app_paths.back() == ':') + app_paths.pop_back(); + + auto convert = [&app_paths, ignores, igcount, &cb](const char* path) + { + for (int i=0; i<igcount; i++) + { + if (strcmp(path, ignores[i]) == 0) + return; + } + std::string ni; + if (IsManagedAssembly(path) && !IsNativeImage(path) && !NIExist(path, ni)) + { + crossgen(path, app_paths.c_str()); + if (NIExist(path, ni)) + { + if (cb != nullptr) + { + cb(ni.c_str()); + } + } + } + }; + + for (int i=0; i<count; i++) + { + ScanFilesInDir(root_paths[i], convert, -1); + } +} +void create_ni_under_dirs(const char* root_paths[], int count, after_create cb) +{ + create_ni_under_dirs(root_paths, count, nullptr, 0, cb); +} +void create_ni_under_dirs(const char* root_paths[], int count) +{ + create_ni_under_dirs(root_paths, count, nullptr); +} + +int create_ni_under_pkg_root(const char* pkg_name) +{ + std::string pkgroot; + if (get_root_path(pkg_name, pkgroot) < 0) + { + return 1; + } + + //printf("pkgroot : %s\n", pkgroot.c_str()); + + std::string bindir = ConcatPath(pkgroot, "bin"); + std::string libdir = ConcatPath(pkgroot, "lib"); + + //printf("bindir : %s\n", bindir.c_str()); + //printf("libdir : %s\n", libdir.c_str()); + _INFO("bindir : %s", bindir.c_str()); + _INFO("libdir : %s", libdir.c_str()); + + const char* paths[] = { + bindir.c_str(), + libdir.c_str() + }; + create_ni_under_dirs(paths, 2); + + return 0; +} diff --git a/NativeLauncher/installer-plugin/common.h b/NativeLauncher/installer-plugin/common.h new file mode 100644 index 0000000..39f4381 --- /dev/null +++ b/NativeLauncher/installer-plugin/common.h @@ -0,0 +1,13 @@ +#ifndef __INSTALLER_PLUGIN_COMMON_H__ +#define __INSTALLER_PLUGIN_COMMON_H__ + +#include <functional> + +typedef std::function<void (const char*)> after_create; +void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb); +void create_ni_under_dirs(const char* root_paths[], int count, after_create cb); +void create_ni_under_dirs(const char* root_paths[], int count); +int create_ni_under_pkg_root(const char* pkg_name); +void create_ni_platform(); + +#endif // __INSTALLER_PLUGIN_COMMON_H__ diff --git a/NativeLauncher/installer-plugin/nitool.cc b/NativeLauncher/installer-plugin/nitool.cc new file mode 100644 index 0000000..1fd4c8f --- /dev/null +++ b/NativeLauncher/installer-plugin/nitool.cc @@ -0,0 +1,93 @@ +#include "common.h" + +#include <cstdio> +#include <cstring> + +#include <algorithm> + +std::vector<const char*> get_cmd_args(char** begin, char** end) +{ + for (char** itr = end-1; itr != begin-1; --itr) + { + if (itr != end && strncmp(*itr, "--", 2) == 0) + { + itr++; + int len = end - itr; + return std::vector<const char*>(len, *itr); + } + } + return std::vector<const char*>(end-begin-1, *(begin+1)); +} + +bool cmd_option_exists(char** begin, char** end, const std::string& option) +{ + return std::find(begin, end, option) != end; +} + +static void help(const char *argv0) +{ + const char* helpdesc = + "Usage: %s [args] <root paths or pkg name>\n" + " --help - Display this screen\n" + " --system - Create NI under System DLLs\n" + " --pkg - Create NI for package\n" + "\n" + "Example:\n" + "Create native image for dlls and exes under platform directories\n" + "%s --system\n" + "Create native image under the package's bin and lib directory\n" + "%s --pkg org.tizen.FormsGallery\n\n"; + printf(helpdesc, argv0, argv0, argv0); +} + +int main(int argc, char* argv[]) +{ + bool pkg_mode = false; + + if (cmd_option_exists(argv, argv+argc, "--help")) + { + help(argv[0]); + return 0; + } + + if (cmd_option_exists(argv, argv+argc, "--system")) + { + create_ni_platform(); + return 0; + } + + if (cmd_option_exists(argv, argv+argc, "--pkg")) + { + pkg_mode = true; + } + + std::vector<const char*> args = get_cmd_args(argv, argv+argc); + + if (args.size() < 1) + { + if (pkg_mode) + fprintf(stderr, "Package name is missed\n"); + else + fprintf(stderr, "DLL path is missed\n"); + help(argv[0]); + return 1; + } + + if (pkg_mode) + { + for (const char* pkg : args) + { + if (create_ni_under_pkg_root(pkg) != 0) + { + fprintf(stderr, "Failed to get root path from [%s]\n", pkg); + return 1; + } + } + } + else + { + create_ni_under_dirs(args.data(), args.size()); + } + + return 0; +} diff --git a/NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h b/NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h new file mode 100644 index 0000000..0f2d4a8 --- /dev/null +++ b/NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h @@ -0,0 +1,21 @@ +#ifndef __PKGMGR_PARSER_PLUGIN_INTERFACE__ +#define __PKGMGR_PARSER_PLUGIN_INTERFACE__ + +extern "C" +{ + typedef struct _xmlDoc xmlDoc; + typedef xmlDoc* xmlDocPtr; + int PKGMGR_PARSER_PLUGIN_PRE_INSTALL (const char *pkgid); + int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE (const char *pkgid); + int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL (const char *pkgid); + + 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_POST_INSTALL (const char *pkgid); + int PKGMGR_PARSER_PLUGIN_POST_UPGRADE (const char *pkgid); + int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL (const char *pkgid); +} + +#endif // __PKGMGR_PARSER_PLUGIN_INTERFACE__ diff --git a/NativeLauncher/installer-plugin/ui-application.cc b/NativeLauncher/installer-plugin/ui-application.cc new file mode 100644 index 0000000..c0196e3 --- /dev/null +++ b/NativeLauncher/installer-plugin/ui-application.cc @@ -0,0 +1,96 @@ +#include "common.h" +#include "log.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "NETCORE_INSTALLER_PLUGIN" + +#include <cstring> +#include <pkgmgr-info.h> +#include <pkgmgr_installer_info.h> + +/* + * forked crossgen from installer is not working. + * because crossgen's capability is not enough. + * following command is needed + * + * setcap cap_dac_override=eip /opt/usr/share/dotnet.tizen/framework/crossgen + * + */ + +extern "C" int PKGMGR_PARSER_PLUGIN_POST_INSTALL (const char *pkgid) +{ + _INFO("pkg : %s", 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, uid, &handle); + if (ret != PMINFO_R_OK) + { + _ERR("Failed to get pkg info"); + return 0; + } + + _INFO("success to get pkg info"); + + bool dotnet_exist = false; + + auto dotnet_app_counter = [] (pkgmgrinfo_appinfo_h handle, void *user_data) -> int + { + char* appid = nullptr; + char* type = nullptr; + bool* dotnet = static_cast<bool*>(user_data); + + if (pkgmgrinfo_appinfo_get_appid(handle, &appid) != PMINFO_R_OK) + { + _ERR("Failed to get app id"); + return 0; + } + + _INFO("App id : %s", appid); + + if (pkgmgrinfo_appinfo_get_apptype(handle, &type) != PMINFO_R_OK) + { + _ERR("Failed to get app type : %s", appid); + return 0; + } + + _INFO("App type : %s", type); + + if (strcmp(type, "dotnet") == 0) + { + *dotnet = true; + } + + return 0; + }; + + if (pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, dotnet_app_counter, &dotnet_exist, uid) != PMINFO_R_OK) + { + _ERR("Failed to get list of app in pkg : %s", pkgid); + return -1; + } + + _INFO("Finish to get pkg list"); + + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + if (dotnet_exist) + { + _INFO("dotnet app is exist"); + return create_ni_under_pkg_root(pkgid) == 0 ? 0 : -1; + } + + return 0; +} +extern "C" int PKGMGR_PARSER_PLUGIN_POST_UPGRADE (const char *pkgid) +{ + return PKGMGR_PARSER_PLUGIN_POST_INSTALL(pkgid); +} diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc index ce880a9..1bfbdec 100644 --- a/NativeLauncher/src/dotnet/dotnet_launcher.cc +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc @@ -15,15 +15,15 @@ namespace runtime { namespace dotnetcore { CoreRuntime::CoreRuntime() : + InitializeClr(nullptr), + ExecuteAssembly(nullptr), + Shutdown(nullptr), + CreateDelegate(nullptr), coreclrLib(nullptr), hostHandle(nullptr), domainId(-1), PreparedFunction(nullptr), - LaunchFunction(nullptr), - InitializeClr(nullptr), - ExecuteAssembly(nullptr), - Shutdown(nullptr), - CreateDelegate(nullptr) + LaunchFunction(nullptr) { #define __XSTR(x) #x #define __STR(x) __XSTR(x) diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.h b/NativeLauncher/launcher/dotnet/dotnet_launcher.h index fa72e11..fa72e11 100644 --- a/NativeLauncher/src/dotnet/dotnet_launcher.h +++ b/NativeLauncher/launcher/dotnet/dotnet_launcher.h diff --git a/NativeLauncher/src/launcher.cc b/NativeLauncher/launcher/launcher.cc index 9efd49e..9efd49e 100644 --- a/NativeLauncher/src/launcher.cc +++ b/NativeLauncher/launcher/launcher.cc diff --git a/NativeLauncher/inc/launcher.h b/NativeLauncher/launcher/launcher.h index 399bef5..399bef5 100644 --- a/NativeLauncher/inc/launcher.h +++ b/NativeLauncher/launcher/launcher.h diff --git a/NativeLauncher/src/main.cc b/NativeLauncher/launcher/main.cc index 18085b7..c43c299 100644 --- a/NativeLauncher/src/main.cc +++ b/NativeLauncher/launcher/main.cc @@ -114,23 +114,25 @@ int main(int argc, char *argv[]) } else { - Launchpad.OnCreate = [&runtime] + Launchpad.OnCreate = [&runtime]() { - auto idle_task = [](void *data) -> Eina_Bool - { - LauncherInterface* runtime = static_cast<LauncherInterface*>(data); - if (runtime->RunManagedLauncher() != 0) - { - _ERR("Failed to run managed launcher"); - } - return ECORE_CALLBACK_CANCEL; - }; if (runtime->Initialize(false) != 0) { _ERR("Failed to initialized"); - return 1; } - ecore_idler_add(idle_task, runtime.get()); + else + { + auto idle_task = [](void *data) -> Eina_Bool + { + LauncherInterface* runtime = static_cast<LauncherInterface*>(data); + if (runtime->RunManagedLauncher() != 0) + { + _ERR("Failed to run managed launcher"); + } + return ECORE_CALLBACK_CANCEL; + }; + ecore_idler_add(idle_task, runtime.get()); + } }; Launchpad.OnTerminate = [&runtime](const AppInfo& info, int argc, char** argv) diff --git a/NativeLauncher/src/mono/mono_launcher.cc b/NativeLauncher/launcher/mono/mono_launcher.cc index 8636447..e0d0156 100644 --- a/NativeLauncher/src/mono/mono_launcher.cc +++ b/NativeLauncher/launcher/mono/mono_launcher.cc @@ -238,7 +238,7 @@ int MonoRuntime::Launch(const char* root, const char* path, int argc, char* argv _ERR("Failed to open assembly : %s", path); return 1; } - int ret = AssemblyExec(domain, app, argc, argv); + AssemblyExec(domain, app, argc, argv); } return 0; } diff --git a/NativeLauncher/src/mono/mono_launcher.h b/NativeLauncher/launcher/mono/mono_launcher.h index d705d9e..d705d9e 100644 --- a/NativeLauncher/src/mono/mono_launcher.h +++ b/NativeLauncher/launcher/mono/mono_launcher.h diff --git a/NativeLauncher/src/waiter/waiter.cc b/NativeLauncher/launcher/waiter/waiter.cc index 6447d4a..6447d4a 100644 --- a/NativeLauncher/src/waiter/waiter.cc +++ b/NativeLauncher/launcher/waiter/waiter.cc diff --git a/NativeLauncher/src/waiter/waiter.h b/NativeLauncher/launcher/waiter/waiter.h index c4b98fb..c4b98fb 100644 --- a/NativeLauncher/src/waiter/waiter.h +++ b/NativeLauncher/launcher/waiter/waiter.h diff --git a/NativeLauncher/src/utils.cc b/NativeLauncher/util/utils.cc index 776fd9f..2cc1026 100644 --- a/NativeLauncher/src/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -8,13 +8,41 @@ #include <cstdlib> #include <cstring> #include <algorithm> -#include <set> +#include <unordered_map> #include <vector> #include <iterator> #include <sstream> #include "utils.h" +bool ICompare(const std::string& a, const std::string& b) +{ + return a.length() == b.length() && + std::equal(b.begin(), b.end(), a.begin(), + [](unsigned char a, unsigned char b) + { return std::tolower(a) == std::tolower(b); }); +} + +bool ICompare(const std::string& a, int a_offset, const std::string& b, int b_offset, int length) +{ + return static_cast<int>(a.length()) - length >= a_offset && + static_cast<int>(b.length()) - length >= b_offset && + std::equal(b.begin() + b_offset, b.begin() + b_offset + length, a.begin() + a_offset, + [](unsigned char a, unsigned char b) + { return std::tolower(a) == std::tolower(b); }); +} + +bool IsManagedAssembly(const std::string& filename) +{ + return ICompare(filename, filename.size()-4, ".dll", 0, 4) || + ICompare(filename, filename.size()-4, ".exe", 0, 4); +} + +bool IsNativeImage(const std::string& filename) +{ + return ICompare(filename, filename.size()-7, ".ni", 0, 3); +} + std::string ReadSelfPath() { char buff[PATH_MAX]; @@ -104,7 +132,7 @@ bool EndWithIgnoreCase(const std::string& str1, const std::string& str2, std::st bool FileNotExist(const std::string& path) { struct stat sb; - return (stat(path.c_str(), &sb) != 0) || !S_ISREG(sb.st_mode); + return stat(path.c_str(), &sb) != 0; } static bool ExtCheckAndGetFileNameIfExist(const std::string& dir, const std::string& ext, struct dirent* entry, std::string& filename) @@ -168,44 +196,134 @@ std::string JoinStrings(const std::vector<std::string>& strings, const char* con } } -void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList) +struct AssemblyFile { - static const std::string tpaExtensions[] = - {".ni.dll", ".dll", ".ni.exe", ".exe"}; + std::string noext; + std::string ext; +}; - std::set<std::string> addedAssemblies; - - DIR* dir = nullptr; - struct dirent* entry = nullptr; +bool operator == (const AssemblyFile& lhs, const AssemblyFile& rhs) +{ + return lhs.noext == rhs.noext && lhs.ext == rhs.ext; +} - for (auto directory : directories) +namespace std +{ + template<> + struct hash<AssemblyFile> { - dir = opendir(directory.c_str()); - if (dir == nullptr) + std::size_t operator () (const AssemblyFile& f) const { - continue; + const std::size_t h1 = std::hash<std::string>{}(f.noext); + const std::size_t h2 = std::hash<std::string>{}(f.ext); + + return h1 ^ (h2 << 1); } + }; +} + +void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList) +{ + std::unordered_map<AssemblyFile, bool> addedAssemblies; + + auto reader = [&addedAssemblies] (const char* path) + { + std::string _path(path); - for (auto ext : tpaExtensions) + std::string::size_type dotp = _path.rfind('.'); + std::string ext = dotp != std::string::npos ? _path.substr(dotp) : ""; + std::string noext; + bool ni = false; + + if (IsManagedAssembly(_path)) { - while ((entry = readdir(dir)) != nullptr) + if (IsNativeImage(_path)) { - std::string fullname; - if (ExtCheckAndGetFileNameIfExist(directory.c_str(), ext, entry, fullname)) - { - std::string filename = StripNIDLL(fullname); - if (addedAssemblies.find(filename) == addedAssemblies.end()) - { - addedAssemblies.insert(filename); - tpaList += fullname + ':'; - } - } + noext = _path.substr(0, _path.size()-7); + ni = true; + } + else + { + noext = _path.substr(0, _path.size()-4); } - rewinddir(dir); + + AssemblyFile f = {noext, ext}; + addedAssemblies[f] = ni; } - closedir(dir); + }; + + for (auto directory : directories) + { + ScanFilesInDir(directory.c_str(), reader, 1); + } + + for (auto kv : addedAssemblies) + { + tpaList += kv.first.noext + (kv.second ? ".ni" : "") + kv.first.ext + ':'; } + if (tpaList.back() == ':') tpaList.pop_back(); +} + +void ScanFilesInDir(const char* directory, FileReader reader, unsigned int depth) +{ + DIR *dir; + struct dirent* entry; + bool isDir; + + dir = opendir(directory); + + if (dir == nullptr) + { + //_ERR("Can not open directory : %s", directory); + return; + } + + std::vector<std::string> innerDirectories; + + while ((entry = readdir(dir)) != nullptr) + { + isDir = false; + std::string path = ConcatPath(directory, entry->d_name); + switch (entry->d_type) + { + case DT_REG: break; + case DT_DIR: + isDir = true; + break; + case DT_LNK: + case DT_UNKNOWN: + struct stat sb; + if (stat(path.c_str(), &sb) == -1) + { + continue; + } + + if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode)) + { + break; + } + default: + continue; + } + if (!isDir) + { + reader(path.c_str()); + } + else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) + { + innerDirectories.push_back(path); + } + } + + if (depth != 0) + { + for (auto& d : innerDirectories) + { + ScanFilesInDir(d.c_str(), reader, depth-1); + } + } + closedir(dir); } diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index fa0bb60..1050527 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -15,6 +15,8 @@ BuildRequires: pkgconfig(bundle) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(ecore) BuildRequires: pkgconfig(launchpad) +BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(pkgmgr-installer) BuildRequires: aul-devel BuildRequires: mono-compiler BuildRequires: mono-devel @@ -33,6 +35,7 @@ Requires(preun): /usr/bin/systemctl %define _device_api_dir %{dotnet_assembly_path} %define _runtime_dir /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0 %define _preload_dir /opt/usr/share/dotnet.tizen/preload +%define _install_plugin_dir /usr/etc/package-manager/parserlib %description Launchpad plugin for launching dotnet apps @@ -56,8 +59,10 @@ cmake \ -DCMAKE_BUILD_TYPE=%{_buildmode} \ -DDEVICE_API_DIR=%{_device_api_dir} \ -DRUNTIME_DIR=%{_runtime_dir} \ + -DCROSSGEN_PATH=%{_device_api_dir}/crossgen \ -DCORECLR_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Coreclr.dll \ -DMONO_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Mono.dll \ + -DINSTALL_PLUGIN_DIR=%{_install_plugin_dir} \ -DVERSION=%{version} \ NativeLauncher @@ -89,5 +94,7 @@ install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.Mono.dll %{buildroot}%{_bindir %{_loaderdir}/dotnet.launcher %{_loaderdir}/dotnet.debugger %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher +%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/nitool +%caps(cap_mac_admin,cap_setgid=ei) %{_install_plugin_dir}/libui-application.so %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Coreclr.dll %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Mono.dll |