Add installer plugin and tool for create a NI
authorpius.lee <pius.lee@samsung.com>
Thu, 10 Nov 2016 11:26:43 +0000 (20:26 +0900)
committerpius.lee <pius.lee@samsung.com>
Fri, 11 Nov 2016 11:08:33 +0000 (20:08 +0900)
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

18 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/inc/utils.h
NativeLauncher/installer-plugin/common.cc [new file with mode: 0644]
NativeLauncher/installer-plugin/common.h [new file with mode: 0644]
NativeLauncher/installer-plugin/nitool.cc [new file with mode: 0644]
NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h [new file with mode: 0644]
NativeLauncher/installer-plugin/ui-application.cc [new file with mode: 0644]
NativeLauncher/launcher/dotnet/dotnet_launcher.cc [moved from NativeLauncher/src/dotnet/dotnet_launcher.cc with 99% similarity]
NativeLauncher/launcher/dotnet/dotnet_launcher.h [moved from NativeLauncher/src/dotnet/dotnet_launcher.h with 100% similarity]
NativeLauncher/launcher/launcher.cc [moved from NativeLauncher/src/launcher.cc with 100% similarity]
NativeLauncher/launcher/launcher.h [moved from NativeLauncher/inc/launcher.h with 100% similarity]
NativeLauncher/launcher/main.cc [moved from NativeLauncher/src/main.cc with 88% similarity]
NativeLauncher/launcher/mono/mono_launcher.cc [moved from NativeLauncher/src/mono/mono_launcher.cc with 99% similarity]
NativeLauncher/launcher/mono/mono_launcher.h [moved from NativeLauncher/src/mono/mono_launcher.h with 100% similarity]
NativeLauncher/launcher/waiter/waiter.cc [moved from NativeLauncher/src/waiter/waiter.cc with 100% similarity]
NativeLauncher/launcher/waiter/waiter.h [moved from NativeLauncher/src/waiter/waiter.h with 100% similarity]
NativeLauncher/util/utils.cc [moved from NativeLauncher/src/utils.cc with 51% similarity]
packaging/dotnet-launcher.spec

index 0647e2a..cd273e1 100644 (file)
@@ -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)
index 145a43d..ed993fa 100644 (file)
@@ -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 (file)
index 0000000..70b963f
--- /dev/null
@@ -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 (file)
index 0000000..39f4381
--- /dev/null
@@ -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 (file)
index 0000000..1fd4c8f
--- /dev/null
@@ -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 (file)
index 0000000..0f2d4a8
--- /dev/null
@@ -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 (file)
index 0000000..c0196e3
--- /dev/null
@@ -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);
+}
@@ -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)
similarity index 88%
rename from NativeLauncher/src/main.cc
rename to NativeLauncher/launcher/main.cc
index 18085b7..c43c299 100644 (file)
@@ -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)
similarity index 99%
rename from NativeLauncher/src/mono/mono_launcher.cc
rename to NativeLauncher/launcher/mono/mono_launcher.cc
index 8636447..e0d0156 100644 (file)
@@ -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;
 }
similarity index 51%
rename from NativeLauncher/src/utils.cc
rename to NativeLauncher/util/utils.cc
index 776fd9f..2cc1026 100644 (file)
@@ -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);
 }
index fa0bb60..1050527 100644 (file)
@@ -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