609491598cd4ea7d27bd3e3797f8b315ce0427b9
[platform/core/dotnet/launcher.git] / NativeLauncher / util / path_manager.cc
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <vconf.h>
22
23 #include <iterator>
24 #include <sstream>
25 #include <fstream>
26
27 #include "utils.h"
28 #include "path_manager.h"
29 #include "plugin_manager.h"
30 #include "log.h"
31
32 static const char* __TIZEN_API_PATH_KEY = "db/dotnet/tizen_api_path";
33 static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
34
35 #define __XSTR(x) #x
36 #define __STR(x) __XSTR(x)
37 static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR);
38 static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR);
39 static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR);
40 #undef __STR
41 #undef __XSTR
42
43 // The sequence of RID_FALLBACK graphs must be:
44 // 1. Tizen + Version + Architecture
45 // 2. Tizen + Version
46 // 3. OS(tizen, linux, unix) + Architecture
47 // 4. OS(tizen, linux, unix)
48 // 5. any, base
49 static std::string getExtraNativeLibDirs(const std::string& appRoot)
50 {
51         std::vector<std::string> RID_FALLBACK_GRAPH;
52         char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
53         if (tizen_rid) {
54                 std::vector<std::string> version;
55                 splitPath(tizen_rid, version);
56                 std::reverse(std::begin(version), std::end(version));
57                 for (unsigned int i = 0; i < version.size(); i++) {
58                         RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
59                         RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i]));
60                 }
61                 free(tizen_rid);
62         }
63
64         std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
65         for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
66                 RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" + ARCHITECTURE_IDENTIFIER));
67                 RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
68         }
69         RID_FALLBACK_GRAPH.push_back("any");
70         RID_FALLBACK_GRAPH.push_back("base");
71
72         std::string candidate;
73         for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) {
74                 if (!candidate.empty()) {
75                         candidate += ":";
76                 }
77                 candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native");
78         }
79
80         candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER);
81         if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
82                 candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64");
83         } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
84                 candidate = candidate + ":" + concatPath(appRoot, "lib/arm");
85         }
86
87         return candidate;
88 }
89
90 void PathManager::updateAppRelatedPath(const std::string& appRootPath)
91 {
92         std::string appBinPath = concatPath(appRootPath, "bin");
93         std::string appLibPath = concatPath(appRootPath, "lib");
94
95         appTacPath = concatPath(appBinPath, TAC_SYMLINK_SUB_DIR);
96         appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath;
97         appNIPaths = concatPath(appBinPath, APP_NI_SUB_DIR) + ":" + concatPath(appLibPath, APP_NI_SUB_DIR) + ":"+ appTacPath;
98         nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" + getExtraNativeLibDirs(appRootPath) + ":" + appBinPath + ":" + appLibPath;
99 }
100
101 PathManager::PathManager() :
102         rootFD(-1)
103 {
104         // set runtime path
105         runtimePath = getAbsolutePath(__RUNTIME_DIR);
106         platformAssembliesPaths.push_back(runtimePath);
107
108         // set tizenfx path
109         char* tmp = vconf_get_str(__TIZEN_API_PATH_KEY);
110         if (tmp) {
111                 tizenfxPath = std::string(tmp);
112                 _DBG("Device API Directory is set by vconf : %s", tmp);
113                 free(tmp);
114         } else {
115                 tizenfxPath = getAbsolutePath(__DEVICE_API_DIR);
116         }
117         platformAssembliesPaths.push_back(tizenfxPath);
118         platformAssembliesPaths.push_back(tizenfxPath + "/ref");
119
120         // set temporal application root path for candidate process
121         rootFD = open("/proc/self", O_DIRECTORY);
122         if (rootFD < 0) {
123                 _ERR("Failed to open /proc/self");
124                 throw std::ios_base::failure("Fail to open /proc/self");
125         }
126
127         appRootPath = std::string("/proc/self/fd/") + std::to_string(rootFD);
128         updateAppRelatedPath(appRootPath);
129
130         _INFO("Path manager created successfully");
131 }
132
133 PathManager::~PathManager()
134 {
135         _INFO("Path manager destroyed");
136 }
137
138 // paths: ":" separated muliple path.
139 void PathManager::addPlatformAssembliesPaths(const std::string& paths, bool isHighPriority)
140 {
141         std::vector<std::string>::iterator it;
142         std::vector<std::string> pathVec;
143         splitPath(paths, pathVec);
144
145         for (unsigned int i = 0; i < pathVec.size(); i++) {
146                 pathVec[i] = getAbsolutePath(pathVec[i]);
147         }
148
149         if (isHighPriority) {
150                 it = platformAssembliesPaths.begin();
151         } else {
152                 it = platformAssembliesPaths.end();
153         }
154
155         platformAssembliesPaths.insert(it, pathVec.begin(), pathVec.end());
156 }
157
158 void PathManager::setAppRootPath(const std::string& rootPath)
159 {
160         // override root path for application launch mode (candidate / standalone mode)
161         if (rootFD >= 0) {
162                 int tmpFD = open(rootPath.c_str(), O_DIRECTORY);
163                 dup3(tmpFD, rootFD, O_CLOEXEC);
164                 if (tmpFD >= 0)
165                         close(tmpFD);
166         }
167
168         appRootPath = getAbsolutePath(rootPath);
169         updateAppRelatedPath(appRootPath);
170 }
171
172 const std::string& PathManager::getRuntimePath()
173 {
174         return runtimePath;
175 }
176
177 const std::string& PathManager::getTizenFXPath()
178 {
179         return tizenfxPath;
180 }
181
182 // return platform assembly paths
183 const std::vector<std::string>& PathManager::getPlatformAssembliesPaths()
184 {
185         return platformAssembliesPaths;
186 }
187
188 // return app root path
189 const std::string& PathManager::getAppRootPath()
190 {
191         return appRootPath;
192 }
193
194 // return .tac_symlink path
195 const std::string& PathManager::getAppTacPath()
196 {
197         return appTacPath;
198 }
199
200 // return dll searching paths for app
201 const std::string& PathManager::getAppPaths()
202 {
203         return appPaths;
204 }
205
206 // return ni dll searching paths for app
207 const std::string& PathManager::getAppNIPaths()
208 {
209         return appNIPaths;
210 }
211
212 // return native dll searching paths for app
213 const std::string& PathManager::getNativeDllSearchingPaths()
214 {
215         return nativeDllSearchingPaths;
216 }