Refactoring path manager
authorWoongsuk Cho <ws77.cho@samsung.com>
Mon, 29 Jun 2020 03:50:55 +0000 (12:50 +0900)
committer조웅석/Common Platform Lab(SR)/Principal Engineer/삼성전자 <ws77.cho@samsung.com>
Wed, 8 Jul 2020 00:15:17 +0000 (09:15 +0900)
The existing path manager provided only the function to create and provide TPA with some directories (runtime/tizenfx/etc).
As a result, a lot of path related duplicate code was used in launcher internal code,

To modify this, the PathManager was refactored as follows:
  1. The paths required for app execution and native image creation are obtained through path manager.
  2. The path manager is created as an object so that it can be maintained and managed where it is needed.
  3. The dependency between path manager and the plugin manager has been removed.
  4. Platform assembly searching path can be updated. (To support dotnet-plugin, system library upgrade)
  5. The nitool doesnot supported any more
  6. --ni-pkg-dll option is removed from dotnettool
  7. TPA related code is moved out from PathManager

Interface change
  1. The parameter of initNICommon() function is removed.
  2. Some functions in ni_common.h, tac_common.h are removed or changed

20 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/hydra/hydra_main.cc
NativeLauncher/inc/ni_common.h
NativeLauncher/inc/path_manager.h
NativeLauncher/inc/tac_common.h
NativeLauncher/inc/utils.h
NativeLauncher/installer-plugin/prefer_dotnet_aot_plugin.cc
NativeLauncher/installer-plugin/prefer_nuget_cache_plugin.cc
NativeLauncher/launcher/exec/launcher.cc
NativeLauncher/launcher/exec/loader.cc
NativeLauncher/launcher/lib/core_runtime.cc
NativeLauncher/launcher/lib/core_runtime.h
NativeLauncher/tool/dotnettool.cc
NativeLauncher/tool/ni_common.cc
NativeLauncher/tool/nitool.cc
NativeLauncher/tool/tac_common.cc
NativeLauncher/tool/tpatool.cc
NativeLauncher/util/path_manager.cc
NativeLauncher/util/utils.cc
packaging/dotnet-launcher.spec

index 17fb44f..53cdf86 100644 (file)
@@ -191,14 +191,6 @@ ADD_LIBRARY(${NI_COMMON} SHARED ${${NI_COMMON}_SOURCE_FILES})
 SET_TARGET_PROPERTIES(${NI_COMMON} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_LIB})
 TARGET_LINK_LIBRARIES(${NI_COMMON} ${${PROJECT_NAME}_LDFLAGS} ${DOTNET_LAUNCHER_UTIL} ${TAC_COMMON})
 
-SET(NITOOL "nitool")
-SET(${NITOOL}_SOURCE_FILES
-    tool/nitool.cc
-)
-ADD_EXECUTABLE(${NITOOL} ${${NITOOL}_SOURCE_FILES})
-SET_TARGET_PROPERTIES(${NITOOL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_EXE})
-TARGET_LINK_LIBRARIES(${NITOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie" ${DOTNET_LAUNCHER_UTIL} ${NI_COMMON})
-
 SET(TPATOOL "tpatool")
 SET(${TPATOOL}_SOURCE_FILES
     tool/tpatool.cc
@@ -241,7 +233,6 @@ INSTALL(TARGETS ${DOTNET_CORERUN} DESTINATION ${BINDIR})
 INSTALL(TARGETS ${DOTNET_HYDRA_LOADER} DESTINATION ${BINDIR})
 INSTALL(TARGETS ${TAC_COMMON} DESTINATION ${LIBDIR})
 INSTALL(TARGETS ${NI_COMMON} DESTINATION ${LIBDIR})
-INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR})
 INSTALL(TARGETS ${TPATOOL} DESTINATION ${BINDIR})
 INSTALL(TARGETS ${DOTNETTOOL} DESTINATION ${BINDIR})
 INSTALL(TARGETS ${PREFER_DOTNET_AOT_PLUGIN} DESTINATION ${INSTALL_MDPLUGIN_DIR})
index 3e45eb2..b14f1ef 100644 (file)
@@ -52,7 +52,7 @@ static std::string getAbsolutePath(const std::string& path)
 static bool isFile(const std::string& path)
 {
        struct stat sb;
-       return stat(path.c_str(), &sb) == 0;
+       return lstat(path.c_str(), &sb) == 0;
 }
 
 static std::string replaceAll(const std::string& str, const std::string& pattern, const std::string& replace)
index d1ade3d..2b00a6f 100644 (file)
@@ -46,20 +46,10 @@ typedef enum {
 } ni_error_e;
 
 /**
- * @brief : structure which contains base directory info
- */
-typedef struct NICommonOption {
-       std::string runtimeDir; /**< .NETCore Runtime directory */
-       std::string tizenFXDir; /**< TizenFX directory */
-       std::string extraDirs; /**< ":" seperated directories which can be set by plugins */
-} NICommonOption;
-
-/**
  * @brief initialize NICommon
- * @param[i] options base directory info
  * @return ni_error_e 0 on success, otherwise a negative error value
  */
-ni_error_e initNICommon(NICommonOption* option);
+ni_error_e initNICommon();
 
 /**
  * @brief finalize NICommon
@@ -82,22 +72,14 @@ ni_error_e createNIPlatform(DWORD flags);
  */
 ni_error_e createNIDll(const std::string& dllPath, DWORD flags);
 
-/**
- * @brief creates a symbolic link file, the native image of TAC for specific package.
- * @param[i] pkgId package ID
- * @param[i] flags additional flags for the image generator
- * @return ni_error_e
- */
-ni_error_e createTACPkgRoot(const std::string& pkgId, DWORD flags);
 
 /**
  * @brief create native images for all DLLs under directories
  * @param[i] rootPaths paths to directories
- * @param[i] count length of rootPaths
  * @param[i] flags additional flags for the image generator
  * @return ni_error_e
  */
-ni_error_e createNIUnderDirs(const std::string rootPaths[], int count, DWORD flags);
+ni_error_e createNIUnderDirs(const std::string rootPaths, DWORD flags);
 
 /**
  * @brief create native images for all DLLs in a package
@@ -108,15 +90,6 @@ ni_error_e createNIUnderDirs(const std::string rootPaths[], int count, DWORD fla
 ni_error_e createNIUnderPkgRoot(const std::string& pkgId, DWORD flags);
 
 /**
- * @brief create a native image for a single dll in a package
- * @param[i] pkgId package ID
- * @param[i] dllPath path to input DLL
- * @param[i] flags additional flags for the image generator
- * @return ni_error_e
- */
-ni_error_e createNIDllUnderPkgRoot(const std::string& pkgId, const std::string& dllPath, DWORD flags);
-
-/**
  * @brief remove platform native images (.NETCore + TizenFX)
  */
 void removeNIPlatform();
@@ -124,9 +97,8 @@ void removeNIPlatform();
 /**
  * @brief remove native images under directories
  * @param[i] rootPaths paths to directories
- * @param[i] count length of rootPaths
  */
-void removeNIUnderDirs(const std::string rootPaths[], int count);
+void removeNIUnderDirs(const std::string rootPaths);
 
 /**
  * @brief remove native images of a package
index 6843c61..264d4b6 100644 (file)
  * limitations under the License.
  */
 
+#include <string>
+#include <vector>
+
 #ifndef __DLL_PATH_MANAGER_H__
 #define __DLL_PATH_MANAGER_H__
 
-int initializePathManager(const std::string& runtimeDir, const std::string& tizenFXDir, const std::string& extraDir);
-void finalizePathManager();
+/**
+ * This class helps to easily obtain paths that are frequently used in the implementation.
+ * The following paths are the major paths managed by this class.
+ *
+ * 1. Platform Assemblies Path
+ *    - Paths where the platform assemblies exist
+ *    - Installation directory of coreclr and tizenfx are included by default
+ *
+ * 2. Application Root Path
+ *    - Installation directory of a Tizen application associated with the current process
+ *    - bin, lib, data, res directories are under Application Root Path
+ *
+ * 3. AppPaths
+ *    - The ":" separated paths where applications's managed assemblies exist
+ *    - Returns the bin, lib, and .tac_symlink under AppRootPath
+ *    - ":" separated path list
+ *
+ * 4. AppNIPaths
+ *    - Paths where applications's native image files exist
+ *    - Returns bin/.native_image, lib/.native_image, and .tac_symlink under AppRootPath
+ *    - ":" separated path list
+ *
+ * 5. Native Dll Searching Path
+ *    - Path to find native libraries required by coreclr
+ *
+ * Platform Assemblies Path can be expanded through the addPlatformAssembliesPath () function.
+ * For example, middleware library path which is passed through plugin can be added to platform assemblies path.
+ *
+ * Application related path (AppPath / AppNIPaths / Native Dll Searching Path) is created based on AppRootPath.
+ * Therefore, it has a temporary location before the AppRootPath is set up,
+ * and has the actual location after the setAppRootPath() function is called.
+*/
+class PathManager 
+{
+public:
+       /**
+        * @brief Platform defined path (runtime and tizenfx path) is set by default
+        *        Temporal application root path is set by default, and paths which based on application root path is also set.
+        *        These paths are updated by calling @setAppRootPath()
+        */
+       PathManager();
+
+       /**
+        * @brief destructor
+        */
+       ~PathManager();
+
+       /**
+        * @brief Add platform assemblies paths. The TPA(Trusted-Platform-Assembly) is generated based on this paths
+        * @param[i] paths the paths to be added
+        * @param[i] isHighPriority if true, paths are added in front of the current list, otherwise added at the end of the list
+        */
+       void addPlatformAssembliesPaths(const std::string& paths, bool isHighPriority = false);
+
+       /**
+        * @brief Set application root path.
+        *        All application related paths ("bin", "lib", ".tac_symlink", ".native_image") are generated based on it.
+        *        A temporary path (/proc/self/fd/[fd]) is used if this function is never called.
+        * @param[i] rootPath application root path
+        */
+       void setAppRootPath(const std::string& rootPath);
+
+       /**
+        * @brief Get runtime path which contains coreclr and corefx
+        * @return[i] runtime path
+        */
+       const std::string& getRuntimePath();
+
+       /**
+        * @brief Get tizenfx path which contains tizenfx
+        * @return[i] runtime path
+        */
+       const std::string& getTizenFXPath();
+
+       /**
+        * @brief Get platform assemblies paths
+        * @return[i] return path vector
+        */
+       const std::vector<std::string>& getPlatformAssembliesPaths();
+
+       /**
+        * @brief Get application root path
+        * @see setAppRootPath()
+        * @return[i] system paths
+        */
+       const std::string& getAppRootPath();
+
+       /**
+        * @brief Get the path of .tac_symlink of application
+        * @return[i] .tac_symlink path
+        */
+       const std::string& getAppTacPath();
+
+       /**
+        * @brief Get the list of directories where the assemlies of this application exist
+        * @return[i] the list(":" seperated) of paths to probe in for an assembly
+        */
+       const std::string& getAppPaths();
+
+       /**
+        * @brief Get the list of directories where the native image of this application exist
+        * @return[i] the list(":" seperated) of paths to probe in for an native image
+        */
+       const std::string& getAppNIPaths();
+
+       /**
+        * @brief Get the list of directories where the native libraries of this application exist
+        * @return[i] the list(":" seperated) of paths the loader should probe when looking for native libraries
+        */
+       const std::string& getNativeDllSearchingPaths();
+
+private:
+       // update application related path (bin, lib, tac_symlink, native_image)
+       void updateAppRelatedPath(const std::string& appRootPath);
 
-std::string getRuntimeDir();
-std::string getTizenFXDir();
-std::string getTizenFXRefDir();
-std::string getExtraDirs();
-std::string getTPA();
+private:
+       std::vector<std::string> platformAssembliesPaths;
+       std::string systemPaths;
+       std::string appRootPath;
+       std::string runtimePath;
+       std::string tizenfxPath;
+       std::string appPaths;
+       std::string appNIPaths;
+       std::string nativeDllSearchingPaths;
+       std::string appTacPath;
+       int rootFD;
+};
 
 #endif /* __DLL_PATH_MANAGER_H__ */
index ae0a221..aa09464 100644 (file)
@@ -36,13 +36,6 @@ typedef enum {
 tac_error_e restoreTACDB();
 
 /**
- * @brief remove a symbolic link file, the native images of TAC for specific package.
- * @param[i] pkgId package ID
- * @return tac_error_e
- */
-tac_error_e resetTACPackage(const std::string& pkgId);
-
-/**
  * @brief disable tac feature.
  * @param[i] pkgId package ID
  * @return tac_error_e
@@ -60,9 +53,8 @@ tac_error_e enableTACPackage(const std::string& pkgId);
  * @brief .deps.json file parser
  * @param[in] root path
  * @param[in] exec name
- * @param[in] tpa list
  * @return std::vector<std::string> parser data
  */
-std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName, const std::string& tpaList);
+std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName);
 
 #endif /* __TAC_COMMON_H__ */
