[Refactoring] Code cleanup and remove duplicate methods
[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 <fcntl.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <limits.h>
22 #include <strings.h>
23 #include <pkgmgr_installer_info.h>
24 #include <sys/smack.h>
25 #include <sys/prctl.h>
26
27 #include <openssl/evp.h>
28 #include <openssl/crypto.h>
29
30 #include <mntent.h>
31
32 #include <cstdlib>
33 #include <cstring>
34 #include <algorithm>
35 #include <unordered_map>
36 #include <vector>
37 #include <iterator>
38 #include <fstream>
39 #include <sstream>
40 #include <map>
41 #include <iomanip>
42
43 #include "log.h"
44 #include "utils.h"
45 #include "path_manager.h"
46 #include "r2r_checker.h"
47
48 static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length)
49 {
50         return static_cast<int>(a.length()) - length >= aOffset &&
51                 static_cast<int>(b.length()) - length >= bOffset &&
52                 std::equal(b.begin() + bOffset, b.begin() + bOffset + length, a.begin() + aOffset,
53                         [](unsigned char a, unsigned char b)
54                         { return std::tolower(a) == std::tolower(b); });
55 }
56
57 bool isManagedAssembly(const std::string& fileName)
58 {
59         return iCompare(fileName, fileName.size()-4, ".dll", 0, 4) && !isR2RImage(fileName);
60 }
61
62 std::string concatPath(const std::string& path1, const std::string& path2)
63 {
64         std::string path(path1);
65         if (path.back() == PATH_SEPARATOR) {
66                 path.append(path2);
67         } else {
68                 path += PATH_SEPARATOR;
69                 path.append(path2);
70         }
71
72         return path;
73 }
74
75 void splitPath(const std::string& path, std::vector<std::string>& out)
76 {
77         std::istringstream ss(path);
78         std::string token;
79
80         while (std::getline(ss, token, ':')) {
81                 if (token != "") {
82                         out.push_back(token);
83                 }
84         }
85 }
86
87 std::string getAbsolutePath(const std::string& path)
88 {
89         std::string absPath;
90         char *realPath = realpath(path.c_str(), NULL);
91         if (realPath) {
92                 absPath.assign(realPath);
93                 free(realPath);
94         }
95
96         return absPath;
97 }
98
99 std::string getRootPath(const std::string& pkgId)
100 {
101         int ret = 0;
102         char *path = 0;
103         std::string rootPath;
104
105         pkgmgrinfo_pkginfo_h pkg_handle;
106         ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
107         if (ret != 0) {
108                 return rootPath;
109         }
110
111         ret = pkgmgrinfo_pkginfo_get_root_path(pkg_handle, &path);
112         if (ret != PMINFO_R_OK) {
113                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
114                 return rootPath;
115         }
116         rootPath = path;
117         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
118
119         return rootPath;
120 }
121
122 std::string getExecName(const std::string& pkgId)
123 {
124         char *exec = NULL;
125         char *appId = 0;
126         std::string execName;
127
128         pkgmgrinfo_pkginfo_h pkg_handle;
129         int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
130         if (ret != 0) {
131                 return execName;
132         }
133
134         ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId);
135         if (ret != PMINFO_R_OK) {
136                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
137                 return execName;
138         }
139
140         pkgmgrinfo_appinfo_h app_handle;
141         ret = pkgmgrGetAppInfo(appId, &app_handle);
142         if (ret != 0) {
143                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
144                 return execName;
145         }
146
147         ret = pkgmgrinfo_appinfo_get_exec(app_handle, &exec);
148         if (ret != PMINFO_R_OK) {
149                 pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
150                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
151                 return execName;
152         }
153         execName = std::string(exec).substr(std::string(exec).rfind('/') + 1);
154
155         pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
156         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
157
158         return execName;
159 }
160
161 std::string getAppType(const std::string& pkgId)
162 {
163         char *appId = 0;
164         char *type = 0;
165         std::string appType;
166
167         pkgmgrinfo_pkginfo_h pkg_handle;
168         int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
169         if (ret != 0) {
170                 return appType;
171         }
172
173         ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId);
174         if (ret != PMINFO_R_OK) {
175                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
176                 return appType;
177         }
178
179         pkgmgrinfo_appinfo_h app_handle;
180         ret = pkgmgrGetAppInfo(appId, &app_handle);
181         if (ret != 0) {
182                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
183                 return appType;
184         }
185
186         ret = pkgmgrinfo_appinfo_get_apptype(app_handle, &type);
187         if (ret != PMINFO_R_OK) {
188                 pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
189                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
190                 return appType;
191         }
192         appType = type;
193
194         pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
195         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
196
197         return appType;
198 }
199
200 std::string getMetadataValue(const std::string& pkgId, const std::string& key)
201 {
202         char *value = NULL;
203         char *appId = 0;
204         std::string metadataValue;
205
206         pkgmgrinfo_pkginfo_h pkg_handle;
207         int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
208         if (ret != 0) {
209                 return metadataValue;
210         }
211
212         ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId);
213         if (ret != PMINFO_R_OK) {
214                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
215                 return metadataValue;
216         }
217
218         pkgmgrinfo_appinfo_h app_handle;
219         ret = pkgmgrGetAppInfo(appId, &app_handle);
220         if (ret != 0) {
221                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
222                 return metadataValue;
223         }
224
225         ret = pkgmgrinfo_appinfo_get_metadata_value(app_handle, key.c_str(), &value);
226         if (ret != PMINFO_R_OK) {
227                 pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
228                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
229                 return metadataValue;
230         }
231         metadataValue = std::string(value);
232
233         pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
234         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
235
236         return metadataValue;
237 }
238
239 bool isReadOnlyArea(const std::string& path)
240 {
241         FILE *f = NULL;
242         struct mntent *m = NULL;
243
244         // "/opt/usr" is mounted to "RW" only
245         if (path.find("/opt/usr") != std::string::npos) {
246                 return false;
247         }
248
249         // check whether "/" is mounted to RO or not
250         f = setmntent("/proc/mounts", "r");
251         if (!f) {
252                 // return true for fail case to generate NI files under RW area.
253                 return true;
254         }
255
256         while((m = getmntent(f))) {
257                 if (m->mnt_dir != NULL && strcmp(m->mnt_dir, "/") == 0 &&
258                         m->mnt_opts != NULL && strstr(m->mnt_opts, "ro,") != NULL) {
259                         endmntent(f);
260                         return true;
261                 }
262         }
263         endmntent(f);
264         return false;
265
266 }
267
268 std::string getBaseName(const std::string& path)
269 {
270         auto pos = path.find_last_of(PATH_SEPARATOR);
271         if (pos != std::string::npos)
272                 return path.substr(0, pos);
273         else
274                 return std::string(".");
275         return path;
276 }
277
278 std::string replaceAll(const std::string& str, const std::string& pattern, const std::string& replace)
279 {
280         std::string result = str;
281         std::string::size_type pos = 0;
282         std::string::size_type offset = 0;
283
284         while ((pos = result.find(pattern, offset)) != std::string::npos) {
285                 result.replace(result.begin() + pos, result.begin() + pos + pattern.size(), replace);
286                 offset = pos + replace.size();
287         }
288
289         return result;
290 }
291
292 std::string changeExtension(const std::string& path, const std::string& from, const std::string& to)
293 {
294         return path.substr(0, path.rfind(from)) + to;
295 }
296
297 bool isFile(const std::string& path)
298 {
299         struct stat sb;
300         return lstat(path.c_str(), &sb) == 0;
301 }
302
303 bool isSymlinkFile(const std::string& path)
304 {
305         struct stat sb;
306         if (lstat(path.c_str(), &sb) != 0) {
307                 return false;
308         }
309         return (sb.st_mode & S_IFMT) == S_IFLNK;
310 }
311
312 bool isDirectory(const std::string& path)
313 {
314         struct stat sb;
315         if (stat(path.c_str(), &sb) != 0) {
316                 return false;
317         }
318         return (sb.st_mode & S_IFMT) == S_IFDIR;
319 }
320
321 std::string getAssemblyNameFromPath(const std::string& path)
322 {
323         std::string ret(getFileName(path));
324
325         if (ret.find_last_of(".") == std::string::npos)
326                 return ret;
327         ret.erase(ret.find_last_of("."));
328
329         if (ret.size() > 3 && std::equal(ret.begin() + ret.size() - 3, ret.end(), ".ni"))
330                 ret.erase(ret.size() - 3);
331
332         return ret;
333 }
334
335 void addAssembliesFromDirectories(const std::vector<std::string>& directories, std::string& list)
336 {
337         std::vector<std::string> assems;
338         std::unordered_map<std::string, std::string> assemPaths;
339
340         auto reader = [&assems, &assemPaths](const std::string& path, const std::string& filename) {
341                 if (isManagedAssembly(filename) || isR2RImage(filename)) {
342                         std::string assem = getAssemblyNameFromPath(filename);
343
344                         if (assemPaths.count(assem) == 0) {
345                                 assems.push_back(assem);
346                                 assemPaths[assem] = path;
347                         } else if (isManagedAssembly(assemPaths[assem]) && isR2RImage(filename)) {
348                                 // Update only if a native image is found in the same directory.
349                                 // For example, if we have two directories = { X, Y } where X contains A.dll and
350                                 // Y contains both A.dll and A.ni.dll, always A.dll in X will be used.
351                                 if (getBaseName(assemPaths[assem]).compare(getBaseName(path)) == 0)
352                                         assemPaths[assem] = path;
353                         }
354                 }
355         };
356         for (auto& directory : directories)
357                 scanFilesInDirectory(directory, reader, 0);
358
359         if (!list.empty() && list.back() != ':')
360                 list.push_back(':');
361
362         for (auto& assem : assems)
363                 list += assemPaths[assem] + ":";
364
365         if (list.back() == ':')
366                 list.pop_back();
367 }
368
369 void scanFilesInDirectory(const std::string& directory, FileReader reader, unsigned int depth)
370 {
371         DIR *dir;
372         struct dirent* entry;
373         bool isDir;
374
375         dir = opendir(directory.c_str());
376
377         if (dir == nullptr)
378                 return;
379
380         std::vector<std::string> innerDirectories;
381
382         while ((entry = readdir(dir)) != nullptr) {
383                 isDir = false;
384                 std::string path = concatPath(directory, entry->d_name);
385                 switch (entry->d_type) {
386                         case DT_REG: break;
387                         case DT_DIR:
388                                 isDir = true;
389                                 break;
390                         // symlink is added to the list even if there is no original file.
391                         // It used to remove broken symlinks related to TAC
392                         case DT_LNK:
393                                 break;
394                         case DT_UNKNOWN:
395                                 continue;
396                         default:
397                                 continue;
398                 }
399                 if (!isDir)
400                         reader(path, entry->d_name);
401                 else if (depth > 0 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
402                         innerDirectories.push_back(path);
403         }
404
405         if (depth > 0)
406                 for (auto& d : innerDirectories)
407                         scanFilesInDirectory(d, reader, depth - 1);
408
409         closedir(dir);
410 }
411
412 void copySmackAndOwnership(const std::string& fromPath, const std::string& toPath, bool isSymlink)
413 {
414         char* label = NULL;
415         struct stat info;
416
417         if (isSymlink) {
418                 // change smack label for symbolic link.
419                 if (smack_lgetlabel(fromPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) {
420                         if (smack_lsetlabel(toPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) {
421                                 _SERR("Fail to set smack label");
422                         }
423                         free(label);
424                 }
425
426                 // change owner and groupsfor symbolic link.
427                 // change mode is skipped for symlink because permission of symlink file is meaningless.
428                 if (!lstat(fromPath.c_str(), &info)) {
429                         if (lchown(toPath.c_str(), info.st_uid, info.st_gid) == -1)
430                                 _SERR("Failed to change owner and group name");
431                 }
432         } else {
433                 // change smack label
434                 if (smack_getlabel(fromPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) {
435                         if (smack_setlabel(toPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) {
436                                 _SERR("Fail to set smack label");
437                         }
438                         free(label);
439                 }
440
441                 // change owner, groups and mode for generated ni file.
442                 if (!stat(fromPath.c_str(), &info)) {
443                         if (chown(toPath.c_str(), info.st_uid, info.st_gid) == -1)
444                                 _SERR("Failed to change owner and group name");
445                         if (chmod(toPath.c_str(), info.st_mode) == -1)
446                                 _SERR("Failed to change mode");
447                 }
448         }
449 }
450
451 static bool setOwnership(const bf::path& path, uid_t uid, gid_t gid)
452 {
453         int fd = open(path.c_str(), O_RDONLY);
454         if (fd < 0) {
455                 _ERR("Can't open directory: %s", path.c_str());
456                 return false;
457         }
458         int ret = fchown(fd, uid, gid);
459         close(fd);
460         if (ret != 0) {
461                 _ERR("Failed to change owner of: %s", path.c_str());
462                 return false;
463         }
464         return true;
465 }
466
467 static bool setDirPermissions(const bf::path& path, bf::perms permissions)
468 {
469         bs::error_code error;
470         bf::permissions(path, permissions, error);
471         if (error) {
472                 _ERR("Failed to set permissions for directory: %s, %s", path.c_str(), error.message().c_str());
473                 return false;
474         }
475         return true;
476 }
477
478 static bool setDirOwnershipAndPermissions(const bf::path& path, bf::perms permissions, uid_t uid, gid_t gid)
479 {
480         if (!setOwnership(path, uid, gid)) {
481                 _ERR("Failed to change owner: %s, (uid: %d, gid: %d)", path.c_str(), uid, gid);
482                 return false;
483         }
484         if (!setDirPermissions(path, permissions)) {
485                 _ERR("Failed to change permission: %s, (%d)", path.c_str(), permissions);
486                 return false;
487         }
488         return true;
489 }
490
491 static bool copyOwnershipAndPermissions(const bf::path& path, const bf::path& path2)
492 {
493         if (!exist(path)) {
494                 _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str());
495                 return false;
496         }
497         bs::error_code error;
498         bf::perms permissions = bf::status(path, error).permissions();
499         if (error) {
500                 _ERR("Failed to copy ownership and permissions : %s", error.message().c_str());
501                 return false;
502         }
503         struct stat stats;
504         if (stat(path.c_str(), &stats) != 0) {
505                 return false;
506         }
507         if (!setDirOwnershipAndPermissions(path2, permissions, stats.st_uid, stats.st_gid)) {
508                 _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str());
509                 return false;
510         }
511         return true;
512 }
513
514 bool exist(const bf::path& path)
515 {
516         bs::error_code error;
517         int ret = bf::exists(path, error);
518         if (error) {
519                 if ((error.value() != bs::errc::success) && (error.value() != bs::errc::no_such_file_or_directory)) {
520                         _ERR("Failed to check %s exists : %s", path.c_str(), error.message().c_str());
521                 }
522         }
523         return ret;
524 }
525
526 bool createDir(const bf::path& path)
527 {
528         if (exist(path)) {
529                 return true;
530         }
531         bs::error_code error;
532         bf::create_directories(path, error);
533         if (error) {
534                 _ERR("Failed to create directory: %s", error.message().c_str());
535                 return false;
536         }
537         return true;
538 }
539
540 bool copyDir(const bf::path& path1, const bf::path& path2, FSFlag flags)
541 {
542         try {
543                 // Check whether the function call is valid
544                 if (!exist(path1) || !bf::is_directory(path1)) {
545                         _ERR("Source directory %s does not exist or is not a directory", path1.c_str());
546                         return false;
547                 }
548                 if (!exist(path2)) {
549                         // Create the destination directory
550                         if (!createDir(path2)) {
551                                 _ERR("Unable to create destination directory %s", path2.c_str());
552                                 return false;
553                         }
554                         if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) {
555                                 copyOwnershipAndPermissions(path1, path2);
556                         }
557                 } else {
558                         if (!(flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE))) {
559                                 _ERR("Destination directory %s already exists", path2.c_str());
560                                 return false;
561                         }
562                         if (flags & (FS_MERGE_OVERWRITE | FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS)) {
563                                 copyOwnershipAndPermissions(path1, path2);
564                         }
565                 }
566         } catch (const bf::filesystem_error& error) {
567                 _ERR("Failed to copy directory: %s", error.what());
568                 return false;
569         }
570
571         // Iterate through the source directory
572         try {
573                 for (bf::directory_iterator file(path1); file != bf::directory_iterator(); ++file) {
574                         bf::path current(file->path());
575                         bf::path target = path2 / current.filename();
576                         if (bf::is_symlink(bf::symlink_status(current))) {
577                                 if ((flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE)) && exist(target)) {
578                                         continue;
579                                 }
580                                 bs::error_code error;
581                                 bf::copy_symlink(current, target, error);
582                                 if (error) {
583                                         _ERR("Failed to copy symlink: %s, %s", current.c_str(), error.message().c_str());
584                                         return false;
585                                 }
586                         } else if (bf::is_directory(current)) {
587                                 // Found directory: Recursion
588                                 if (!copyDir(current, target, flags)) {
589                                         return false;
590                                 }
591                         } else {
592                                 if ((flags & FS_MERGE_SKIP) && exist(target)) {
593                                         continue;
594                                 }
595                                 bf::path destination = target;
596                                 if (flags & FS_COMMIT_COPY_FILE) {
597                                         destination = bf::unique_path(target.parent_path() / "%%%%-%%%%-%%%%-%%%%");
598                                 }
599                                 if (flags & FS_MERGE_OVERWRITE) {
600                                         bf::copy_file(current, destination, bf::copy_option::overwrite_if_exists);
601                                 } else {
602                                         bf::copy_file(current, destination);
603                                 }
604                                 if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) {
605                                         copyOwnershipAndPermissions(current, destination);
606                                 }
607                                 if (flags & FS_COMMIT_COPY_FILE) {
608                                         if (flags & FS_MERGE_OVERWRITE) {
609                                                 bf::remove(target);
610                                         }
611                                         bf::rename(destination, target);
612                                 }
613                         }
614                 }
615         } catch (const bf::filesystem_error& error) {
616                 _ERR("Failed to copy directory: %s", error.what());
617                 return false;
618         }
619
620         return true;
621 }
622
623 bool copyFile(const bf::path& path1, const bf::path& path2)
624 {
625         bs::error_code error;
626         if (!exist(path1)) {
627                 return false;
628         }
629         bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error);
630         if (error) {
631                 _ERR("copy file %s due to error [%s]", path1.c_str(), error.message().c_str());
632                 return false;
633         }
634         return true;
635 }
636
637 bool moveFile(const bf::path& path1, const bf::path& path2)
638 {
639         if (!exist(path1) || exist(path2)) {
640                 return false;
641         }
642         bs::error_code error;
643         bf::rename(path1, path2, error);
644         if (error) {
645                 _ERR("Cannot move file: %s. Will copy/remove... with error [%s]", path1.c_str(), error.message().c_str());
646                 bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error);
647                 if (error) {
648                         _ERR("Cannot copy file %s due to error [%s]", path1.c_str(), error.message().c_str());
649                         return false;
650                 }
651                 bf::remove_all(path1, error);
652                 if (error) {
653                         _ERR("Cannot remove old file when coping: %s with error [%s]", path1.c_str(), error.message().c_str());
654                         return false;
655                 }
656         }
657         return true;
658 }
659
660 bool removeFile(const bf::path& path)
661 {
662         if (!exist(path)) {
663                 return true;
664         }
665         bs::error_code error;
666         bf::remove(path, error);
667         if (error) {
668                 _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str());
669                 return false;
670         }
671         return true;
672 }
673
674 bool removeAll(const bf::path& path)
675 {
676         if (!exist(path)) {
677                 return true;
678         }
679         bs::error_code error;
680         bf::remove_all(path, error);
681         if (error) {
682                 _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str());
683                 return false;
684         }
685         return true;
686 }
687
688 void setCmdName(const std::string& name)
689 {
690         #define PRC_NAME_LENGTH         16
691
692         char processName[PRC_NAME_LENGTH] = {0, };
693
694         if (name.empty())
695                 return;
696
697         memset(processName, '\0', PRC_NAME_LENGTH);
698         snprintf(processName, PRC_NAME_LENGTH, "%s", name.c_str());
699         prctl(PR_SET_NAME, processName);
700 }
701
702 std::string getFileName(const std::string& path)
703 {
704         std::string ret(path);
705         size_t index = ret.find_last_of(PATH_SEPARATOR);
706         return index == std::string::npos ? ret : ret.substr(index + 1);
707 }
708
709 std::string SHA256(const std::string& path)
710 {
711         int bytesRead = 0;
712         const int bufSize = 32768;
713
714         unsigned int digest_len = 0;
715         unsigned char* digest = NULL;
716
717         std::stringstream ss;
718         EVP_MD_CTX *mdctx = NULL;
719         std::string output = "";
720
721         FILE *file = fopen(path.c_str(), "rb");
722         if (!file) {
723                 return output;
724         }
725
726         char *buffer = (char*)malloc(bufSize);
727         if (!buffer) {
728                 goto cleanup4;
729         }
730
731         mdctx = EVP_MD_CTX_new();
732         if (mdctx == NULL) {
733                 _ERR("Message Digest Context creation NULL");
734                 goto cleanup3;
735         }
736
737         digest = (unsigned char*)OPENSSL_malloc(EVP_MD_size(EVP_sha256()));
738         if (!digest) {
739                 _ERR("Memory Allocation for SHA256 failed");
740                 goto cleanup2;
741         }
742
743         if (!EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL)) {
744                 _ERR("Message Digest init failed");
745                 goto cleanup1;
746         }
747
748         while ((bytesRead = fread(buffer, 1, bufSize, file))) {
749                 if (!EVP_DigestUpdate(mdctx, buffer, bytesRead)) {
750                         _ERR("Message Digest update failed");
751                         goto cleanup1;
752                 }
753         }
754
755         if (!EVP_DigestFinal_ex(mdctx, digest, &digest_len)) {
756                 _ERR("Message Digest Finalization falied");
757                 goto cleanup1;
758         }
759
760         for (unsigned int i = 0; i < digest_len; i++) {
761                 ss << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i];
762         }
763         output = ss.str();
764
765 cleanup1:
766         EVP_MD_CTX_free(mdctx);
767 cleanup2:
768         OPENSSL_free(digest);
769 cleanup3:
770         free(buffer);
771 cleanup4:
772         fclose(file);
773
774         return output;
775 }
776
777 int pkgmgrGetPkgInfo(const std::string& pkgId, pkgmgrinfo_pkginfo_h* handle)
778 {
779         uid_t uid = 0;
780         int ret = 0;
781
782         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
783                 _ERR("Failed to get UID");
784                 return -1;
785         }
786
787         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, handle);
788         if (ret != PMINFO_R_OK) {
789                 _ERR("Failed to get pkginfo (%d)", ret);
790                 return -1;
791         }
792
793         return 0;
794 }
795
796 int pkgmgrGetAppInfo(const std::string& appId, pkgmgrinfo_appinfo_h* handle)
797 {
798         uid_t uid = 0;
799         int ret = 0;
800
801         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
802                 _ERR("Failed to get UID");
803                 return -1;
804         }
805
806         ret = pkgmgrinfo_appinfo_get_usr_appinfo(appId.c_str(), uid, handle);
807         if (ret != PMINFO_R_OK) {
808                 _ERR("Failed to get appinfo (%d)", ret);
809                 return -1;
810         }
811
812         return 0;
813 }
814
815 int pkgmgrMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle,
816                                                         pkgmgrinfo_app_list_cb app_cb,
817                                                         void *user_data)
818 {
819         uid_t uid = 0;
820         int ret = 0;
821
822         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
823                 _ERR("Failed to get UID");
824                 return -1;
825         }
826
827
828         ret = pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle, app_cb, user_data, uid);
829         if (ret != PMINFO_R_OK) {
830                 _ERR("Failed to execute the metadata filter query (%d)", ret);
831                 return -1;
832         }
833
834         return 0;
835 }
836
837 void printHWClockLog(const char* format, ...)
838 {
839         char buf[1024] = {0,};
840         va_list ap;
841
842         va_start(ap, format);
843         vsnprintf(buf, sizeof(buf), format, ap);
844         va_end(ap);
845
846         prctl(PR_TASK_PERF_USER_TRACE, buf, strlen(buf));
847 }
848
849 const char* getNCDBStartupHook()
850 {
851         return "/home/owner/share/tmp/sdk_tools/netcoredbg/ncdbhook.dll";
852 }
853
854 bool isNCDBStartupHookProvided()
855 {
856         char *env = nullptr;
857         env = getenv("DOTNET_STARTUP_HOOKS");
858         if (env == nullptr)
859                 return false;
860
861         // Note, `DOTNET_STARTUP_HOOKS` env could provide list of dlls with ':' delimiter,
862         // for example: "/path1/name1.dll:/path2/name2.dll"
863         while (*env != '\0')
864         {
865                 const char *ncdbCur = getNCDBStartupHook();
866                 while (*ncdbCur != '\0' && *env != '\0' && *env != ':')
867                 {
868                         if (*ncdbCur != *env)
869                                 break;
870
871                         ncdbCur++;
872                         env++;
873
874                         if (*ncdbCur == '\0' && (*env == '\0' || *env == ':'))
875                                 return true;
876                 }
877                 while (*env != '\0' && *env != ':')
878                 {
879                         env++;
880                 }
881                 if (*env == ':')
882                         env++;
883         }
884
885         return false;
886 }