donot create coredump file for unhandled exception
[platform/core/dotnet/launcher.git] / NativeLauncher / util / utils.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 <dirent.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <limits.h>
21 #include <strings.h>
22
23 #include <cstdlib>
24 #include <cstring>
25 #include <algorithm>
26 #include <unordered_map>
27 #include <vector>
28 #include <iterator>
29 #include <sstream>
30 #include <map>
31
32 #include "utils.h"
33 #include "path_manager.h"
34
35 static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length)
36 {
37         return static_cast<int>(a.length()) - length >= aOffset &&
38                 static_cast<int>(b.length()) - length >= bOffset &&
39                 std::equal(b.begin() + bOffset, b.begin() + bOffset + length, a.begin() + aOffset,
40                         [](unsigned char a, unsigned char b)
41                         { return std::tolower(a) == std::tolower(b); });
42 }
43
44 bool isManagedAssembly(const std::string& fileName)
45 {
46         return (iCompare(fileName, fileName.size()-4, ".dll", 0, 4) ||
47                         iCompare(fileName, fileName.size()-4, ".exe", 0, 4)) &&
48                         !isNativeImage(fileName);
49 }
50
51 bool isNativeImage(const std::string& fileName)
52 {
53         return iCompare(fileName, fileName.size()-7, ".ni", 0, 3);
54 }
55
56 std::string readSelfPath()
57 {
58         char buff[PATH_MAX];
59         ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
60         if (len != -1) {
61                 buff[len] = '\0';
62                 return std::string(buff);
63         }
64
65         return "";
66 }
67
68 std::string concatPath(const std::string& path1, const std::string& path2)
69 {
70         std::string path(path1);
71         if (path.back() == PATH_SEPARATOR) {
72                 path.append(path2);
73         } else {
74                 path += PATH_SEPARATOR;
75                 path.append(path2);
76         }
77
78         return path;
79 }
80
81 void splitPath(const std::string& path, std::vector<std::string>& out)
82 {
83         std::istringstream ss(path);
84         std::string token;
85
86         while (std::getline(ss, token, ':')) {
87                 out.push_back(token);
88         }
89 }
90
91 std::string absolutePath(const std::string& path)
92 {
93         std::string absPath;
94         char realPath[PATH_MAX];
95         if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
96                 absPath.assign(realPath);
97
98         return absPath;
99 }
100
101 std::string baseName(const std::string& path)
102 {
103         auto pos = path.find_last_of(PATH_SEPARATOR);
104         if (pos != std::string::npos)
105                 return path.substr(0, pos);
106         else
107                 return std::string(".");
108         return path;
109 }
110
111 bool isFileExist(const std::string& path)
112 {
113         struct stat sb;
114         return stat(path.c_str(), &sb) == 0;
115 }
116
117 std::string stripNiDLL(const std::string& path)
118 {
119         std::string niPath(path);
120         if (path.size() < 5) return niPath;
121         if (!strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
122                 niPath = path.substr(0, path.size()-4);
123         else if (!strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
124                 niPath = path.substr(0, path.size()-4);
125
126         if (!strncasecmp(niPath.c_str() + niPath.size() - 3, ".ni", 3))
127                 return niPath.substr(0, niPath.size()-3);
128
129         return niPath;
130 }
131
132 void assembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
133 {
134         std::map<std::string, std::string> assemblyList;
135         std::map<std::string, std::string> tmpList;
136
137         auto reader = [&assemblyList, &tmpList] (const std::string& path, const char* name) {
138                 if (isManagedAssembly(path) || isNativeImage(path)) {
139                         std::string dllName = stripNiDLL(name);
140                         std::pair<std::map<std::string, std::string>::iterator, bool> ret;
141                         ret = tmpList.insert(std::pair<std::string, std::string>(dllName, path));
142                         if (ret.second == false) {
143                                 if (isNativeImage(path))
144                                         tmpList[dllName] = path;
145                         }
146                 }
147         };
148
149         for (auto directory : directories) {
150                 scanFilesInDir(directory.c_str(), reader, 1);
151                 // merge scaned dll list to tpa list.
152                 // if the dll is already exist in the list, that is skipped.
153                 assemblyList.insert(tmpList.begin(), tmpList.end());
154         }
155
156         std::map<std::string, std::string>::iterator it;
157         for (it = assemblyList.begin(); it != assemblyList.end(); it++)
158                 tpaList += it->second + ':';
159
160         if (tpaList.back() == ':')
161                 tpaList.pop_back();
162 }
163
164 void scanFilesInDir(const std::string& directory, FileReader reader, unsigned int depth)
165 {
166         DIR *dir;
167         struct dirent* entry;
168         bool isDir;
169
170         dir = opendir(directory.c_str());
171
172         if (dir == nullptr)
173                 return;
174
175         std::vector<std::string> innerDirectories;
176
177         while ((entry = readdir(dir)) != nullptr) {
178                 isDir = false;
179                 std::string path = concatPath(directory, entry->d_name);
180                 switch (entry->d_type) {
181                         case DT_REG: break;
182                         case DT_DIR:
183                                 isDir = true;
184                                 break;
185                         case DT_LNK:
186                         case DT_UNKNOWN:
187                                 struct stat sb;
188                                 if (stat(path.c_str(), &sb) == -1)
189                                         continue;
190
191                                 if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
192                                         break;
193                         default:
194                                 continue;
195                 }
196                 if (!isDir)
197                         reader(path, entry->d_name);
198                 else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
199                         innerDirectories.push_back(path);
200         }
201
202         if (depth != 0)
203                 for (auto& d : innerDirectories)
204                         scanFilesInDir(d.c_str(), reader, depth-1);
205
206         closedir(dir);
207 }
208