index 1c930ee..3c4e758 100644 (file)
@@ -108,6 +108,7 @@ void splitPath(const std::string& path, std::vector<std::string>& out);
 
 /**
  * @brief check file exists
+ *        in case of symlink file, check both input file and link reference file.
  * @param[in] source path
  * @return bool
  */
index 17a0718..86fbc3c 100644 (file)
@@ -57,8 +57,7 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app
        if (metaValue == METADATA_VALUE) {
                _DBG("Prefer dotnet application AOT set TRUE");
 
-               NICommonOption option = {std::string(), std::string(), std::string()};
-               if (initNICommon(&option) < 0) {
+               if (initNICommon() != NI_ERROR_NONE) {
                        _ERR("Fail to initialize NI Common");
                        return -1;
                }
@@ -66,53 +65,9 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app
                if (createNIUnderPkgRoot(pkgId, 0) != NI_ERROR_NONE) {
                        _ERR("Failed to get root path from [%s]", pkgId);
                        return -1;
-               } else {
-                       _INFO("Complete make application to native image");
                }
 
-               std::string rootPath = getRootPath(std::string(pkgId));
-               if (rootPath.empty()) {
-                       _ERR("Failed to get root path from [%s]", pkgId);
-                       return -1;
-               }
-
-               std::string binDir = concatPath(rootPath, "bin");
-               std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-               if (bf::exists(tacDir)) {
-                       uid_t g_uid = 0;
-                       gid_t g_gid = 0;
-                       if (pkgmgr_installer_info_get_target_uid(&g_uid) < 0) {
-                               _ERR("Failed to get UID");
-                               return -1;
-                       }
-                       try {
-                               for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
-                                       std::string symPath = symlinkAssembly.path().string();
-                                       if (!isNativeImage(symPath)) {
-                                               std::string originPath = bf::read_symlink(symPath).string();
-                                               std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
-                                               if (!bf::exists(originNIPath)) {
-                                                       if (createNIDllUnderPkgRoot(pkgId, originPath, 0) != NI_ERROR_NONE) {
-                                                               _ERR("Failed to create NI file [%s]", originPath.c_str());
-                                                               return -1;
-                                                       }
-                                               }
-                                               std::string setNIPath = symPath.substr(0, symPath.rfind(".dll")) + ".ni.dll";
-                                               if (!bf::exists(setNIPath)) {
-                                                       bf::create_symlink(originNIPath, setNIPath);
-                                                       _INFO("%s symbolic link file generated successfully.", setNIPath.c_str());
-                                                       if (lchown(setNIPath.c_str(), g_uid, g_gid)) {
-                                                               _ERR("Failed to change owner of: %s", setNIPath.c_str());
-                                                               return -1;
-                                                       }
-                                               }
-                                       }
-                               }
-                       } catch (const bf::filesystem_error& error) {
-                               _ERR("File system error while interating files: %s", error.what());
-                               return -1;
-                       }
-               }
+               _INFO("Complete make application to native image");
        }
        return 0;
 }
@@ -134,10 +89,13 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_REMOVED(const char *pkgId, const char *app
 
 extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId, GList *list)
 {
+       // it can be call without initializeNICommon()
+       finalizeNICommon();
        return 0;
 }
 
 extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, GList *list)
 {
+       finalizeNICommon();
        return 0;
 }
index 769f2f6..2d77a80 100644 (file)
@@ -17,8 +17,6 @@
 #include "log.h"
 #include "utils.h"
 #include "db_manager.h"
-#include "path_manager.h"
-#include "plugin_manager.h"
 #include "tac_common.h"
 
 #include <cstring>
@@ -178,7 +176,7 @@ static int copyNCreateSymlink(std::string binPath, std::string tacVersionDir, st
 
 static void depsJsonCheck(std::string rootPath, std::string binPath, std::string execName)
 {
-       for (auto& npAssembly : depsJsonParser(rootPath, execName, getTPA())) {
+       for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
                std::string nuget_package = npAssembly.substr(0, npAssembly.rfind(':'));
                std::string assembly_name = npAssembly.substr(npAssembly.rfind(':') + 1);
                tacDB.push_back(nuget_package);
@@ -203,11 +201,6 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *app
        }
        tacPluginInstalled = true;
 
-       if (initializePathManager(std::string(), std::string(), std::string())) {
-               _ERR("Fail to initialize PathManger");
-               return 0;
-       }
-
        std::string appType = getAppType(std::string(pkgId));
        if (strstr(appType.c_str(), "dotnet") == NULL) {
                _ERR("App type is not dotnet");
@@ -351,11 +344,6 @@ extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *app
        }
        tacPluginInstalled = true;
 
-       if (initializePathManager(std::string(), std::string(), std::string())) {
-               _ERR("Fail to initialize PathManger");
-               return 0;
-       }
-
        std::string appType = getAppType(std::string(pkgId));
        if (strstr(appType.c_str(), "dotnet") == NULL) {
                _ERR("App type is not dotnet");
index a302bb4..e52001e 100644 (file)
@@ -102,19 +102,19 @@ int main(int argc, char *argv[])
        snprintf(argv[0], cmdlineSize - 1, "%s", standalonePath);
 
        // initialize CoreRuntime
-       if (CoreRuntime::initialize(appType, LaunchMode::launcher) != 0) {
+       int err = CoreRuntime::initialize(appType, LaunchMode::launcher);
+       if (err) {
                _ERR("Failed to initialize");
-               return -1;
-       }
-
-       // launch application
-       if (CoreRuntime::launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0])) {
-               _ERR("Failed to launch");
-               return -1;
+       } else {
+               // launch application
+               err = CoreRuntime::launch(appId, appRootPath, standalonePath, vargs.size(), &vargs[0]);
+               if (err) {
+                       _ERR("Failed to launch");
+               }
        }
 
-       // finalize runtime
+       // finalize CoreRuntime
        CoreRuntime::finalize();
 
-       return 0;
+       return err;
 }
index 757aa19..08505ff 100644 (file)
@@ -203,9 +203,8 @@ extern "C" int realMain(int argc, char *argv[])
        };
 
        int ret = launchpad_loader_main(argc, argv, &callbacks, &adapter, NULL);
