2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
28 #include <unordered_map>
35 #include "path_manager.h"
38 static pthread_t loggingThread;
40 static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length)
42 return static_cast<int>(a.length()) - length >= aOffset &&
43 static_cast<int>(b.length()) - length >= bOffset &&
44 std::equal(b.begin() + bOffset, b.begin() + bOffset + length, a.begin() + aOffset,
45 [](unsigned char a, unsigned char b)
46 { return std::tolower(a) == std::tolower(b); });
49 bool isManagedAssembly(const std::string& fileName)
51 return (iCompare(fileName, fileName.size()-4, ".dll", 0, 4) ||
52 iCompare(fileName, fileName.size()-4, ".exe", 0, 4)) &&
53 !isNativeImage(fileName);
56 bool isNativeImage(const std::string& fileName)
58 return iCompare(fileName, fileName.size()-7, ".ni", 0, 3);
61 std::string readSelfPath()
64 ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
67 return std::string(buff);
73 std::string concatPath(const std::string& path1, const std::string& path2)
75 std::string path(path1);
76 if (path.back() == PATH_SEPARATOR) {
79 path += PATH_SEPARATOR;
86 void splitPath(const std::string& path, std::vector<std::string>& out)
88 std::istringstream ss(path);
91 while (std::getline(ss, token, ':')) {
96 std::string absolutePath(const std::string& path)
99 char realPath[PATH_MAX];
100 if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
101 absPath.assign(realPath);
106 std::string baseName(const std::string& path)
108 auto pos = path.find_last_of(PATH_SEPARATOR);
109 if (pos != std::string::npos)
110 return path.substr(0, pos);
112 return std::string(".");
116 bool isFileExist(const std::string& path)
119 return stat(path.c_str(), &sb) == 0;
122 std::string stripNiDLL(const std::string& path)
124 std::string niPath(path);
125 if (path.size() < 5) return niPath;
126 if (!strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
127 niPath = path.substr(0, path.size()-4);
128 else if (!strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
129 niPath = path.substr(0, path.size()-4);
131 if (!strncasecmp(niPath.c_str() + niPath.size() - 3, ".ni", 3))
132 return niPath.substr(0, niPath.size()-3);
137 void assembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
139 std::map<std::string, std::string> assemblyList;
140 std::map<std::string, std::string> tmpList;
142 auto reader = [&assemblyList, &tmpList] (const std::string& path, const char* name) {
143 if (isManagedAssembly(path) || isNativeImage(path)) {
144 std::string dllName = stripNiDLL(name);
145 std::pair<std::map<std::string, std::string>::iterator, bool> ret;
146 ret = tmpList.insert(std::pair<std::string, std::string>(dllName, path));
147 if (ret.second == false) {
148 if (isNativeImage(path))
149 tmpList[dllName] = path;
154 for (auto directory : directories) {
155 scanFilesInDir(directory.c_str(), reader, 1);
156 // merge scaned dll list to tpa list.
157 // if the dll is already exist in the list, that is skipped.
158 assemblyList.insert(tmpList.begin(), tmpList.end());
161 std::map<std::string, std::string>::iterator it;
162 for (it = assemblyList.begin(); it != assemblyList.end(); it++)
163 tpaList += it->second + ':';
165 if (tpaList.back() == ':')
169 void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth)
172 struct dirent* entry;
175 dir = opendir(directory.c_str());
180 std::vector<std::string> innerDirectories;
182 while ((entry = readdir(dir)) != nullptr) {
184 std::string path = concatPath(directory, entry->d_name);
185 switch (entry->d_type) {
193 if (stat(path.c_str(), &sb) == -1)
196 if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
202 reader(path, entry->d_name);
203 else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
204 innerDirectories.push_back(path);
208 for (auto& d : innerDirectories)
209 scanFilesInDir(d.c_str(), reader, depth-1);
216 static void *stdlog(void*)
221 while ((readSize = read(__pfd[0], buf, sizeof buf - 1)) > 0) {
222 if (buf[readSize - 1] == '\n') {
236 int runLoggingThread()
238 if (setvbuf(stdout, NULL, _IOLBF, 0) < 0) {
239 _DBG("fail to make stdout line-buffered");
243 if (setvbuf(stderr, NULL, _IONBF, 0) < 0) {
244 _DBG("make stderr unbuffered");
248 /* create the pipe and redirect stdout and stderr */
249 if (pipe(__pfd) < 0) {
250 _DBG("fail to create pipe for logging");
255 if (dup2(__pfd[1], 1) == -1) {
256 _DBG("fail to duplicate fd to stdout");
261 if (dup2(__pfd[1], 2) == -1) {
262 _DBG("fail to duplicate fd to stderr");
268 /* spawn the logging thread */
269 if (pthread_create(&loggingThread, 0, stdlog, 0) != 0) {
270 _DBG("fail to create pthread");
274 if (pthread_detach(loggingThread) != 0) {
275 _DBG("fail to detach pthread");