X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=NativeLauncher%2Futil%2Futils.cc;h=37ba52e1d0d428398b58a180574db90925529992;hb=33b4aa2fcbb716d081fc13ac6855fc53bd343532;hp=92440f111ccf0fd5c486873659bf54a4df9b858c;hpb=6d179f13ad595875a0843741036930b1bf683760;p=platform%2Fcore%2Fdotnet%2Flauncher.git diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index 92440f1..37ba52e 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -14,12 +14,20 @@ * limitations under the License. */ - #include +#include #include #include #include #include +#include +#include +#include + +#include +#include + +#include #include #include @@ -27,19 +35,17 @@ #include #include #include +#include #include +#include +#include +#include "log.h" #include "utils.h" +#include "path_manager.h" +#include "r2r_checker.h" -bool iCompare(const std::string& a, const std::string& b) -{ - return a.length() == b.length() && - std::equal(b.begin(), b.end(), a.begin(), - [](unsigned char a, unsigned char b) - { return std::tolower(a) == std::tolower(b); }); -} - -bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length) +static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length) { return static_cast(a.length()) - length >= aOffset && static_cast(b.length()) - length >= bOffset && @@ -50,25 +56,7 @@ bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffs bool isManagedAssembly(const std::string& fileName) { - return iCompare(fileName, fileName.size()-4, ".dll", 0, 4) || - iCompare(fileName, fileName.size()-4, ".exe", 0, 4); -} - -bool isNativeImage(const std::string& fileName) -{ - return iCompare(fileName, fileName.size()-7, ".ni", 0, 3); -} - -std::string readSelfPath() -{ - char buff[PATH_MAX]; - ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1); - if (len != -1) { - buff[len] = '\0'; - return std::string(buff); - } - - return ""; + return iCompare(fileName, fileName.size()-4, ".dll", 0, 4) && !isR2RImage(fileName); } std::string concatPath(const std::string& path1, const std::string& path2) @@ -84,178 +72,307 @@ std::string concatPath(const std::string& path1, const std::string& path2) return path; } -void appendPath(std::string& path1, const std::string& path2) +void splitPath(const std::string& path, std::vector& out) { - if (path1.back() == PATH_SEPARATOR) { - path1.append(path2); - } else { - path1 += PATH_SEPARATOR; - path1.append(path2); + std::istringstream ss(path); + std::string token; + + while (std::getline(ss, token, ':')) { + if (token != "") { + out.push_back(token); + } } } -std::string absolutePath(const std::string& path) +std::string getAbsolutePath(const std::string& path) { std::string absPath; - char realPath[PATH_MAX]; - if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0') + char *realPath = realpath(path.c_str(), NULL); + if (realPath) { absPath.assign(realPath); + free(realPath); + } return absPath; } -std::string baseName(const std::string& path) +std::string getRootPath(const std::string& pkgId) { - auto pos = path.find_last_of(PATH_SEPARATOR); - if (pos != std::string::npos) - return path.substr(0, pos); - else - return std::string("."); - return path; + int ret = 0; + char *path = 0; + std::string rootPath; + + pkgmgrinfo_pkginfo_h pkg_handle; + ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle); + if (ret != 0) { + return rootPath; + } + + ret = pkgmgrinfo_pkginfo_get_root_path(pkg_handle, &path); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return rootPath; + } + rootPath = path; + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + + return rootPath; } -bool endWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& fileName) +std::string getExecName(const std::string& pkgId) { - std::string::size_type len1 = str1.length(); - std::string::size_type len2 = str2.length(); - if (len2 > len1) - return false; + char *exec = NULL; + char *appId = 0; + std::string execName; + + pkgmgrinfo_pkginfo_h pkg_handle; + int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle); + if (ret != 0) { + return execName; + } - int i = 0; - bool result = std::all_of(str1.cend() - len2, str1.end(), - [&i, &str2] (char x) { - return std::tolower(x) == std::tolower(str2[i++]); - }); - if (result) - fileName = str1.substr(0, len1 - len2); + ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return execName; + } - return result; + pkgmgrinfo_appinfo_h app_handle; + ret = pkgmgrGetAppInfo(appId, &app_handle); + if (ret != 0) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return execName; + } + + ret = pkgmgrinfo_appinfo_get_exec(app_handle, &exec); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return execName; + } + execName = std::string(exec).substr(std::string(exec).rfind('/') + 1); + + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + + return execName; } -bool fileNotExist(const std::string& path) +std::string getAppType(const std::string& pkgId) { - struct stat sb; - return stat(path.c_str(), &sb) != 0; + char *appId = 0; + char *type = 0; + std::string appType; + + pkgmgrinfo_pkginfo_h pkg_handle; + int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle); + if (ret != 0) { + return appType; + } + + ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return appType; + } + + pkgmgrinfo_appinfo_h app_handle; + ret = pkgmgrGetAppInfo(appId, &app_handle); + if (ret != 0) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return appType; + } + + ret = pkgmgrinfo_appinfo_get_apptype(app_handle, &type); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return appType; + } + appType = type; + + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + + return appType; } -#ifdef NOT_USE_FUNCTION -static bool extCheckAndGetFileNameIfExist(const std::string& dir, const std::string& ext, struct dirent* entry, std::string& fileName) +std::string getMetadataValue(const std::string& pkgId, const std::string& key) { - std::string fName(entry->d_name); - if (fName.length() < ext.length() || - fHame.compare(fName.length() - ext.length(), ext.length(), ext) != 0) { - return false; + char *value = NULL; + char *appId = 0; + std::string metadataValue; + + pkgmgrinfo_pkginfo_h pkg_handle; + int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle); + if (ret != 0) { + return metadataValue; } - std::string fullName = concatPath(dir, entry->d_name); - switch (entry->d_type) { - case DT_REG: break; - case DT_LNK: - case DT_UNKNOWN: - if (fileNotExist(fullName)) - return false; - default: - return false; + ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return metadataValue; } - fileName = fullName; + pkgmgrinfo_appinfo_h app_handle; + ret = pkgmgrGetAppInfo(appId, &app_handle); + if (ret != 0) { + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return metadataValue; + } - return true; + ret = pkgmgrinfo_appinfo_get_metadata_value(app_handle, key.c_str(), &value); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + return metadataValue; + } + metadataValue = std::string(value); + + pkgmgrinfo_appinfo_destroy_appinfo(app_handle); + pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle); + + return metadataValue; } -#endif -std::string stripNiDLL(const std::string& path) +bool isReadOnlyArea(const std::string& path) { - std::string niPath(path); - if (path.size() < 5) return niPath; - if (!strncasecmp(path.c_str() + path.size() - 4, ".dll", 4)) - niPath = path.substr(0, path.size()-4); - else if (!strncasecmp(path.c_str() + path.size() - 4, ".exe", 4)) - niPath = path.substr(0, path.size()-4); + FILE *f = NULL; + struct mntent *m = NULL; + + // "/opt/usr" is mounted to "RW" only + if (path.find("/opt/usr") != std::string::npos) { + return false; + } + + // check whether "/" is mounted to RO or not + f = setmntent("/proc/mounts", "r"); + if (!f) { + // return true for fail case to generate NI files under RW area. + return true; + } + + while((m = getmntent(f))) { + if (m->mnt_dir != NULL && strcmp(m->mnt_dir, "/") == 0 && + m->mnt_opts != NULL && strstr(m->mnt_opts, "ro,") != NULL) { + endmntent(f); + return true; + } + } + endmntent(f); + return false; - if (!strncasecmp(niPath.c_str() + niPath.size() - 3, ".ni", 3)) - return niPath.substr(0, niPath.size()-3); +} - return niPath; +std::string getBaseName(const std::string& path) +{ + auto pos = path.find_last_of(PATH_SEPARATOR); + if (pos != std::string::npos) + return path.substr(0, pos); + else + return std::string("."); + return path; } -std::string joinStrings(const std::vector& strings, const char* const delimeter) +std::string replaceAll(const std::string& str, const std::string& pattern, const std::string& replace) { - switch (strings.size()) { - case 0: - return ""; - case 1: - return strings[0]; - default: - std::ostringstream os; - std::copy(strings.begin(), strings.end()-1, std::ostream_iterator(os, delimeter)); - os << *strings.rbegin(); - return os.str(); + std::string result = str; + std::string::size_type pos = 0; + std::string::size_type offset = 0; + + while ((pos = result.find(pattern, offset)) != std::string::npos) { + result.replace(result.begin() + pos, result.begin() + pos + pattern.size(), replace); + offset = pos + replace.size(); } + + return result; } -struct AssemblyFile { - std::string noExt; - std::string ext; -}; +std::string changeExtension(const std::string& path, const std::string& from, const std::string& to) +{ + return path.substr(0, path.rfind(from)) + to; +} -bool operator == (const AssemblyFile& lhs, const AssemblyFile& rhs) +bool isFile(const std::string& path) { - return lhs.noExt == rhs.noExt && lhs.ext == rhs.ext; + struct stat sb; + return lstat(path.c_str(), &sb) == 0; } -namespace std { - template<> - struct hash { - std::size_t operator () (const AssemblyFile& f) const { - const std::size_t h1 = std::hash{}(f.noExt); - const std::size_t h2 = std::hash{}(f.ext); +bool isSymlinkFile(const std::string& path) +{ + struct stat sb; + if (lstat(path.c_str(), &sb) != 0) { + return false; + } + return (sb.st_mode & S_IFMT) == S_IFLNK; +} - return h1 ^ (h2 << 1); - } - }; +bool isDirectory(const std::string& path) +{ + struct stat sb; + if (stat(path.c_str(), &sb) != 0) { + return false; + } + return (sb.st_mode & S_IFMT) == S_IFDIR; } -void assembliesInDirectory(const std::vector& directories, std::string& tpaList) +std::string getAssemblyNameFromPath(const std::string& path) { - std::map assemblyList; - std::map tmpList; + std::string ret(getFileName(path)); + + if (ret.find_last_of(".") == std::string::npos) + return ret; + ret.erase(ret.find_last_of(".")); - auto reader = [&assemblyList, &tmpList] (const char* path, const char* name) { - std::string pathStr(path); - if (isManagedAssembly(pathStr)) { - std::string dllName = stripNiDLL(name); - std::pair::iterator, bool> ret; - ret = tmpList.insert(std::pair(dllName, pathStr)); - if (ret.second == false) { - if (isNativeImage(pathStr)) - tmpList[dllName] = pathStr; + if (ret.size() > 3 && std::equal(ret.begin() + ret.size() - 3, ret.end(), ".ni")) + ret.erase(ret.size() - 3); + + return ret; +} + +void addAssembliesFromDirectories(const std::vector& directories, std::string& list) +{ + std::vector assems; + std::unordered_map assemPaths; + + auto reader = [&assems, &assemPaths](const std::string& path, const std::string& filename) { + if (isManagedAssembly(filename) || isR2RImage(filename)) { + std::string assem = getAssemblyNameFromPath(filename); + + if (assemPaths.count(assem) == 0) { + assems.push_back(assem); + assemPaths[assem] = path; + } else if (isManagedAssembly(assemPaths[assem]) && isR2RImage(filename)) { + // Update only if a native image is found in the same directory. + // For example, if we have two directories = { X, Y } where X contains A.dll and + // Y contains both A.dll and A.ni.dll, always A.dll in X will be used. + if (getBaseName(assemPaths[assem]).compare(getBaseName(path)) == 0) + assemPaths[assem] = path; } } }; + for (auto& directory : directories) + scanFilesInDirectory(directory, reader, 0); - for (auto directory : directories) { - scanFilesInDir(directory.c_str(), reader, 1); - // merge scaned dll list to tpa list. - // if the dll is already exist in the list, that is skipped. - assemblyList.insert(tmpList.begin(), tmpList.end()); - } + if (!list.empty() && list.back() != ':') + list.push_back(':'); - std::map::iterator it; - for (it = assemblyList.begin(); it != assemblyList.end(); it++) - tpaList += it->second + ':'; + for (auto& assem : assems) + list += assemPaths[assem] + ":"; - if (tpaList.back() == ':') - tpaList.pop_back(); + if (list.back() == ':') + list.pop_back(); } -void scanFilesInDir(const char* directory, FileReader reader, unsigned int depth) +void scanFilesInDirectory(const std::string& directory, FileReader reader, unsigned int depth) { DIR *dir; struct dirent* entry; bool isDir; - dir = opendir(directory); + dir = opendir(directory.c_str()); if (dir == nullptr) return; @@ -270,26 +387,500 @@ void scanFilesInDir(const char* directory, FileReader reader, unsigned int depth case DT_DIR: isDir = true; break; + // symlink is added to the list even if there is no original file. + // It used to remove broken symlinks related to TAC case DT_LNK: + break; case DT_UNKNOWN: - struct stat sb; - if (stat(path.c_str(), &sb) == -1) - continue; - - if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode)) - break; + continue; default: continue; } if (!isDir) - reader(path.c_str(), entry->d_name); - else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) + reader(path, entry->d_name); + else if (depth > 0 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) innerDirectories.push_back(path); } - if (depth != 0) + if (depth > 0) for (auto& d : innerDirectories) - scanFilesInDir(d.c_str(), reader, depth-1); + scanFilesInDirectory(d, reader, depth - 1); closedir(dir); -} \ No newline at end of file +} + +void copySmackAndOwnership(const std::string& fromPath, const std::string& toPath, bool isSymlink) +{ + char* label = NULL; + struct stat info; + + if (isSymlink) { + // change smack label for symbolic link. + if (smack_lgetlabel(fromPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) { + if (smack_lsetlabel(toPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) { + _SERR("Fail to set smack label"); + } + free(label); + } + + // change owner and groupsfor symbolic link. + // change mode is skipped for symlink because permission of symlink file is meaningless. + if (!lstat(fromPath.c_str(), &info)) { + if (lchown(toPath.c_str(), info.st_uid, info.st_gid) == -1) + _SERR("Failed to change owner and group name"); + } + } else { + // change smack label + if (smack_getlabel(fromPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) { + if (smack_setlabel(toPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) { + _SERR("Fail to set smack label"); + } + free(label); + } + + // change owner, groups and mode for generated ni file. + if (!stat(fromPath.c_str(), &info)) { + if (chown(toPath.c_str(), info.st_uid, info.st_gid) == -1) + _SERR("Failed to change owner and group name"); + if (chmod(toPath.c_str(), info.st_mode) == -1) + _SERR("Failed to change mode"); + } + } +} + +static bool setOwnership(const bf::path& path, uid_t uid, gid_t gid) +{ + int fd = open(path.c_str(), O_RDONLY); + if (fd < 0) { + _ERR("Can't open directory: %s", path.c_str()); + return false; + } + int ret = fchown(fd, uid, gid); + close(fd); + if (ret != 0) { + _ERR("Failed to change owner of: %s", path.c_str()); + return false; + } + return true; +} + +static bool setDirPermissions(const bf::path& path, bf::perms permissions) +{ + bs::error_code error; + bf::permissions(path, permissions, error); + if (error) { + _ERR("Failed to set permissions for directory: %s, %s", path.c_str(), error.message().c_str()); + return false; + } + return true; +} + +static bool setDirOwnershipAndPermissions(const bf::path& path, bf::perms permissions, uid_t uid, gid_t gid) +{ + if (!setOwnership(path, uid, gid)) { + _ERR("Failed to change owner: %s, (uid: %d, gid: %d)", path.c_str(), uid, gid); + return false; + } + if (!setDirPermissions(path, permissions)) { + _ERR("Failed to change permission: %s, (%d)", path.c_str(), permissions); + return false; + } + return true; +} + +static bool copyOwnershipAndPermissions(const bf::path& path, const bf::path& path2) +{ + if (!exist(path)) { + _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str()); + return false; + } + bs::error_code error; + bf::perms permissions = bf::status(path, error).permissions(); + if (error) { + _ERR("Failed to copy ownership and permissions : %s", error.message().c_str()); + return false; + } + struct stat stats; + if (stat(path.c_str(), &stats) != 0) { + return false; + } + if (!setDirOwnershipAndPermissions(path2, permissions, stats.st_uid, stats.st_gid)) { + _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str()); + return false; + } + return true; +} + +bool exist(const bf::path& path) +{ + bs::error_code error; + int ret = bf::exists(path, error); + if (error) { + if ((error.value() != bs::errc::success) && (error.value() != bs::errc::no_such_file_or_directory)) { + _ERR("Failed to check %s exists : %s", path.c_str(), error.message().c_str()); + } + } + return ret; +} + +bool createDir(const bf::path& path) +{ + if (exist(path)) { + return true; + } + bs::error_code error; + bf::create_directories(path, error); + if (error) { + _ERR("Failed to create directory: %s", error.message().c_str()); + return false; + } + return true; +} + +bool copyDir(const bf::path& path1, const bf::path& path2, FSFlag flags) +{ + try { + // Check whether the function call is valid + if (!exist(path1) || !bf::is_directory(path1)) { + _ERR("Source directory %s does not exist or is not a directory", path1.c_str()); + return false; + } + if (!exist(path2)) { + // Create the destination directory + if (!createDir(path2)) { + _ERR("Unable to create destination directory %s", path2.c_str()); + return false; + } + if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) { + copyOwnershipAndPermissions(path1, path2); + } + } else { + if (!(flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE))) { + _ERR("Destination directory %s already exists", path2.c_str()); + return false; + } + if (flags & (FS_MERGE_OVERWRITE | FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS)) { + copyOwnershipAndPermissions(path1, path2); + } + } + } catch (const bf::filesystem_error& error) { + _ERR("Failed to copy directory: %s", error.what()); + return false; + } + + // Iterate through the source directory + try { + for (bf::directory_iterator file(path1); file != bf::directory_iterator(); ++file) { + bf::path current(file->path()); + bf::path target = path2 / current.filename(); + if (bf::is_symlink(bf::symlink_status(current))) { + if ((flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE)) && exist(target)) { + continue; + } + bs::error_code error; + bf::copy_symlink(current, target, error); + if (error) { + _ERR("Failed to copy symlink: %s, %s", current.c_str(), error.message().c_str()); + return false; + } + } else if (bf::is_directory(current)) { + // Found directory: Recursion + if (!copyDir(current, target, flags)) { + return false; + } + } else { + if ((flags & FS_MERGE_SKIP) && exist(target)) { + continue; + } + bf::path destination = target; + if (flags & FS_COMMIT_COPY_FILE) { + destination = bf::unique_path(target.parent_path() / "%%%%-%%%%-%%%%-%%%%"); + } + if (flags & FS_MERGE_OVERWRITE) { + bf::copy_file(current, destination, bf::copy_option::overwrite_if_exists); + } else { + bf::copy_file(current, destination); + } + if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) { + copyOwnershipAndPermissions(current, destination); + } + if (flags & FS_COMMIT_COPY_FILE) { + if (flags & FS_MERGE_OVERWRITE) { + bf::remove(target); + } + bf::rename(destination, target); + } + } + } + } catch (const bf::filesystem_error& error) { + _ERR("Failed to copy directory: %s", error.what()); + return false; + } + + return true; +} + +bool copyFile(const bf::path& path1, const bf::path& path2) +{ + bs::error_code error; + if (!exist(path1)) { + return false; + } + bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error); + if (error) { + _ERR("copy file %s due to error [%s]", path1.c_str(), error.message().c_str()); + return false; + } + return true; +} + +bool moveFile(const bf::path& path1, const bf::path& path2) +{ + if (!exist(path1) || exist(path2)) { + return false; + } + bs::error_code error; + bf::rename(path1, path2, error); + if (error) { + _ERR("Cannot move file: %s. Will copy/remove... with error [%s]", path1.c_str(), error.message().c_str()); + bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error); + if (error) { + _ERR("Cannot copy file %s due to error [%s]", path1.c_str(), error.message().c_str()); + return false; + } + bf::remove_all(path1, error); + if (error) { + _ERR("Cannot remove old file when coping: %s with error [%s]", path1.c_str(), error.message().c_str()); + return false; + } + } + return true; +} + +bool removeFile(const bf::path& path) +{ + if (!exist(path)) { + return true; + } + bs::error_code error; + bf::remove(path, error); + if (error) { + _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str()); + return false; + } + return true; +} + +bool removeAll(const bf::path& path) +{ + if (!exist(path)) { + return true; + } + bs::error_code error; + bf::remove_all(path, error); + if (error) { + _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str()); + return false; + } + return true; +} + +void setCmdName(const std::string& name) +{ + #define PRC_NAME_LENGTH 16 + + char processName[PRC_NAME_LENGTH] = {0, }; + + if (name.empty()) + return; + + memset(processName, '\0', PRC_NAME_LENGTH); + snprintf(processName, PRC_NAME_LENGTH, "%s", name.c_str()); + prctl(PR_SET_NAME, processName); +} + +std::string getFileName(const std::string& path) +{ + std::string ret(path); + size_t index = ret.find_last_of(PATH_SEPARATOR); + return index == std::string::npos ? ret : ret.substr(index + 1); +} + +std::string SHA256(const std::string& path) +{ + int bytesRead = 0; + const int bufSize = 32768; + + unsigned int digest_len = 0; + unsigned char* digest = NULL; + + std::stringstream ss; + EVP_MD_CTX *mdctx = NULL; + std::string output = ""; + + FILE *file = fopen(path.c_str(), "rb"); + if (!file) { + return output; + } + + char *buffer = (char*)malloc(bufSize); + if (!buffer) { + goto cleanup4; + } + + mdctx = EVP_MD_CTX_new(); + if (mdctx == NULL) { + _ERR("Message Digest Context creation NULL"); + goto cleanup3; + } + + digest = (unsigned char*)OPENSSL_malloc(EVP_MD_size(EVP_sha256())); + if (!digest) { + _ERR("Memory Allocation for SHA256 failed"); + goto cleanup2; + } + + if (!EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL)) { + _ERR("Message Digest init failed"); + goto cleanup1; + } + + while ((bytesRead = fread(buffer, 1, bufSize, file))) { + if (!EVP_DigestUpdate(mdctx, buffer, bytesRead)) { + _ERR("Message Digest update failed"); + goto cleanup1; + } + } + + if (!EVP_DigestFinal_ex(mdctx, digest, &digest_len)) { + _ERR("Message Digest Finalization falied"); + goto cleanup1; + } + + for (unsigned int i = 0; i < digest_len; i++) { + ss << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i]; + } + output = ss.str(); + +cleanup1: + EVP_MD_CTX_free(mdctx); +cleanup2: + OPENSSL_free(digest); +cleanup3: + free(buffer); +cleanup4: + fclose(file); + + return output; +} + +int pkgmgrGetPkgInfo(const std::string& pkgId, pkgmgrinfo_pkginfo_h* handle) +{ + uid_t uid = 0; + int ret = 0; + + if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { + _ERR("Failed to get UID"); + return -1; + } + + ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, handle); + if (ret != PMINFO_R_OK) { + _ERR("Failed to get pkginfo (%d)", ret); + return -1; + } + + return 0; +} + +int pkgmgrGetAppInfo(const std::string& appId, pkgmgrinfo_appinfo_h* handle) +{ + uid_t uid = 0; + int ret = 0; + + if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { + _ERR("Failed to get UID"); + return -1; + } + + ret = pkgmgrinfo_appinfo_get_usr_appinfo(appId.c_str(), uid, handle); + if (ret != PMINFO_R_OK) { + _ERR("Failed to get appinfo (%d)", ret); + return -1; + } + + return 0; +} + +int pkgmgrMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle, + pkgmgrinfo_app_list_cb app_cb, + void *user_data) +{ + uid_t uid = 0; + int ret = 0; + + if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { + _ERR("Failed to get UID"); + return -1; + } + + + ret = pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle, app_cb, user_data, uid); + if (ret != PMINFO_R_OK) { + _ERR("Failed to execute the metadata filter query (%d)", ret); + return -1; + } + + return 0; +} + +void printHWClockLog(const char* format, ...) +{ + char buf[1024] = {0,}; + va_list ap; + + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + prctl(PR_TASK_PERF_USER_TRACE, buf, strlen(buf)); +} + +const char* getNCDBStartupHook() +{ + return "/home/owner/share/tmp/sdk_tools/netcoredbg/ncdbhook.dll"; +} + +bool isNCDBStartupHookProvided() +{ + char *env = nullptr; + env = getenv("DOTNET_STARTUP_HOOKS"); + if (env == nullptr) + return false; + + // Note, `DOTNET_STARTUP_HOOKS` env could provide list of dlls with ':' delimiter, + // for example: "/path1/name1.dll:/path2/name2.dll" + while (*env != '\0') + { + const char *ncdbCur = getNCDBStartupHook(); + while (*ncdbCur != '\0' && *env != '\0' && *env != ':') + { + if (*ncdbCur != *env) + break; + + ncdbCur++; + env++; + + if (*ncdbCur == '\0' && (*env == '\0' || *env == ':')) + return true; + } + while (*env != '\0' && *env != ':') + { + env++; + } + if (*env == ':') + env++; + } + + return false; +}