-       if (ret >= 0) {
-               CoreRuntime::finalize();
-       }
+
+       CoreRuntime::finalize();
 
        return ret;
 }
index 3fd90bb..8f0cd26 100644 (file)
@@ -59,85 +59,9 @@ static set_environment_variable_ptr setEnvironmentVariable = nullptr;
 static void* __coreclrLib = nullptr;
 static void* __hostHandle = nullptr;
 static unsigned int __domainId = -1;
-static int __fd = -1;
 static bool __initialized = false;
 static bool __isProfileMode = false;
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifdef NATIVE_LIB_DIR
-static std::string __nativeLibDirectory = __STR(NATIVE_LIB_DIR);
-#endif
-
-#undef __STR
-#undef __XSTR
-
-#if defined (__aarch64__)
-#define ARCHITECTURE_IDENTIFIER "arm64"
-
-#elif defined (__arm__)
-#define ARCHITECTURE_IDENTIFIER "armel"
-
-#elif defined (__x86_64__)
-#define ARCHITECTURE_IDENTIFIER "x64"
-
-#elif defined (__i386__)
-#define ARCHITECTURE_IDENTIFIER "x86"
-
-#else
-#error "Unknown target"
-#endif
-
-static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
-
-// The sequence of RID_FALLBACK graphs must be:
-// 1. Tizen + Version + Architecture
-// 2. Tizen + Version
-// 3. OS(tizen, linux, unix) + Architecture
-// 4. OS(tizen, linux, unix)
-// 5. any, base
-static std::string getExtraNativeLibDirs(const std::string& appRoot)
-{
-       std::vector<std::string> RID_FALLBACK_GRAPH;
-       char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
-       if (tizen_rid) {
-               std::vector<std::string> version;
-               splitPath(tizen_rid, version);
-               std::reverse(std::begin(version), std::end(version));
-               for (unsigned int i = 0; i < version.size(); i++) {
-                       RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
-                       RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i]));
-               }
-               free(tizen_rid);
-       }
-
-       std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
-       for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
-               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" +  ARCHITECTURE_IDENTIFIER));
-               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
-       }
-       RID_FALLBACK_GRAPH.push_back("any");
-       RID_FALLBACK_GRAPH.push_back("base");
-
-       std::string candidate;
-       for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) {
-               if (!candidate.empty()) {
-                       candidate += ":";
-               }
-               candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native");
-       }
-
-       candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER);
-       if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
-               candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64");
-       } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
-               candidate = candidate + ":" + concatPath(appRoot, "lib/arm");
-       }
-
-       return candidate;
-}
-
+PathManager* CoreRuntime::__pm = nullptr;
 
 static std::vector<std::string> __envList;
 
@@ -316,13 +240,11 @@ void preload()
        } else {
                preloadDelegate();
        }
+
+       pluginPreload();
 }
 
-bool initializeCoreClr(const char* appId,
-                                                                        const char* assemblyProbePaths,
-                                                                        const char* NIProbePaths,
-                                                                        const char* pinvokeProbePaths,
-                                                                        const char* tpaList)
+bool initializeCoreClr(PathManager* pm, const std::string& tpa)
 {
        const char *propertyKeys[] = {
                "TRUSTED_PLATFORM_ASSEMBLIES",
@@ -333,17 +255,17 @@ bool initializeCoreClr(const char* appId,
        };
 
        const char *propertyValues[] = {
-               tpaList,
-               assemblyProbePaths,
-               NIProbePaths,
-               pinvokeProbePaths,
+               tpa.c_str(),
+               pm->getAppPaths().c_str(),
+               pm->getAppNIPaths().c_str(),
+               pm->getNativeDllSearchingPaths().c_str(),
                "UseLatestBehaviorWhenTFMNotSpecified"
        };
 
        std::string selfPath = readSelfPath();
 
        int st = initializeClr(selfPath.c_str(),
-                                                       appId,
+                                                       "TizenDotnetApp",
                                                        sizeof(propertyKeys) / sizeof(propertyKeys[0]),
                                                        propertyKeys,
                                                        propertyValues,
@@ -425,11 +347,18 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
        // read string from external file and set them to environment value.
        setEnvFromFile();
 
-       if (initializePathManager(std::string(), std::string(), std::string()) < 0) {
-               _ERR("Failed to initialize PathManager");
+       try {
+               __pm = new PathManager();
+       } catch (const std::exception& e) {
+               _ERR("Failed to create PathManager");
                return -1;
        }
 
+       char* pluginPath = pluginGetDllPath();
+       if (pluginPath) {
+               __pm->addPlatformAssembliesPaths(pluginPath);
+       }
+
        if (!pluginHasLogControl()) {
                if (initializeLogManager() < 0) {
                        _ERR("Failed to initnialize LogManager");
@@ -437,7 +366,7 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
                }
        }
 
-       std::string libCoreclr(concatPath(getRuntimeDir(), "libcoreclr.so"));
+       std::string libCoreclr(concatPath(__pm->getRuntimePath(), "libcoreclr.so"));
 
        __coreclrLib = dlopen(libCoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
        if (__coreclrLib == nullptr) {
@@ -472,24 +401,15 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
        // To avoid gdbus blocking issue, below function should be called after fork()
        initEnvForSpecialFolder();
 
-       __fd = open("/proc/self", O_DIRECTORY);
-       if (__fd < 0) {
-               _ERR("Failed to open /proc/self");
-               return -1;
+       std::string tpa;
+       char* pluginTPA = pluginGetTPA();
+       if (pluginTPA) {
+               tpa = std::string(pluginTPA);
+       } else {
+               addAssembliesFromDirectories(__pm->getPlatformAssembliesPaths(), tpa);
        }
 
-       std::string tpa = getTPA();
-       std::string runtimeDir = getRuntimeDir();
-       std::string appName = std::string("dotnet-launcher-") + std::to_string(getpid());
-       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 appTac = concatPath(appBin, TAC_SYMLINK_SUB_DIR);
-       std::string probePath = appRoot + ":" + appBin + ":" + appLib + ":" + appTac;
-       std::string NIprobePath = concatPath(appBin, APP_NI_SUB_DIR) + ":" + concatPath(appLib, APP_NI_SUB_DIR) + ":" + appTac;
-       std::string nativeLibPath = runtimeDir + ":" + __nativeLibDirectory + ":" + getExtraNativeLibDirs(appRoot) + ":" + appBin + ":" + appLib;
-
-       if (!initializeCoreClr(appName.c_str(), probePath.c_str(), NIprobePath.c_str(), nativeLibPath.c_str(), tpa.c_str())) {
+       if (!initializeCoreClr(__pm, tpa)) {
                _ERR("Failed to initialize coreclr");
                return -1;
        }
@@ -500,17 +420,17 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
                return -1;
        }
 
-       __initialized = true;
-
        if (launchMode == LaunchMode::loader) {
                // terminate candidate process if language is changed.
                // CurrentCulture created for preloaded dlls should be updated.
                vconf_notify_key_changed(VCONFKEY_LANGSET, langChangedCB, NULL);
 
-               pluginPreload();
-               preload();              // Preload common managed code
+               // preload libraries and manage dlls for optimizing startup time
+               preload();
        }
 
+       __initialized = true;
+
        _INFO("CoreRuntime initialize success");
 
        return 0;
@@ -518,11 +438,6 @@ int CoreRuntime::initialize(const char* appType, LaunchMode launchMode)
 
 void CoreRuntime::finalize()
 {
-       if (!__initialized) {
-               _ERR("Runtime is not initialized");
-               return;
-       }
-
        // call plugin finalize function to notify finalize to plugin
        // dlclose shoud be done after coreclr shutdown to avoid breaking signal chain
        pluginFinalize();
@@ -554,7 +469,9 @@ void CoreRuntime::finalize()
        }
 
        finalizePluginManager();
-       finalizePathManager();
+
+       delete __pm;
+       __pm = NULL;
 
        __envList.clear();
 
@@ -593,13 +510,8 @@ int CoreRuntime::launch(const char* appId, const char* root, const char* path, i
 
        pluginSetAppInfo(appId, path);
 
-       // override root path for application launch mode (candidate / standalone mode)
-       if (__fd >= 0) {
-               int fd2 = open(root, O_DIRECTORY);
-               dup3(fd2, __fd, O_CLOEXEC);
-               if (fd2 >= 0)
-                       close(fd2);
-       }
+       // temporal root path is overrided to real application root path
+       __pm->setAppRootPath(root);
 
        // set application data path to coreclr environment.
        // application data path can be changed by owner. So, we have to set data path just before launching.
index 27b97b9..c4aa53f 100644 (file)
@@ -20,7 +20,7 @@
 #include <string>
 
 #include "coreclr_host.h"
-#include "plugin_manager.h"
+#include "path_manager.h"
 
 enum LaunchMode {
        corerun = 0,
@@ -38,6 +38,9 @@ class CoreRuntime
                static int initialize(const char* appType, LaunchMode launchMode);
                static void finalize();
                static int launch(const char* appId, const char* root, const char* path, int argc, char* argv[]);
+
+       private:
+               static PathManager* __pm;
 };
 
 }  // dotnetcore
index ff4db07..57f4a7a 100644 (file)
@@ -32,7 +32,6 @@ void DisplayUsage() {
                "       --ni-system               - Create NI under System DLLs\n"
                "       --ni-dll                  - Create NI for DLL\n"
                "       --ni-pkg                  - Create NI for package\n"
-               "       --ni-pkg-dll              - Create NI for DLL in package\n"
                "       --ni-dir                  - Create NI for directory\n"
                "       --ni-reset-system         - Remove System NI files\n"
                "       --ni-reset-pkg            - Remove App NI files\n"
@@ -83,11 +82,6 @@ int main(int argc, char* argv[])
                return -1;
        }
 
-       NICommonOption option = {std::string(), std::string(), std::string()};
-       if (initNICommon(&option) != NI_ERROR_NONE) {
-               return -1;
-       }
-
        //sh-3.2# dotnettool --[r2r|compatibility|instrument|verbose]
        DWORD flags = 0;
        std::vector<std::string> args;
@@ -127,6 +121,10 @@ int main(int argc, char* argv[])
                }
        }
 
+       if (initNICommon() != NI_ERROR_NONE) {
+               return -1;
+       }
+
        std::vector<std::string>::iterator it = args.begin();
        std::string cmd = std::string(*it);
        it = args.erase(it);
@@ -166,40 +164,17 @@ int main(int argc, char* argv[])
                                fprintf(stderr, "Failed to generate NI file [%s]\n", pkg.c_str());
                                break;
                        }
-                       ret = createTACPkgRoot(pkg, flags);
-                       if (ret != NI_ERROR_NONE) {
-                               fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkg.c_str());
-                               break;
-                       }
                        it = args.erase(it);
                }
        }
-       //sh-3.2# dotnettool --ni-pkg-dll [pkgId] [pkgAssemblyPath] [pkgAssemblyPath] ...
-       else if (cmd == "--ni-pkg-dll") {
-               if (args.size() < 2) {
-                       fprintf(stderr, "Package name or DLL path is missing\n");
-               } else {
-                       std::string pkg = std::string(*it);
-                       it = args.erase(it);
-                       while (it != args.end()) {
-                               std::string dll = std::string(*it);
-                               int ret = createNIDllUnderPkgRoot(pkg, dll, flags);
-                               if (ret != NI_ERROR_NONE) {
-                                       fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
-                                       break;
-                               }
-                               it = args.erase(it);
-                       }
-               }
-       }
        //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
        else if (cmd == "--ni-dir") {
                if (args.size() < 1) {
                        fprintf(stderr, "Directory path is missing\n");
                }
                while (it != args.end()) {
-                       const std::string dir[] = {std::string(*it)};
-                       int ret = createNIUnderDirs(dir, 1, flags);
+                       const std::string dir = std::string(*it);
+                       int ret = createNIUnderDirs(dir, flags);
                        if (ret != NI_ERROR_NONE) {
                                fprintf(stderr, "Failed to generate NI directory\n");
                                break;
@@ -223,11 +198,6 @@ int main(int argc, char* argv[])
                                fprintf(stderr, "Failed to remove dlls for given package [%s]\n", pkg.c_str());
                                break;
                        }
-                       ret = resetTACPackage(pkg);
-                       if (ret != TAC_ERROR_NONE) {
-                               fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkg.c_str());
-                               break;
-                       }
                        it = args.erase(it);
                }
        }
