Refactoring path manager
[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
21 #include <iterator>
22 #include <sstream>
23 #include <vconf.h>
24 #include <fstream>
25
26 #include "utils.h"
27 #include "path_manager.h"
28 #include "plugin_manager.h"
29 #include "log.h"
30
31 static const char* __TIZEN_API_PATH_KEY = "db/dotnet/tizen_api_path";
32 static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
33
34 #define __XSTR(x) #x
35 #define __STR(x) __XSTR(x)
36 static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR);
37 static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR);
38 static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR);
39
40 #undef __STR
41 #undef __XSTR
42
43 #if defined (__aarch64__)
44 #define ARCHITECTURE_IDENTIFIER "arm64"
45
46 #elif defined (__arm__)
47 #define ARCHITECTURE_IDENTIFIER "armel"
48
49 #elif defined (__x86_64__)
50 #define ARCHITECTURE_IDENTIFIER "x64"
51
52 #elif defined (__i386__)
53 #define ARCHITECTURE_IDENTIFIER "x86"
54
55 #else
56 #error "Unknown target"
57 #endif
58
59 // The sequence of RID_FALLBACK graphs must be:
60 // 1. Tizen + Version + Architecture
61 // 2. Tizen + Version
62 // 3. OS(tizen, linux, unix) + Architecture
63 // 4. OS(tizen, linux, unix)
64 // 5. any, base
65 static std::string getExtraNativeLibDirs(const std::string& appRoot)
66 {
67         std::vector<std::string> RID_FALLBACK_GRAPH;
68         char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
69         if (tizen_rid) {
70                 std::vector<std::string> version;
71                 splitPath(tizen_rid, version);
72                 std::reverse(std::begin(version), std::end(version));
73                 for (unsigned int i = 0; i < version.size(); i++) {
74                         RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
75                         RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i]));
76                 }
77                 free(tizen_rid);
78         }
79
80         std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
81         for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
82                 RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" +  ARCHITECTURE_IDENTIFIER));
83                 RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
84         }
85         RID_FALLBACK_GRAPH.push_back("any");
86         RID_FALLBACK_GRAPH.push_back("base");
87
88         std::string candidate;
89         for (unsigned int i = 0; i < RID_FALLBACK_GRAPH.size(); i++) {
90                 if (!candidate.empty()) {
91                         candidate += ":";
92                 }
93                 candidate += concatPath(appRoot, "bin/runtimes/" + RID_FALLBACK_GRAPH[i] + "/native");
94         }
95
96         candidate = candidate + ":" + concatPath(appRoot, "lib/" ARCHITECTURE_IDENTIFIER);
97         if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
98                 candidate = candidate + ":" + concatPath(appRoot, "lib/aarch64");
99         } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
100                 candidate = candidate + ":" + concatPath(appRoot, "lib/arm");
101         }
102
103         return candidate;
104 }
105
106 void PathManager::updateAppRelatedPath(const std::string& appRootPath)
107 {
108         std::string appBinPath = concatPath(appRootPath, "bin");
109         std::string appLibPath = concatPath(appRootPath, "lib");
110
111         appTacPath = concatPath(appBinPath, TAC_SYMLINK_SUB_DIR);
112         appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath;
113         appNIPaths = concatPath(appBinPath, APP_NI_SUB_DIR) + ":" + concatPath(appLibPath, APP_NI_SUB_DIR) + ":"+ appTacPath;
114         nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" + getExtraNativeLibDirs(appRootPath) + ":" + appBinPath + ":" + appLibPath;
115 }
116
117 PathManager::PathManager() :
118         rootFD(-1)
119 {
120         // set runtime path
121         runtimePath = getAbsolutePath(__RUNTIME_DIR);
122         platformAssembliesPaths.push_back(runtimePath);
123
124         // set tizenfx path
125         char* tmp = vconf_get_str(__TIZEN_API_PATH_KEY);
126         if (tmp) {
127                 tizenfxPath = std::string(tmp);
128                 _DBG("Device API Directory is set by vconf : %s", tmp);
129                 free(tmp);
130         } else {
131                 tizenfxPath = getAbsolutePath(__DEVICE_API_DIR);
132         }
133         platformAssembliesPaths.push_back(tizenfxPath);
134         platformAssembliesPaths.push_back(tizenfxPath + "/ref");
135
136         // set temporal application root path for candidate process
137         rootFD = open("/proc/self", O_DIRECTORY);
138         if (rootFD < 0) {
139                 _ERR("Failed to open /proc/self");
140                 throw std::ios_base::failure("Fail to open /proc/self");
141         }
142
143         appRootPath = std::string("/proc/self/fd/") + std::to_string(rootFD);
144         updateAppRelatedPath(appRootPath);
145
146         _INFO("Path manager created successfully");
147 }
148
149 PathManager::~PathManager()
150 {
151         _INFO("Path manager destroyed");
152 }
153
154 // paths: ":" separated muliple path.
155 void PathManager::addPlatformAssembliesPaths(const std::string& paths, bool isHighPriority)
156 {
157         std::vector<std::string>::iterator it;
158         std::vector<std::string> pathVec;
159         splitPath(paths, pathVec);
160
161         for (unsigned int i = 0; i < pathVec.size(); i++) {
162                 pathVec[i] = getAbsolutePath(pathVec[i]);
163         }
164
165         if (isHighPriority) {
166                 it = platformAssembliesPaths.begin();
167         } else {
168                 it = platformAssembliesPaths.end();
169         }
170
171         platformAssembliesPaths.insert(it, pathVec.begin(), pathVec.end());
172 }
173
174 void PathManager::setAppRootPath(const std::string& rootPath)
175 {
176         // override root path for application launch mode (candidate / standalone mode)
177         if (rootFD >= 0) {
178                 int tmpFD = open(rootPath.c_str(), O_DIRECTORY);
179                 dup3(tmpFD, rootFD, O_CLOEXEC);
180                 if (tmpFD >= 0)
181                         close(tmpFD);
182         }
183
184         appRootPath = getAbsolutePath(rootPath);
185         updateAppRelatedPath(appRootPath);
186 }
187
188 const std::string& PathManager::getRuntimePath()
189 {
190         return runtimePath;
191 }
192
193 const std::string& PathManager::getTizenFXPath()
194 {
195         return tizenfxPath;
196 }
197
198 // return platform assembly paths
199 const std::vector<std::string>& PathManager::getPlatformAssembliesPaths()
200 {
201         return platformAssembliesPaths;
202 }
203
204 // return app root path
205 const std::string& PathManager::getAppRootPath()
206 {
207         return appRootPath;
208 }
209
210 // return .tac_symlink path
211 const std::string& PathManager::getAppTacPath()
212 {
213         return appTacPath;
214 }
215
216 // return dll searching paths for app
217 const std::string& PathManager::getAppPaths()
218 {
219         return appPaths;
220 }
221
222 // return ni dll searching paths for app
223 const std::string& PathManager::getAppNIPaths()
224 {
225         return appNIPaths;
226 }
227
228 // return native dll searching paths for app 
229 const std::string& PathManager::getNativeDllSearchingPaths()
230 {
231         return nativeDllSearchingPaths;
232 }
233