[Refactoring] Code cleanup and remove duplicate methods
[platform/core/dotnet/launcher.git] / NativeLauncher / util / utils.cc
index 64f4428..37ba52e 100644 (file)
 #include <pkgmgr_installer_info.h>
 #include <sys/smack.h>
 #include <sys/prctl.h>
-#include <openssl/sha.h>
+
+#include <openssl/evp.h>
+#include <openssl/crypto.h>
+
 #include <mntent.h>
 
 #include <cstdlib>
@@ -40,6 +43,7 @@
 #include "log.h"
 #include "utils.h"
 #include "path_manager.h"
+#include "r2r_checker.h"
 
 static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length)
 {
@@ -52,14 +56,7 @@ static bool iCompare(const std::string& a, int aOffset, const std::string& b, in
 
 bool isManagedAssembly(const std::string& fileName)
 {
-       return (iCompare(fileName, fileName.size()-4, ".dll", 0, 4) ||
-                       iCompare(fileName, fileName.size()-4, ".exe", 0, 4)) &&
-                       !isNativeImage(fileName);
-}
-
-bool isNativeImage(const std::string& fileName)
-{
-       return iCompare(fileName, fileName.size()-7, ".ni", 0, 3);
+       return iCompare(fileName, fileName.size()-4, ".dll", 0, 4) && !isR2RImage(fileName);
 }
 
 std::string concatPath(const std::string& path1, const std::string& path2)
@@ -81,7 +78,9 @@ void splitPath(const std::string& path, std::vector<std::string>& out)
        std::string token;
 
        while (std::getline(ss, token, ':')) {
-               out.push_back(token);
+               if (token != "") {
+                       out.push_back(token);
+               }
        }
 }
 
@@ -339,13 +338,13 @@ void addAssembliesFromDirectories(const std::vector<std::string>& directories, s
        std::unordered_map<std::string, std::string> assemPaths;
 
        auto reader = [&assems, &assemPaths](const std::string& path, const std::string& filename) {
-               if (isManagedAssembly(filename) || isNativeImage(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]) && isNativeImage(filename)) {
+                       } 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.
@@ -709,36 +708,68 @@ std::string getFileName(const std::string& path)
 
 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;
        }
 
-       unsigned char hash[SHA256_DIGEST_LENGTH];
-       SHA256_CTX sha256;
-       SHA256_Init(&sha256);
-       int bytesRead = 0;
-       const int bufSize = 32768;
        char *buffer = (char*)malloc(bufSize);
        if (!buffer) {
-               fclose(file);
-               return output;
+               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))) {
-               SHA256_Update(&sha256, buffer, bytesRead);
+               if (!EVP_DigestUpdate(mdctx, buffer, bytesRead)) {
+                       _ERR("Message Digest update failed");
+                       goto cleanup1;
+               }
        }
-       SHA256_Final(hash, &sha256);
 
-       std::stringstream ss;
-       for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
-               ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
+       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();
 
-       fclose(file);
+cleanup1:
+       EVP_MD_CTX_free(mdctx);
+cleanup2:
+       OPENSSL_free(digest);
+cleanup3:
        free(buffer);
+cleanup4:
+       fclose(file);
 
        return output;
 }
@@ -815,3 +846,41 @@ void printHWClockLog(const char* format, ...)
        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;
+}