@@ -237,8 +207,8 @@ int main(int argc, char* argv[])
                        fprintf(stderr, "Directory path is missing\n");
                }
                while (it != args.end()) {
-                       const std::string dir[] = {std::string(*it)};
-                       removeNIUnderDirs(dir, 1);
+                       const std::string dir = std::string(*it);
+                       removeNIUnderDirs(dir);
                        it = args.erase(it);
                }
        }
@@ -298,6 +268,8 @@ int main(int argc, char* argv[])
                DisplayUsage();
        }
 
+       finalizeNICommon();
+
        gettimeofday(&tv, NULL);
        endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
        fprintf(stdout, "\nSpend time for dotnettool is [%d]ms\n", (int)(endtime - starttime));
index 6e9af2f..3f73edb 100644 (file)
@@ -65,7 +65,7 @@ static const char* __SYSTEM_BASE_FILE = __STR(SYSTEM_BASE_FILE);
 #undef __XSTR
 
 static int __interval = 0;
-static std::string __tpa;
+static PathManager* __pm = nullptr;
 
 static void waitInterval()
 {
@@ -93,7 +93,7 @@ static std::string getNIFilePath(const std::string& dllPath)
        return niPath;
 }
 
-static std::string getAppNIPath(const std::string& niPath)
+static std::string getAppNIFilePath(const std::string& niPath)
 {
        std::string fileName;
        std::string niDirPath;
@@ -219,10 +219,13 @@ static void updateBaseAddrFile(const std::string& absNIPath, uintptr_t baseAddr)
 // check if dll is listed in TPA
 static bool isTPADll(const std::string& dllPath)
 {
-       std::string absDllPath = getAbsolutePath(dllPath);
+       std::string absPath = getBaseName(getAbsolutePath(dllPath));
 
-       if (__tpa.find(absDllPath) != std::string::npos) {
-               return true;
+       std::vector<std::string> paths = __pm->getPlatformAssembliesPaths();
+       for (unsigned int i = 0; i < paths.size(); i++) {
+               if (paths[i].find(getBaseName(absPath)) != std::string::npos) {
+                       return true;
+               }
        }
 
        return false;
@@ -250,7 +253,6 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat
        std::string absDllPath = getAbsolutePath(dllPath);
        std::string absNIPath = getNIFilePath(dllPath);
 
-
        if (absNIPath.empty()) {
                fprintf(stderr, "Fail to get ni file name\n");
                return NI_ERROR_UNKNOWN;
@@ -258,7 +260,7 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat
 
        bool isAppNI = flags & NI_FLAGS_APPNI;
        if (isAppNI && strstr(absNIPath.c_str(), __DOTNET_DIR) == NULL) {
-               absNIPath = getAppNIPath(absNIPath);
+               absNIPath = getAppNIFilePath(absNIPath);
        }
 
 #ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
@@ -302,7 +304,7 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat
                        }
                }
        } else {
-               std::string jitPath = getRuntimeDir() + "/libclrjit.so";
+               std::string jitPath = __pm->getRuntimePath() + "/libclrjit.so";
                std::vector<const char*> argv = {
                        __CROSSGEN_PATH,
                        "/nologo",
@@ -310,8 +312,16 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat
                };
 
                bool compat = flags & NI_FLAGS_COMPATIBILITY;
-               argv.push_back(compat ? "/Trusted_Platform_Assemblies" : "/r");
-               argv.push_back(__tpa.c_str());
+               argv.push_back(compat ? "/Platform_Assemblies_Pathes" : "/p");
+               std::vector<std::string> paths = __pm->getPlatformAssembliesPaths();
+               std::string platformAssembliesPaths;
+               for (const auto &path : paths) {
+                       if (!platformAssembliesPaths.empty()) {
+                               platformAssembliesPaths += ":";
+                       }
+                       platformAssembliesPaths += path;
+               }
+               argv.push_back(platformAssembliesPaths.c_str());
 
                bool enableR2R = flags & NI_FLAGS_ENABLER2R;
                if (!enableR2R) {
@@ -375,12 +385,6 @@ static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData)
                return -1;
        }
 
-       if (resetTACPackage(pkgId) != TAC_ERROR_NONE) {
-               fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkgId);
-               return -1;
-       }
-
-       // Regenerate ni files with R2R mode forcibiliy. (there is no way to now which option is used)
        if (createNIUnderPkgRoot(pkgId, *pFlags) != NI_ERROR_NONE) {
                fprintf(stderr, "Failed to generate NI file [%s]\n", pkgId);
                return -1;
@@ -388,13 +392,6 @@ static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData)
                fprintf(stdout, "Complete make application to native image\n");
        }
 
-       if (createTACPkgRoot(pkgId, *pFlags) != NI_ERROR_NONE) {
-               fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkgId);
-               return -1;
-       } else {
-               fprintf(stdout, "Complete make symbolic link file to tac\n");
-       }
-
        return 0;
 }
 
@@ -404,7 +401,7 @@ static bool isCoreLibPrepared(DWORD flags)
                return true;
        }
 
