boost::filesystem::coy_option is deprecated.
[platform/core/dotnet/launcher.git] / NativeLauncher / util / path_manager.cc
index 99446ed..2eac3b7 100644 (file)
  * limitations under the License.
  */
 
-#include <vector>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <vconf.h>
+
 #include <iterator>
 #include <sstream>
-#include <vconf.h>
+#include <fstream>
 
 #include "utils.h"
+#include "path_manager.h"
 #include "plugin_manager.h"
 #include "log.h"
 
@@ -29,107 +35,208 @@ static const char* __TIZEN_API_PATH_KEY = "db/dotnet/tizen_api_path";
 #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);
+static const char* __READ_ONLY_APP_UPDATE_DIR = __STR(READ_ONLY_APP_UPDATE_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;
-} DllPath;
+// /appRoot/lib/{Architecture}/xxxxx.so
+static std::string getExtraNativeLibDirs(const std::string& appRoot)
+{
+       std::string 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");
+       }
 
-static DllPath* __dllPath = nullptr;
-static std::string __tpa;
+       return candidate;
+}
 
-// on success, return 0. otherwise return -1.
-int initializePathManager(const std::string& runtimeDir, const std::string& tizenFXDir, const std::string& extraDir)
+void PathManager::updateAppRelatedPath(const std::string& appRootPath, const std::string& appNIRootPath)
 {
-       __dllPath = new DllPath();
-       if (!__dllPath) {
-               fprintf(stderr, "fail to allocate memory for dll path structure\n");
-               return -1;
+       std::string appBinPath = concatPath(appRootPath, "bin");
+       std::string appLibPath = concatPath(appRootPath, "lib");
+
+       std::string appNIBinPath = concatPath(concatPath(appNIRootPath, "bin"), APP_NI_SUB_DIR);
+       std::string appNILibPath = concatPath(concatPath(appNIRootPath, "lib"), APP_NI_SUB_DIR);
+
+       appTacPath = concatPath(appBinPath, TAC_SYMLINK_SUB_DIR);
+       appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath;
+       appNIPaths = appNIBinPath + ":" + appNILibPath + ":" + appTacPath;
+
+       if (!extraDllPaths.empty()) {
+               appPaths = appPaths + ":" + extraDllPaths;
+               appNIPaths = appNIPaths + ":" + extraDllPaths;
        }
+}
 
-       if (!runtimeDir.empty()) {
-               __dllPath->runtime_dir = absolutePath(runtimeDir);
+PathManager::PathManager() :
+       rootFD(-1),
+       niRootFD(-1)
+{
+       // set runtime path
+       runtimePath = getAbsolutePath(__RUNTIME_DIR);
+       platformAssembliesPaths.push_back(runtimePath);
+
+       // set tizenfx path
+       char* tizenfx_path = vconf_get_str(__TIZEN_API_PATH_KEY);
+       if (tizenfx_path) {
+               tizenfxPath = std::string(tizenfx_path);
+               _DBG("Device API Directory is set by vconf : %s", tizenfx_path);
+               free(tizenfx_path);
        } else {
-               __dllPath->runtime_dir = absolutePath(__RUNTIME_DIR);
+               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");
        }
 
-       if (!tizenFXDir.empty()) {
-               __dllPath->tizenfx_dir = absolutePath(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);
-               } else {
-                       __dllPath->tizenfx_dir = absolutePath(__DEVICE_API_DIR);
-               }
+       // set temporal application root path for native image
+       niRootFD = open("/proc/self", O_DIRECTORY);
+       if (niRootFD < 0) {
+               _ERR("Failed to open /proc/self");
+               throw std::ios_base::failure("Fail to open /proc/self");
        }
 
-       __dllPath->tizenfx_ref_dir = __dllPath->tizenfx_dir + "/ref";
+       std::string fdPath = "/proc/" + std::to_string(getpid()) + "/fd/";
+       appRootPath = fdPath + std::to_string(rootFD);
+       appNIRootPath = fdPath + std::to_string(niRootFD);
+
+       updateAppRelatedPath(appRootPath, appNIRootPath);
+
+       // Set native library searching path
+       nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" +
+                                 concatPath(appRootPath, "bin") + ":" + concatPath(appRootPath, "lib") + ":" +
+                                 getExtraNativeLibDirs(appRootPath);
+
+       _INFO("Path manager created successfully");
+}
+
+PathManager::~PathManager()
+{
+       _INFO("Path manager destroyed");
+}
+
+// paths: ":" separated muliple path.
+void PathManager::addPlatformAssembliesPaths(const std::string& paths, bool isHighPriority)
+{
+       std::vector<std::string>::iterator it;
+       std::vector<std::string> pathVec;
+       splitPath(paths, pathVec);
 
-       // ":" seperated extra directories
-       if (!extraDir.empty()) {
-               splitPath(extraDir, __dllPath->extra_dirs);
+       for (unsigned int i = 0; i < pathVec.size(); i++) {
+               pathVec[i] = getAbsolutePath(pathVec[i]);
+       }
+
+       if (isHighPriority) {
+               it = platformAssembliesPaths.begin();
        } else {
-               char* extraPath = pluginGetDllPath();
-               if (extraPath) {
-                       splitPath(extraPath, __dllPath->extra_dirs);
-               }
+               it = platformAssembliesPaths.end();
        }
 
-       return 0;
+       platformAssembliesPaths.insert(it, pathVec.begin(), pathVec.end());
 }
 
-void finalizePathManager()
+void PathManager::addNativeDllSearchingPaths(const std::string& paths, bool isHighPriority)
 {
-       if (__dllPath) {
-               delete __dllPath;
-               __dllPath = NULL;
+       if (isHighPriority) {
+               nativeDllSearchingPaths = paths + ":" + nativeDllSearchingPaths;
+       } else {
+               nativeDllSearchingPaths = nativeDllSearchingPaths + ":" + paths;
        }
 }
 
-std::string getRuntimeDir()
+void PathManager::setAppRootPath(const std::string& rootPath)
 {
-       return __dllPath->runtime_dir;
+       appRootPath = getAbsolutePath(rootPath);
+
+       // check readonly update directory eixst or not
+       std::string niRootPath = replaceAll(appRootPath, getBaseName(appRootPath), __READ_ONLY_APP_UPDATE_DIR);
+       if (isReadOnlyArea(appRootPath) && isDirectory(niRootPath)) {
+               appNIRootPath = getAbsolutePath(niRootPath);
+       } else {
+               appNIRootPath = appRootPath;
+       }
+
+       // override root path for application launch mode (candidate / standalone mode)
+       if (rootFD >= 0) {
+               int tmpFD = open(appRootPath.c_str(), O_DIRECTORY);
+               dup3(tmpFD, rootFD, O_CLOEXEC);
+               if (tmpFD >= 0)
+                       close(tmpFD);
+       }
+
+       // override ni root path
+       if (niRootFD >= 0) {
+               int tmpFD = open(appNIRootPath.c_str(), O_DIRECTORY);
+               dup3(tmpFD, niRootFD, O_CLOEXEC);
+               if (tmpFD >= 0)
+                       close(tmpFD);
+       }
+
+       updateAppRelatedPath(appRootPath, appNIRootPath);
 }
 
-std::string getTizenFXDir()
+// paths: ":" separated muliple path.
+void PathManager::setExtraDllPaths(const char* paths)
 {
-       return __dllPath->tizenfx_dir;
+       extraDllPaths = std::string(paths);
+       if (!extraDllPaths.empty()) {
+               appPaths = appPaths + ":" + extraDllPaths;
+               appNIPaths = appNIPaths + ":" + extraDllPaths;
+       }
 }
 
-std::string getTizenFXRefDir()
+const std::string& PathManager::getRuntimePath()
 {
-       return __dllPath->tizenfx_ref_dir;
+       return runtimePath;
 }
 
-std::vector <std::string> getExtraDirs()
+const std::string& PathManager::getTizenFXPath()
 {
-       return __dllPath->extra_dirs;
+       return tizenfxPath;
 }
 
-std::string getTPA()
+// return platform assembly paths
+const std::vector<std::string>& PathManager::getPlatformAssembliesPaths()
 {
-       if (!__tpa.empty()) {
-               return __tpa;
-       }
+       return platformAssembliesPaths;
+}
 
-       std::vector<std::string> tpaDir;
+// return app root path
+const std::string& PathManager::getAppRootPath()
+{
+       return appRootPath;
+}
 
-       if (__dllPath == NULL) {
-               return std::string("");
-       }
+// return .tac_symlink path
+const std::string& PathManager::getAppTacPath()
+{
+       return appTacPath;
+}
 
-       tpaDir.push_back(getRuntimeDir());
-       tpaDir.push_back(getTizenFXDir());
-       tpaDir.push_back(getTizenFXRefDir());
-       tpaDir.insert(tpaDir.end(), __dllPath->extra_dirs.begin(), __dllPath->extra_dirs.end());
-       assembliesInDirectory(tpaDir, __tpa);
+// return dll searching paths for app
+const std::string& PathManager::getAppPaths()
+{
+       return appPaths;
+}
 
-       return __tpa;
+// return ni dll searching paths for app
+const std::string& PathManager::getAppNIPaths()
+{
+       return appNIPaths;
 }
 
+// return native dll searching paths for app
+const std::string& PathManager::getNativeDllSearchingPaths()
+{
+       return nativeDllSearchingPaths;
+}