summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpius.lee <pius.lee@samsung.com>2016-11-10 20:26:43 +0900
committerpius.lee <pius.lee@samsung.com>2016-11-11 20:08:33 +0900
commit8cd6fb2c60ac74259fdce9615836949e9d0ef7fc (patch)
treed5415eed68a71cb7da9e9f85b1ddbfa731075f59
parent419ec3b9aa7b2bf3ebc39d1c38ba27823acf357a (diff)
downloadlauncher-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.txt55
-rw-r--r--NativeLauncher/inc/utils.h8
-rw-r--r--NativeLauncher/installer-plugin/common.cc292
-rw-r--r--NativeLauncher/installer-plugin/common.h13
-rw-r--r--NativeLauncher/installer-plugin/nitool.cc93
-rw-r--r--NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h21
-rw-r--r--NativeLauncher/installer-plugin/ui-application.cc96
-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.spec7
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