-       std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup");
+       std::string coreLibBackup = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll.Backup");
        if (isFile(coreLibBackup)) {
                return true;
        } else {
@@ -419,8 +416,8 @@ static bool hasCoreLibNI()
 {
        FILE *fp;
        char buff[1024];
-       std::string ildasm = concatPath(getRuntimeDir(), "ildasm");
-       std::string coreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll");
+       std::string ildasm = concatPath(__pm->getRuntimePath(), "ildasm");
+       std::string coreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll");
        std::string cmd = ildasm + " " + coreLib + " | grep '\\.corflags'";
        fp = popen(cmd.c_str(), "r");
        if (fp != NULL) {
@@ -441,9 +438,9 @@ static bool hasCoreLibNI()
 
 static ni_error_e createCoreLibNI(DWORD flags)
 {
-       std::string coreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll");
-       std::string niCoreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.ni.dll");
-       std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup");
+       std::string coreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll");
+       std::string niCoreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.ni.dll");
+       std::string coreLibBackup = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll.Backup");
 
        if (!isFile(coreLibBackup) && !hasCoreLibNI()) {
                if (!crossgen(coreLib, std::string(), flags)) {
@@ -463,7 +460,7 @@ static ni_error_e createCoreLibNI(DWORD flags)
        return NI_ERROR_NONE;
 }
 
-ni_error_e initNICommon(NICommonOption* option)
+ni_error_e initNICommon()
 {
 #if defined(__arm__) || defined(__aarch64__)
        // get interval value
@@ -478,12 +475,18 @@ ni_error_e initNICommon(NICommonOption* option)
                fprintf(stderr, "Fail to initialize PluginManager\n");
                return NI_ERROR_UNKNOWN;
        }
-       if (initializePathManager(option->runtimeDir, option->tizenFXDir, option->extraDirs)) {
-               fprintf(stderr, "Fail to initialize PathManager\n");
+
+       try {
+               __pm = new PathManager();
+       } catch (const std::exception& e) {
+               fprintf(stderr, "Failed to create PathManager");
                return NI_ERROR_UNKNOWN;
        }
 
-       __tpa = getTPA();
+       char* pluginDllPaths = pluginGetDllPath();
+       if (pluginDllPaths) {
+               __pm->addPlatformAssembliesPaths(pluginDllPaths);
+       }
 
        return NI_ERROR_NONE;
 #else
@@ -497,9 +500,9 @@ void finalizeNICommon()
        __interval = 0;
 
        finalizePluginManager();
-       finalizePathManager();
 
-       __tpa.clear();
+       delete(__pm);
+       __pm = nullptr;
 }
 
 ni_error_e createNIPlatform(DWORD flags)
@@ -508,8 +511,7 @@ ni_error_e createNIPlatform(DWORD flags)
                return NI_ERROR_CORE_NI_FILE;
        }
 
-       const std::string platformDirs[] = {getRuntimeDir(), getTizenFXDir()};
-       return createNIUnderDirs(platformDirs, 2, flags);
+       return createNIUnderDirs(__pm->getRuntimePath() + ":" + __pm->getTizenFXPath(), flags);
 }
 
 ni_error_e createNIDll(const std::string& dllPath, DWORD flags)
@@ -525,121 +527,67 @@ ni_error_e createNIDll(const std::string& dllPath, DWORD flags)
        return crossgen(dllPath, std::string(), flags);
 }
 
-static void createNIUnderTAC(const std::vector<std::string>& nugets, DWORD flags)
+ni_error_e createNIUnderDirs(const std::string rootPaths, DWORD flags)
 {
-       std::string appPaths;
-       for (auto& nuget : nugets) {
-               appPaths += concatPath(__DOTNET_DIR, nuget);
-               appPaths += ':';
-       }
-       if (appPaths.back() == ':') {
-               appPaths.pop_back();
+       if (!isCoreLibPrepared(flags)) {
+               return NI_ERROR_CORE_NI_FILE;
        }
 
-       auto convert = [&appPaths, flags](const std::string& path, const std::string& filename) {
-               if (strstr(path.c_str(), TAC_SHA_256_INFO) != NULL)
-                       return;
-               if (!crossgen(path, appPaths.c_str(), flags)) {
+       auto convert = [&rootPaths, flags](const std::string& path, const std::string& filename) {
+
+               // if path is symlink, donot generate crossgen
+               if (!crossgen(path, rootPaths.c_str(), flags)) {
                        waitInterval();
                }
        };
-       for (auto& nuget : nugets) {
-               scanFilesInDirectory(concatPath(__DOTNET_DIR, nuget), convert, -1);
-       }
-}
 
-ni_error_e createTACPkgRoot(const std::string& pkgId, DWORD flags)
-{
-       if (!isCoreLibPrepared(flags)) {
-               return NI_ERROR_CORE_NI_FILE;
-       }
+       std::vector<std::string> targetPaths;
+       splitPath(rootPaths, targetPaths);
+       for (const auto &path : targetPaths) {
+               // TAC directory should be handled specially because that contains symlink of native image file.
+               if (strstr(path.c_str(), TAC_SYMLINK_SUB_DIR) != NULL) {
+                       if (!isDirectory(path)) {
+                               continue;
+                       }
+                       // make native image symlink if not exist under tac directory
+                       try {
+                               for (auto& symlinkAssembly : bf::recursive_directory_iterator(path)) {
+                                       std::string symPath = symlinkAssembly.path().string();
+                                       if (!isManagedAssembly(symPath)) {
+                                               continue;
+                                       }
 
-       std::string rootPath = getRootPath(pkgId);
-       if (rootPath.empty()) {
-               fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str());
-               return NI_ERROR_INVALID_PACKAGE;
-       }
+                                       // if there is symlink and original file for native image, skip generation
+                                       std::string symNIPath = symPath.substr(0, symPath.rfind(".dll")) + ".ni.dll";
+                                       if (isFile(symNIPath)) {
+                                               continue;
+                                       }
 
-       std::string binDir = concatPath(rootPath, "bin");
-       std::string libDir = concatPath(rootPath, "lib");
-       std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-       std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
-       std::string paths = binDir + ":" + libDir + ":" + tacDir;
-       if (bf::exists(tacDir)) {
-               try {
-                       for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
-                               std::string symPath = symlinkAssembly.path().string();
-                               if (bf::is_symlink(symPath)) {
-                                       if (!isNativeImage(symPath)) {
-                                               std::string originPath = bf::read_symlink(symPath).string();
-                                               std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
-                                               if (!bf::exists(originNIPath)) {
-                                                       flags |= NI_FLAGS_APPNI;
-                                                       if (crossgen(originPath, paths, flags) != NI_ERROR_NONE) {
-                                                               fprintf(stderr, "Failed to create NI file [%s]\n", originPath.c_str());
-                                                               return NI_ERROR_UNKNOWN;
-                                                       }
-                                               }
-                                               std::string symNIPath = symPath.substr(0, symPath.rfind(".dll")) + ".ni.dll";
-                                               if (!bf::exists(symNIPath)) {
-                                                       bf::create_symlink(originNIPath, symNIPath);
-                                                       fprintf(stdout, "%s symbolic link file generated successfully.\n", symNIPath.c_str());
-                                                       copySmackAndOwnership(tacDir.c_str(), symNIPath.c_str(), true);
-
-                                                       std::string niFileName = symNIPath.substr(symNIPath.rfind('/') + 1);
-                                                       if (!removeFile(concatPath(binNIDir, niFileName))) {
-                                                               fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, niFileName).c_str());
-                                                       }
+                                       // if original native image not exist, generate native image
+                                       std::string originPath = bf::read_symlink(symPath).string();
+                                       std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
+                                       if (!isFile(originNIPath)) {
+                                               if (!crossgen(originPath, path.c_str(), flags)) {
+                                                       waitInterval();
                                                }
                                        }
-                               }
-                       }
-               } catch (const bf::filesystem_error& error) {
-                       fprintf(stderr, "Failed to recursive directory: %s\n", error.what());
-                       return NI_ERROR_UNKNOWN;
-               }
-       }
-       return NI_ERROR_NONE;
-}
-
-ni_error_e createNIUnderDirs(const std::string rootPaths[], int count, DWORD flags)
-{
-       if (!isCoreLibPrepared(flags)) {
-               return NI_ERROR_CORE_NI_FILE;
-       }
-
-       std::string appPaths;
-       for (int i = 0; i < count; i++) {
-               appPaths += rootPaths[i];
-               appPaths += ':';
-       }
 
-       if (appPaths.back() == ':')
-               appPaths.pop_back();
-
-       std::vector<std::string> tpaAssemblies;
-       splitPath(__tpa, tpaAssemblies);
-
-       auto convert = [&appPaths, flags, tpaAssemblies](const std::string& path, const std::string& filename) {
-               bool isAppNI = flags & NI_FLAGS_APPNI;
-               if (isAppNI) {
-                       for (auto& tpa : tpaAssemblies) {
-                               if (!strcmp(replaceAll(tpa.substr(tpa.rfind('/') + 1), ".ni.dll", ".dll").c_str(), filename.c_str())) {
-                                       fprintf(stderr, "%s present in the TPA list skips generation of NI file.\n", filename.c_str());
-                                       return;
+                                       // if no symlink file exist, create symlink
+                                       if (!isFile(symNIPath)) {
+                                               bf::create_symlink(originNIPath, symNIPath);
+                                               copySmackAndOwnership(symPath.c_str(), symNIPath.c_str(), true);
+                                               fprintf(stdout, "%s symbolic link file generated successfully.\n", symNIPath.c_str());
+                                       }
                                }
+                       } catch (const bf::filesystem_error& error) {
+                               fprintf(stderr, "Failed to recursive directory: %s\n", error.what());
+                               return NI_ERROR_UNKNOWN;
                        }
+               } else {
+                       scanFilesInDirectory(path, convert, 0);
                }
-               if (!crossgen(path, appPaths.c_str(), flags)) {
-                       waitInterval();
-               }
-       };
-
-       for (int i = 0; i < count; i++) {
-               scanFilesInDirectory(rootPaths[i], convert, 0);
        }
 
-       tpaAssemblies.clear();
        return NI_ERROR_NONE;
 }
 
@@ -651,78 +599,19 @@ ni_error_e createNIUnderPkgRoot(const std::string& pkgId, DWORD flags)
                return NI_ERROR_INVALID_PACKAGE;
        }
 
-       std::string binDir = concatPath(rootPath, "bin");
-       std::string libDir = concatPath(rootPath, "lib");
-       std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-       std::string paths[] = {binDir, libDir, tacDir};
+       __pm->setAppRootPath(rootPath);
 
        flags |= NI_FLAGS_APPNI;
-       return createNIUnderDirs(paths, 3, flags);
-}
-
-ni_error_e createNIDllUnderPkgRoot(const std::string& pkgId, const std::string& dllPath, DWORD flags)
-{
-       if (!isCoreLibPrepared(flags)) {
-               return NI_ERROR_CORE_NI_FILE;
-       }
-
-       std::string rootPath = getRootPath(pkgId);
-       if (rootPath.empty()) {
-               fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str());
-               return NI_ERROR_INVALID_PACKAGE;
-       }
 
-       std::string binDir = concatPath(rootPath, "bin");
-       std::string libDir = concatPath(rootPath, "lib");
-       std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-       std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
-       std::string paths = binDir + ":" + libDir + ":" + tacDir;
-
-       if (bf::is_symlink(dllPath)) {
-               if (bf::exists(tacDir)) {
-                       if (!isNativeImage(dllPath)) {
-                               std::string originPath = bf::read_symlink(dllPath).string();
-                               std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
-                               if (!bf::exists(originNIPath)) {
-                                       flags |= NI_FLAGS_APPNI;
-                                       if (crossgen(originPath, paths, flags) != NI_ERROR_NONE) {
-                                               fprintf(stderr, "Failed to create NI file [%s]\n", originPath.c_str());
-                                               return NI_ERROR_UNKNOWN;
-                                       }
-                               }
-                               std::string setNIPath = dllPath.substr(0, dllPath.rfind(".dll")) + ".ni.dll";
-                               if (!bf::exists(setNIPath)) {
-                                       bf::create_symlink(originNIPath, setNIPath);
-                                       fprintf(stdout, "%s symbolic link file generated successfully.\n", setNIPath.c_str());
-                                       copySmackAndOwnership(tacDir.c_str(), setNIPath.c_str(), true);
-                               }
-                               std::string niFileName = setNIPath.substr(setNIPath.rfind('/') + 1);
-                               if (!removeFile(concatPath(binNIDir, niFileName))) {
-                                       fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, niFileName).c_str());
-                               }
-                       }
-               }
-               return NI_ERROR_NONE;
-       } else {
-               std::string assembly = dllPath.substr(dllPath.rfind('/') + 1);
-               std::vector<std::string> tpaAssemblies;
-               splitPath(__tpa, tpaAssemblies);
-               for (auto& tpa : tpaAssemblies) {
-                       if (!strcmp(replaceAll(tpa.substr(tpa.rfind('/') + 1), ".ni.dll", ".dll").c_str(), assembly.c_str())) {
-                               fprintf(stderr, "%s present in the TPA list skips generation of NI file.\n", assembly.c_str());
-                               return NI_ERROR_NONE;
-                       }
-               }
-               tpaAssemblies.clear();
-               flags |= NI_FLAGS_APPNI;
-               return crossgen(dllPath, paths, flags);
-       }
+       // create native image under bin and lib directory
+       // tac directory is skipped in the createNIUnderDirs.
+       return createNIUnderDirs(__pm->getAppPaths(), flags);
 }
 
 void removeNIPlatform()
 {
-       std::string coreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll");
-       std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup");
+       std::string coreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll");
+       std::string coreLibBackup = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll.Backup");
 
        if (hasCoreLibNI()) {
                if (!isFile(coreLibBackup)) {
@@ -745,12 +634,10 @@ void removeNIPlatform()
        }
 #endif
 
-       const std::string platformDirs[] = {getRuntimeDir(), getTizenFXDir()};
-
-       removeNIUnderDirs(platformDirs, 2);
+       removeNIUnderDirs(__pm->getRuntimePath() + ":" + __pm->getTizenFXPath());
 }
 
-void removeNIUnderDirs(const std::string rootPaths[], int count)
+void removeNIUnderDirs(const std::string rootPaths)
 {
        auto convert = [](const std::string& path, const std::string& filename) {
                if (isNativeImage(path)) {
@@ -760,8 +647,10 @@ void removeNIUnderDirs(const std::string rootPaths[], int count)
                }
        };
 
-       for (int i = 0; i < count; i++) {
-               scanFilesInDirectory(rootPaths[i], convert, -1);
+       std::vector<std::string> paths;
+       splitPath(rootPaths, paths);
+       for (const auto &path : paths) {
+               scanFilesInDirectory(path, convert, -1);
        }
 }
 
@@ -773,23 +662,22 @@ ni_error_e removeNIUnderPkgRoot(const std::string& pkgId)
                return NI_ERROR_INVALID_PACKAGE;
        }
 
-       std::string binDir = concatPath(rootPath, "bin");
-       std::string libDir = concatPath(rootPath, "lib");
-       std::string paths[] = {binDir, libDir};
-
-       removeNIUnderDirs(paths, 2);
+       __pm->setAppRootPath(rootPath);
 
-       std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
-       if (isFile(binNIDir)) {
-               if (!removeAll(binNIDir.c_str())) {
-                       fprintf(stderr, "Failed to remove app ni dir [%s]\n", binNIDir.c_str());
-               }
-       }
-
-       std::string libNIDir = concatPath(libDir, APP_NI_SUB_DIR);
-       if (isFile(libNIDir)) {
-               if (!removeAll(libNIDir.c_str())) {
-                       fprintf(stderr, "Failed to remove app ni dir [%s]\n", libNIDir.c_str());
+       // getAppNIPaths returns bin/.native_image, lib/.native_image and .tac_symlink.
+       std::string appNIPaths = __pm->getAppNIPaths();
+       std::vector<std::string> paths;
+       splitPath(appNIPaths, paths);
+       for (const auto &path : paths) {
+               // Only the native image inside the TAC should be removed.
+               if (strstr(path.c_str(), TAC_SYMLINK_SUB_DIR) != NULL) {
+                       removeNIUnderDirs(path);
+               } else {
+                       if (isDirectory(path)) {
+                               if (!removeAll(path.c_str())) {
+                                       fprintf(stderr, "Failed to remove app ni dir [%s]\n", path.c_str());
+                               }
+                       }
                }
        }
 
@@ -835,7 +723,7 @@ static int regenTacCb(pkgmgrinfo_appinfo_h handle, void *userData)
        DWORD *pFlags = (DWORD*)userData;
 
        int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
-       if (ret != PMINFO_R_OK) {
+       if (ret != PMINFO_R_OK || pkgId == NULL) {
                fprintf(stderr, "Failed to get pkgid\n");
                return -1;
        }
@@ -855,7 +743,25 @@ static int regenTacCb(pkgmgrinfo_appinfo_h handle, void *userData)
                tac_db = NULL;
        }
 
-       createNIUnderTAC(nugets, *pFlags);
+       std::string nugetPaths;
+       for (const auto &nuget : nugets) {
+               if (!nugetPaths.empty()) {
+                       nugetPaths += ":";
+               }
+               nugetPaths += concatPath(__DOTNET_DIR, nuget);
+       }
+
+       auto convert = [&nugetPaths, pFlags](const std::string& path, const std::string& filename) {
+               if (strstr(path.c_str(), TAC_SHA_256_INFO) != NULL)
+                       return;
+               if (!crossgen(path, nugetPaths.c_str(), *pFlags)) {
+                       waitInterval();
+               }
+       };
+
+       for (auto& nuget : nugets) {
+               scanFilesInDirectory(concatPath(__DOTNET_DIR, nuget), convert, -1);
+       }
 
        return 0;
 }
@@ -866,8 +772,7 @@ ni_error_e regenerateTACNI(DWORD flags)
                return NI_ERROR_CORE_NI_FILE;
        }
 
-       const std::string tacDir[] = {__DOTNET_DIR};
-       removeNIUnderDirs(tacDir, 1);
+       removeNIUnderDirs(__DOTNET_DIR);
 
        pkgmgrinfo_appinfo_metadata_filter_h handle;
        int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
index 29b6b78..1b99e3f 100644 (file)
@@ -52,12 +52,9 @@ int main(int argc, char* argv[])
        DWORD flags = 0;
        bool pkgMode = false;
        bool dllMode = false;
-       bool dirMode = false;
        bool rmPkgMode = false;
-       bool pkgDllMode = false;
 
-       NICommonOption option = {std::string(), std::string(), std::string()};
-       if (initNICommon(&option) != NI_ERROR_NONE) {
+       if (initNICommon() != NI_ERROR_NONE) {
                return -1;
        }
 
@@ -86,8 +83,6 @@ int main(int argc, char* argv[])
                dllMode = true;
        } else if (cmdOptionExists(argv, argv+argc, "--pkg")) {
                pkgMode = true;
-       } else if (cmdOptionExists(argv, argv+argc, "--dir")) {
-               dirMode = true;
        } else if (cmdOptionExists(argv, argv+argc, "--reset-system")) {
                removeNIPlatform();
                return 0;
@@ -96,8 +91,6 @@ int main(int argc, char* argv[])
        } else if (cmdOptionExists(argv, argv+argc, "--regen-all-app")) {
                regenerateAppNI(flags);
                return 0;
-       } else if (cmdOptionExists(argv, argv+argc, "--pkg-dll")) {
-               pkgDllMode = true;
        } else {
                help(argv[0]);
                return 0;
@@ -126,18 +119,6 @@ int main(int argc, char* argv[])
                                return -1;
                        }
                }
-       } else if (pkgDllMode) {
-               int ret = createNIDllUnderPkgRoot(args[0], args[1], flags);
-               if (ret == NI_ERROR_INVALID_PACKAGE) {
-                       fprintf(stderr, "Failed to get root path from [%s]\n", args[0].c_str());
-                       return -1;
-               } else if (ret == NI_ERROR_ALREADY_EXIST) {
-                       // skip for already exist case
-                       return -1;
-               } else if (ret != NI_ERROR_NONE) {
-                       fprintf(stderr, "Failed to generate NI file [%s]\n", args[1].c_str());
-                       return -1;
-               }
        } else if (rmPkgMode) {
                for (const std::string pkg : args) {
                        int ret = removeNIUnderPkgRoot(pkg);
@@ -160,8 +141,6 @@ int main(int argc, char* argv[])
                                fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
                        }
                }
-       } else if (dirMode) {
-               createNIUnderDirs(args.data(), args.size(), flags);
        }
 
        return 0;
