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