Modify tizen coding style
[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
18 #include <dirent.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <limits.h>
22 #include <strings.h>
23
24 #include <cstdlib>
25 #include <cstring>
26 #include <algorithm>
27 #include <unordered_map>
28 #include <vector>
29 #include <iterator>
30 #include <sstream>
31
32 #include "utils.h"
33
34 bool iCompare(const std::string& a, const std::string& b)
35 {
36         return a.length() == b.length() &&
37                 std::equal(b.begin(), b.end(), a.begin(),
38                         [](unsigned char a, unsigned char b)
39                         { return std::tolower(a) == std::tolower(b); });
40 }
41
42 bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length)
43 {
44         return static_cast<int>(a.length()) - length >= aOffset &&
45                 static_cast<int>(b.length()) - length >= bOffset &&
46                 std::equal(b.begin() + bOffset, b.begin() + bOffset + length, a.begin() + aOffset,
47                         [](unsigned char a, unsigned char b)
48                         { return std::tolower(a) == std::tolower(b); });
49 }
50
51 bool isManagedAssembly(const std::string& fileName)
52 {
53         return iCompare(fileName, fileName.size()-4, ".dll", 0, 4) ||
54                 iCompare(fileName, fileName.size()-4, ".exe", 0, 4);
55 }
56
57 bool isNativeImage(const std::string& fileName)
58 {
59         return iCompare(fileName, fileName.size()-7, ".ni", 0, 3);
60 }
61
62 std::string readSelfPath()
63 {
64         char buff[PATH_MAX];
65         ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
66         if (len != -1) {
67                 buff[len] = '\0';
68                 return std::string(buff);
69         }
70
71         return "";
72 }
73
74 std::string concatPath(const std::string& path1, const std::string& path2)
75 {
76         std::string path(path1);
77         if (path.back() == PATH_SEPARATOR) {
78                 path.append(path2);
79         } else {
80                 path += PATH_SEPARATOR;
81                 path.append(path2);
82         }
83
84         return path;
85 }
86
87 void appendPath(std::string& path1, const std::string& path2)
88 {
89         if (path1.back() == PATH_SEPARATOR) {
90                 path1.append(path2);
91         } else {
92                 path1 += PATH_SEPARATOR;
93                 path1.append(path2);
94         }
95 }
96
97 std::string absolutePath(const std::string& path)
98 {
99         std::string absPath;
100         char realPath[PATH_MAX];
101         if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
102                 absPath.assign(realPath);
103
104         return absPath;
105 }
106
107 std::string baseName(const std::string& path)
108 {
109         auto pos = path.find_last_of(PATH_SEPARATOR);
110         if (pos != std::string::npos)
111                 return path.substr(0, pos);
112         else
113                 return std::string(".");
114         return path;
115 }
116
117 bool endWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& fileName)
118 {
119         std::string::size_type len1 = str1.length();
120         std::string::size_type len2 = str2.length();
121         if (len2 > len1)
122                 return false;
123
124         int i = 0;
125         bool result = std::all_of(str1.cend() - len2, str1.end(),
126                                 [&i, &str2] (char x) {
127                                         return std::tolower(x) == std::tolower(str2[i++]);
128                                 });
129         if (result)
130                 fileName = str1.substr(0, len1 - len2);
131
132         return result;
133 }
134
135 bool fileNotExist(const std::string& path)
136 {
137         struct stat sb;
138         return stat(path.c_str(), &sb) != 0;
139 }
140
141 #ifdef NOT_USE_FUNCTION
142 static bool extCheckAndGetFileNameIfExist(const std::string& dir, const std::string& ext, struct dirent* entry, std::string& fileName)
143 {
144         std::string fName(entry->d_name);
145         if (fName.length() < ext.length() ||
146                         fHame.compare(fName.length() - ext.length(), ext.length(), ext) != 0) {
147                 return false;
148
149         std::string fullName = concatPath(dir, entry->d_name);
150         switch (entry->d_type) {
151                 case DT_REG: break;
152                 case DT_LNK:
153                 case DT_UNKNOWN:
154                         if (fileNotExist(fullName))
155                                 return false;
156                 default:
157                         return false;
158         }
159
160         fileName = fullName;
161
162         return true;
163 }
164 #endif
165
166 std::string stripNiDLL(const std::string& path)
167 {
168         std::string niPath(path);
169         if (path.size() < 5) return niPath;
170         if (!strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
171                 niPath = path.substr(0, path.size()-4);
172         else if (!strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
173                 niPath = path.substr(0, path.size()-4);
174
175         if (!strncasecmp(niPath.c_str() + niPath.size() - 3, ".ni", 3))
176                 return niPath.substr(0, niPath.size()-3);
177
178         return niPath;
179 }
180
181 std::string joinStrings(const std::vector<std::string>& strings, const char* const delimeter)
182 {
183         switch (strings.size()) {
184                 case 0:
185                         return "";
186                 case 1:
187                         return strings[0];
188                 default:
189                         std::ostringstream os;
190                         std::copy(strings.begin(), strings.end()-1, std::ostream_iterator<std::string>(os, delimeter));
191                         os << *strings.rbegin();
192                         return os.str();
193         }
194 }
195
196 struct AssemblyFile {
197         std::string noExt;
198         std::string ext;
199 };
200
201 bool operator == (const AssemblyFile& lhs, const AssemblyFile& rhs)
202 {
203         return lhs.noExt == rhs.noExt && lhs.ext == rhs.ext;
204 }
205
206 namespace std {
207         template<>
208         struct hash<AssemblyFile> {
209                 std::size_t operator () (const AssemblyFile& f) const {
210                         const std::size_t h1 = std::hash<std::string>{}(f.noExt);
211                         const std::size_t h2 = std::hash<std::string>{}(f.ext);
212
213                         return h1 ^ (h2 << 1);
214                 }
215         };
216 }
217
218 void assembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
219 {
220         std::map<std::string, std::string> assemblyList;
221         std::map<std::string, std::string> tmpList;
222
223         auto reader = [&assemblyList, &tmpList] (const char* path, const char* name) {
224                 std::string pathStr(path);
225                 if (isManagedAssembly(pathStr)) {
226                         std::string dllName = stripNiDLL(name);
227                         std::pair<std::map<std::string, std::string>::iterator, bool> ret;
228                         ret = tmpList.insert(std::pair<std::string, std::string>(dllName, pathStr));
229                         if (ret.second == false) {
230                                 if (isNativeImage(pathStr))
231                                         tmpList[dllName] = pathStr;
232                         }
233                 }
234         };
235
236         for (auto directory : directories) {
237                 scanFilesInDir(directory.c_str(), reader, 1);
238                 // merge scaned dll list to tpa list.
239                 // if the dll is already exist in the list, that is skipped.
240                 assemblyList.insert(tmpList.begin(), tmpList.end());
241         }
242
243         std::map<std::string, std::string>::iterator it;
244         for (it = assemblyList.begin(); it != assemblyList.end(); it++)
245                 tpaList += it->second + ':';
246
247         if (tpaList.back() == ':')
248                 tpaList.pop_back();
249 }
250
251 void scanFilesInDir(const char* directory, FileReader reader, unsigned int depth)
252 {
253         DIR *dir;
254         struct dirent* entry;
255         bool isDir;
256
257         dir = opendir(directory);
258
259         if (dir == nullptr)
260                 return;
261
262         std::vector<std::string> innerDirectories;
263
264         while ((entry = readdir(dir)) != nullptr) {
265                 isDir = false;
266                 std::string path = concatPath(directory, entry->d_name);
267                 switch (entry->d_type) {
268                         case DT_REG: break;
269                         case DT_DIR:
270                                 isDir = true;
271                                 break;
272                         case DT_LNK:
273                         case DT_UNKNOWN:
274                                 struct stat sb;
275                                 if (stat(path.c_str(), &sb) == -1)
276                                         continue;
277
278                                 if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
279                                         break;
280                         default:
281                                 continue;
282                 }
283                 if (!isDir)
284                         reader(path.c_str(), entry->d_name);
285                 else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
286                         innerDirectories.push_back(path);
287         }
288
289         if (depth != 0)
290                 for (auto& d : innerDirectories)
291                         scanFilesInDir(d.c_str(), reader, depth-1);
292
293         closedir(dir);
294 }