index 844ad5e..a982b26 100644 (file)
@@ -107,7 +107,7 @@ static int restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData)
        std::vector<std::string> parserData;
        std::string binDir = concatPath(rootPath, "bin");
        std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-       for (auto& npAssembly : depsJsonParser(rootPath, execName, getTPA())) {
+       for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
                std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':'));
                std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1);
                if (bf::exists(tacDir) && bf::exists(concatPath(tacDir, assemblyName))) {
@@ -146,11 +146,6 @@ tac_error_e restoreTACDB()
                return TAC_ERROR_UNKNOWN;
        }
 
-       if (initializePathManager(std::string(), std::string(), std::string())) {
-               fprintf(stderr, "Fail to initialize PathManger\n");
-               return TAC_ERROR_UNKNOWN;
-       }
-
        tac_db = dbCreate(TAC_APP_LIST_RESTORE_DB, CREATE_TAC_DB_TABLE);
        if (!tac_db) {
                fprintf(stderr, "Sqlite create error\n");
@@ -217,42 +212,6 @@ tac_error_e restoreTACDB()
        return TAC_ERROR_NONE;
 }
 
-tac_error_e resetTACPackage(const std::string& pkgId)
-{
-       std::string rootPath = getRootPath(pkgId);
-       if (rootPath.empty()) {
-               fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str());
-               return TAC_ERROR_INVALID_PACKAGE;
-       }
-
-       std::vector<std::string> tacNativeImage;
-       std::string binDir = concatPath(rootPath, "bin");
-       std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-       if (bf::exists(tacDir)) {
-               try {
-                       for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
-                               std::string symPath = symlinkAssembly.path().string();
-                               if (bf::is_symlink(symPath)) {
-                                       if (isNativeImage(symPath)) {
-                                               tacNativeImage.push_back(symPath);
-                                       }
-                               }
-                       }
-                       for (auto& path : tacNativeImage) {
-                               if (!removeFile(path)) {
-                                       fprintf(stderr, "Failed to remove of %s\n", path.c_str());
-                                       return TAC_ERROR_UNKNOWN;
-                               }
-                       }
-                       tacNativeImage.clear();
-               } catch (const bf::filesystem_error& error) {
-                       fprintf(stderr, "Failed to recursive directory: %s\n", error.what());
-                       return TAC_ERROR_UNKNOWN;
-               }
-       }
-       return TAC_ERROR_NONE;
-}
-
 tac_error_e disableTACPackage(const std::string& pkgId)
 {
        std::string rootPath = getRootPath(pkgId);
@@ -320,11 +279,6 @@ tac_error_e enableTACPackage(const std::string& pkgId)
                return TAC_ERROR_INVALID_PACKAGE;
        }
 
-       if (initializePathManager(std::string(), std::string(), std::string())) {
-               fprintf(stderr, "Fail to initialize PathManger\n");
-               return TAC_ERROR_UNKNOWN;
-       }
-
        if (!strcmp(metaValue.c_str(), "true")) {
                std::string binDir = concatPath(rootPath, "bin");
                std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
@@ -337,7 +291,7 @@ tac_error_e enableTACPackage(const std::string& pkgId)
                        copySmackAndOwnership(binDir.c_str(), tacDir.c_str());
 
                        std::vector<std::string> enableNuget;
-                       for (auto& npAssembly : depsJsonParser(rootPath, execName, getTPA())) {
+                       for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
                                std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':'));
                                std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1);
                                std::string nugetPath = concatPath(__DOTNET_DIR, nugetPackage);
@@ -390,11 +344,8 @@ tac_error_e enableTACPackage(const std::string& pkgId)
 }
 
 //Parser the .deps.json file to get nuget information.
-std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName, const std::string& tpaList)
+std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName)
 {
-       std::vector<std::string> tpaAssemblies;
-       splitPath(tpaList, tpaAssemblies);
-
        std::vector<std::string> parserData;
        std::string depsJsonName = execName.substr(0, execName.rfind(".dll")) + ".deps.json";
        std::string depsJsonPath = concatPath(rootPath, depsJsonName);
@@ -408,7 +359,6 @@ std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::
                                if (!Json::parseFromStream(reader, ifs, &root, &error)) {
                                        _ERR("Failed to parse of deps.json");
                                        ifs.close();
-                                       tpaAssemblies.clear();
                                        return parserData;
                                }
                                const Json::Value runtimeTargetName = root["runtimeTarget"]["name"];
@@ -453,25 +403,11 @@ std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::
                                                                }
                                                        }
                                                        if (!hasDependency) {
-                                                               bool isExistTpaAssembly = false;
+                                                               // handle assembly even though that is included in the TPA.
                                                                for (auto& assembly : assemblies.getMemberNames()) {
                                                                        std::string assemblyName = assembly.substr(assembly.rfind('/') + 1);
-                                                                       //Skip the assembly present in the TPA list
-                                                                       for (auto& tpaPath : tpaAssemblies) {
-                                                                               std::string tpaName = replaceAll(tpaPath.substr(tpaPath.rfind('/') + 1), ".ni.dll", ".dll");
-                                                                               if (!strcmp(tpaName.c_str(), assemblyName.c_str())) {
-                                                                                       isExistTpaAssembly = true;
-                                                                                       break;
-                                                                               }
-                                                                       }
-                                                                       if (isExistTpaAssembly) break;
-                                                               }
-                                                               if (!isExistTpaAssembly) {
-                                                                       for (auto& assembly : assemblies.getMemberNames()) {
-                                                                               std::string assemblyName = assembly.substr(assembly.rfind('/') + 1);
-                                                                               parserData.push_back(nuget + ":" + assemblyName);
-                                                                               _INFO("Nuget : [%s] / Assembly : [%s]", nuget.c_str(), assemblyName.c_str());
-                                                                       }
+                                                                       parserData.push_back(nuget + ":" + assemblyName);
+                                                                       _INFO("Nuget : [%s] / Assembly : [%s]", nuget.c_str(), assemblyName.c_str());
                                                                }
                                                        }
                                                }
@@ -484,6 +420,5 @@ std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::
        } catch (const Json::LogicError& error) {
                _ERR("Failed to parse Json: %s", error.what());
        }
-       tpaAssemblies.clear();
        return parserData;
 }
index 197bf50..ef00bf5 100644 (file)
 
 int main(int argc, char* argv[])
 {
-       if (initializePathManager(std::string(), std::string(), std::string())) {
-               fprintf(stderr, "Fail to initialize PathManager\n");
+       PathManager* __pm = nullptr;
+       try {
+               __pm = new PathManager();
+       }  catch (const std::exception& e) {
+               fprintf(stderr, "Failed to create PathManager");
                return -1;
        }
 
-       std::string tpaList = getTPA();
+       std::string tpaList;
+       addAssembliesFromDirectories(__pm->getPlatformAssembliesPaths(), tpaList);
+
        if (!bf::is_symlink(PLATFORM_TPA_CACHE)) {
                std::ofstream out(PLATFORM_TPA_CACHE);
                out << tpaList;
@@ -38,5 +43,8 @@ int main(int argc, char* argv[])
                return -1;
        }
 
+       delete(__pm);
+       __pm = nullptr;
+
        return 0;
 }
index d89b84e..250f6fb 100644 (file)
  * limitations under the License.
  */
 
-#include <vector>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include <iterator>
 #include <sstream>
 #include <vconf.h>
 #include <fstream>
 
 #include "utils.h"
+#include "path_manager.h"
 #include "plugin_manager.h"
 #include "log.h"
 
 static const char* __TIZEN_API_PATH_KEY = "db/dotnet/tizen_api_path";
+static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
 
 #define __XSTR(x) #x
 #define __STR(x) __XSTR(x)
 static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR);
 static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR);
+static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR);
+
 #undef __STR
 #undef __XSTR
 
-typedef struct DllPath {
-       std::string runtime_dir;
-       std::string tizenfx_dir;
-       std::string tizenfx_ref_dir;
-       std::vector<std::string> extra_dirs;
-       std::vector<std::string> plugin_dirs;
-} DllPath;
+#if defined (__aarch64__)
+#define ARCHITECTURE_IDENTIFIER "arm64"
 
-static DllPath* __dllPath = nullptr;
-static std::string __tpa;
-bool initializedPathManager = false;
+#elif defined (__arm__)
+#define ARCHITECTURE_IDENTIFIER "armel"
 
-// on success, return 0. otherwise return -1.
-int initializePathManager(const std::string& runtimeDir, const std::string& tizenFXDir, const std::string& extraDir)
-{
-       if (initializedPathManager) {
-               _INFO("Path manager already initialized");
-               return 0;
-       }
+#elif defined (__x86_64__)
+#define ARCHITECTURE_IDENTIFIER "x64"
 
-       __dllPath = new DllPath();
-       if (!__dllPath) {
-               _ERR("fail to allocate memory for dll path structure\n");
-               return -1;
-       }
+#elif defined (__i386__)
+#define ARCHITECTURE_IDENTIFIER "x86"
 
-       if (!runtimeDir.empty()) {
-               __dllPath->runtime_dir = getAbsolutePath(runtimeDir);
-       } else {
-               __dllPath->runtime_dir = getAbsolutePath(__RUNTIME_DIR);
-       }
+#else
+#error "Unknown target"
+#endif
 
-       if (!tizenFXDir.empty()) {
-               __dllPath->tizenfx_dir = getAbsolutePath(tizenFXDir);
-       } else {
-               char* tmp = vconf_get_str(__TIZEN_API_PATH_KEY);
-               if (tmp) {
-                       __dllPath->tizenfx_dir = std::string(tmp);
-                       _DBG("Device API Directory is set by vconf : %s", tmp);
-                       free(tmp);
-               } else {
-                       __dllPath->tizenfx_dir = getAbsolutePath(__DEVICE_API_DIR);
+// The sequence of RID_FALLBACK graphs must be:
+// 1. Tizen + Version + Architecture
+// 2. Tizen + Version
+// 3. OS(tizen, linux, unix) + Architecture
+// 4. OS(tizen, linux, unix)
+// 5. any, base
+static std::string getExtraNativeLibDirs(const std::string& appRoot)
+{
+       std::vector<std::string> RID_FALLBACK_GRAPH;
+       char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
+       if (tizen_rid) {
+               std::vector<std::string> version;
+               splitPath(tizen_rid, version);
+               std::reverse(std::begin(version), std::end(version));
+               for (unsigned int i = 0; i < version.size(); i++) {
+                       RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
+                       RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i]));
                }
+               free(tizen_rid);
        }
 
-       __dllPath->tizenfx_ref_dir = __dllPath->tizenfx_dir + "/ref";
+       std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
+       for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
+               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" +  ARCHITECTURE_IDENTIFIER));
+               RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
+       }
+       RID_FALLBACK_GRAPH.push_back("any");
+       RID_FALLBACK_GRAPH.push_back("base");
 
-       // ":" seperated extra directories
-       if (!extraDir.empty()) {
-               splitPath(extraDir, __dllPath->extra_dirs);
+       std::string candidate;
+       for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) {
+               if (!candidate.empty()) {
+                       candidate += ":";
+               }
+               candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native");
        }
 
-       char* pluginPath = pluginGetDllPath();
-       if (pluginPath) {
-               splitPath(pluginPath, __dllPath->plugin_dirs);
+       candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER);
+       if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
+               candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64");
+       } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
+               candidate = candidate + ":" + concatPath(appRoot, "lib/arm");
        }
 
-       _INFO("Path manager initialize success");
+       return candidate;
+}
 
-       initializedPathManager = true;
-       return 0;
+void PathManager::updateAppRelatedPath(const std::string& appRootPath)
+{
+       std::string appBinPath = concatPath(appRootPath, "bin");
+       std::string appLibPath = concatPath(appRootPath, "lib");
+
+       appTacPath = concatPath(appBinPath, TAC_SYMLINK_SUB_DIR);
+       appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath;
+       appNIPaths = concatPath(appBinPath, APP_NI_SUB_DIR) + ":" + concatPath(appLibPath, APP_NI_SUB_DIR) + ":"+ appTacPath;
+       nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" + getExtraNativeLibDirs(appRootPath) + ":" + appBinPath + ":" + appLibPath;
 }
 
-void finalizePathManager()
+PathManager::PathManager() :
+       rootFD(-1)
 {
-       _INFO("Path manager finalize called");
-       if (__dllPath) {
-               delete __dllPath;
-               __dllPath = NULL;
+       // set runtime path
+       runtimePath = getAbsolutePath(__RUNTIME_DIR);
+       platformAssembliesPaths.push_back(runtimePath);
+
+       // set tizenfx path
+       char* tmp = vconf_get_str(__TIZEN_API_PATH_KEY);
+       if (tmp) {
+               tizenfxPath = std::string(tmp);
+               _DBG("Device API Directory is set by vconf : %s", tmp);
+               free(tmp);
+       } else {
+               tizenfxPath = getAbsolutePath(__DEVICE_API_DIR);
        }
+       platformAssembliesPaths.push_back(tizenfxPath);
+       platformAssembliesPaths.push_back(tizenfxPath + "/ref");
+
+       // set temporal application root path for candidate process
+       rootFD = open("/proc/self", O_DIRECTORY);
+       if (rootFD < 0) {
+               _ERR("Failed to open /proc/self");
+               throw std::ios_base::failure("Fail to open /proc/self");
+       }
+
+       appRootPath = std::string("/proc/self/fd/") + std::to_string(rootFD);
+       updateAppRelatedPath(appRootPath);
 
-       initializedPathManager = false;
+       _INFO("Path manager created successfully");
 }
 
-std::string getRuntimeDir()
+PathManager::~PathManager()
 {
-       return __dllPath->runtime_dir;
+       _INFO("Path manager destroyed");
 }
 
-std::string getTizenFXDir()
+// paths: ":" separated muliple path.
+void PathManager::addPlatformAssembliesPaths(const std::string& paths, bool isHighPriority)
 {
-       return __dllPath->tizenfx_dir;
+       std::vector<std::string>::iterator it;
+       std::vector<std::string> pathVec;
+       splitPath(paths, pathVec);
+
+       for (unsigned int i = 0; i < pathVec.size(); i++) {
+               pathVec[i] = getAbsolutePath(pathVec[i]);
+       }
+
+       if (isHighPriority) {
+               it = platformAssembliesPaths.begin();
+       } else {
+               it = platformAssembliesPaths.end();
+       }
+
+       platformAssembliesPaths.insert(it, pathVec.begin(), pathVec.end());
 }
 
-std::string getTizenFXRefDir()
+void PathManager::setAppRootPath(const std::string& rootPath)
 {
-       return __dllPath->tizenfx_ref_dir;
+       // override root path for application launch mode (candidate / standalone mode)
+       if (rootFD >= 0) {
+               int tmpFD = open(rootPath.c_str(), O_DIRECTORY);
+               dup3(tmpFD, rootFD, O_CLOEXEC);
+               if (tmpFD >= 0)
+                       close(tmpFD);
+       }
+
+       appRootPath = getAbsolutePath(rootPath);
+       updateAppRelatedPath(appRootPath);
 }
 
-std::vector<std::string> getExtraDirs()
+const std::string& PathManager::getRuntimePath()
 {
-       return __dllPath->extra_dirs;
+       return runtimePath;
 }
 
-std::vector<std::string> getPluginDirs()
+const std::string& PathManager::getTizenFXPath()
 {
-       return __dllPath->plugin_dirs;
+       return tizenfxPath;
 }
 
-static std::string getPlatformTPA()
+// return platform assembly paths
+const std::vector<std::string>& PathManager::getPlatformAssembliesPaths()
 {
-       std::string platform_tpa;
-
-       if (isFile(PLATFORM_TPA_CACHE)) {
-               _INFO("platform tpa cache found.");
-               std::ifstream cacheFile;
-               cacheFile.open(PLATFORM_TPA_CACHE);
-               std::getline(cacheFile, platform_tpa);
-               cacheFile.close();
-       } else {
-               std::vector<std::string> tpaDirs = { getRuntimeDir(), getTizenFXDir(), getTizenFXRefDir() };
-               tpaDirs.insert(tpaDirs.end(), getExtraDirs().begin(), getExtraDirs().end());
-               addAssembliesFromDirectories(tpaDirs, platform_tpa);
-       }
-
-       return platform_tpa;
+       return platformAssembliesPaths;
 }
 
-static std::string getPluginTPA()
+// return app root path
+const std::string& PathManager::getAppRootPath()
 {
-       std::string plugin_tpa;
-       char* plugin_tpa_list = pluginGetTPA();
-       if (plugin_tpa_list) {
-               _INFO("plugin TPA list found. use TPA list for plugin");
-               plugin_tpa = plugin_tpa_list;
-       } else if (!getPluginDirs().empty()) {
-               _INFO("Plugin directory found. use plugin directroy for TPA");
-               addAssembliesFromDirectories(getPluginDirs(), plugin_tpa);
-       }
+       return appRootPath;
+}
 
-       return plugin_tpa;
+// return .tac_symlink path
+const std::string& PathManager::getAppTacPath()
+{
+       return appTacPath;
 }
 
-std::string getTPA()
+// return dll searching paths for app
+const std::string& PathManager::getAppPaths()
 {
-       if (!__tpa.empty()) {
-               return __tpa;
-       }
+       return appPaths;
+}
 
-       if (__dllPath == NULL) {
-               return std::string("");
-       }
+// return ni dll searching paths for app
+const std::string& PathManager::getAppNIPaths()
+{
+       return appNIPaths;
+}
 
-       return getPlatformTPA() + ":" + getPluginTPA();
+// return native dll searching paths for app 
+const std::string& PathManager::getNativeDllSearchingPaths()
+{
+       return nativeDllSearchingPaths;
 }
+
index 5b047ae..90fd0e4 100644 (file)
@@ -269,7 +269,7 @@ std::string replaceAll(const std::string& str, const std::string& pattern, const
 bool isFile(const std::string& path)
 {
        struct stat sb;
-       return stat(path.c_str(), &sb) == 0;
+       return lstat(path.c_str(), &sb) == 0;
 }
 
 bool isDirectory(const std::string& path)
@@ -339,9 +339,6 @@ void scanFilesInDirectory(const std::string& directory, FileReader reader, unsig
        struct dirent* entry;
        bool isDir;
 
-       if (strstr(directory.c_str(), TAC_SYMLINK_SUB_DIR) != NULL)
-               return;
-
        dir = opendir(directory.c_str());
 
        if (dir == nullptr)
@@ -357,14 +354,12 @@ void scanFilesInDirectory(const std::string& directory, FileReader reader, unsig
                        case DT_DIR:
                                isDir = true;
                                break;
+                       // symlink is added to the list even if there is no original file.
+                       // It used to remove broken symlinks related to TAC
                        case DT_LNK:
+                               break;
                        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;
+                               continue;
                        default:
                                continue;
                }
index 00ad53a..8670b5e 100644 (file)
@@ -169,7 +169,6 @@ chsmack -t -a User::App::Shared /opt/etc/skel/.dotnet
 %{_loaderdir}/dotnet-nui.launcher
 %{_loaderdir}/dotnet-nui.debugger
 %{_native_lib_dir}/libsqlite3.so
-%{_bindir}/nitool
 %{_bindir}/tpatool
 %{_bindir}/dotnettool
 %{_install_mdplugin_dir}/libprefer_nuget_cache_plugin.so