#include <algorithm>
#include <string>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
#include "common.h"
#ifdef LOG_TAG
#define __XSTR(x) #x
#define __STR(x) __XSTR(x)
-static const char* DeviceAPIDir = __STR(DEVICE_API_DIR);
-static const char* RuntimeDir = __STR(RUNTIME_DIR);
-static const char* CrossgenPath = __STR(CROSSGEN_PATH);
-static const char* JITPath = __STR(RUNTIME_DIR)"/libclrjit.so";
+static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR);
+static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR);
+static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH);
+static const char* __JIT_PATH = __STR(RUNTIME_DIR)"/libclrjit.so";
#undef __STR
#undef __XSTR
-static void crossgen(const char* dll_path, const char* app_path);
-static void smack_(const char* dll_path);
-void create_ni_platform()
+#if 0
+static std::string replace(std::string &str, const std::string& from, const std::string& to)
{
- std::string corlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.dll");
- std::string nicorlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.ni.dll");
+ size_t startPos = 0;
+ while ((startPos = str.find(from, startPos)) != std::string::npos) {
+ str.replace(startPos, from.length(), to);
+ startPos += to.length();
+ }
+ return str;
+}
+#endif
- if (FileNotExist(nicorlib))
- {
- crossgen(corlib.c_str(), nullptr);
- smack_(nicorlib.c_str());
- }
+static void smack_(const char* dllPath, const char* label)
+{
+ static const char* chsmack = "/usr/bin/chsmack";
+ pid_t pid = fork();
+ if (pid == -1)
+ return;
+
+ if (pid > 0) {
+ int status;
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status))
+ return;
+ } else {
+ const char* args[] = {
+ chsmack,
+ "-a", label,
+ dllPath,
+ nullptr
+ };
+ execv(chsmack, const_cast<char*const*>(args));
+
+ exit(0);
+ }
+}
- const char* platform_dirs[] = {RuntimeDir, DeviceAPIDir, "/usr/bin"};
- const char* ignores[] = {corlib.c_str()};
+static void crossgen(const char* dllPath, const char* appPath)
+{
+ //pid_t parent = getpid();
+ pid_t pid = fork();
+ if (pid == -1)
+ return;
+
+ if (pid > 0) {
+ int status;
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status))
+ return;
+ } else {
+ // search dlls in the application directory first, to use application dlls
+ // instead of system dlls when proceeding NI
+ std::vector<std::string> tpaDir;
+ if (appPath != NULL) {
+ std::string path(appPath);
+ std::string::size_type prevPos = 0, pos = 0;
+ while ((pos = path.find(':', pos)) != std::string::npos) {
+ std::string substring(path.substr(prevPos, pos - prevPos));
+ tpaDir.push_back(substring);
+ prevPos = ++pos;
+ }
+ std::string substring(path.substr(prevPos, pos - prevPos));
+ tpaDir.push_back(substring);
+ }
+ tpaDir.push_back(__RUNTIME_DIR);
+ tpaDir.push_back(__DEVICE_API_DIR);
+
+ // get reference API directory ([DEVICE_API_DIR]/ref)
+ int len = strlen(__DEVICE_API_DIR);
+ char* refAPIDir = (char*)calloc(len + 4, 1);
+ if (!refAPIDir) {
+ printf("fail to allocate memory for reference API directory\n");
+ return;
+ }
+ snprintf(refAPIDir, len + 4, "%s%s", __DEVICE_API_DIR, "/ref");
+ tpaDir.push_back(refAPIDir);
+
+ std::string tpa;
+ assembliesInDirectory(tpaDir, tpa);
+
+ std::vector<const char*> argv = {
+ __CROSSGEN_PATH,
+ "/Trusted_Platform_Assemblies", tpa.c_str(),
+ "/JITPath", __JIT_PATH,
+ "/FragileNonVersionable"
+ };
+ if (appPath != nullptr) {
+ argv.push_back("/App_Paths");
+ argv.push_back(appPath);
+ }
+ argv.push_back(dllPath);
+ argv.push_back(nullptr);
+
+ printf("+ %s\n", dllPath);
+
+ execv(__CROSSGEN_PATH, const_cast<char* const*>(argv.data()));
+ exit(0);
+ }
+}
- create_ni_under_dirs(platform_dirs, 3, ignores, 1, [](const char* ni){
- smack_(ni);
- });
+static int getRootPath(const char *pkgId, std::string& rootPath)
+{
+ int ret = 0;
+ char *path = 0;
+
+ uid_t uid = 0;
+
+ if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
+ _ERR("Failed to get UID");
+ return -1;
+ }
+
+ _INFO("user id is %d", uid);
+
+ pkgmgrinfo_pkginfo_h handle;
+ if (uid == 0) {
+ ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId, &handle);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ } else {
+ ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId, uid, &handle);
+ if (ret != PMINFO_R_OK)
+ return -1;
+ }
+
+ ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return -1;
+ }
+ rootPath = path;
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+
+ return 0;
}
-static void smack_(const char* dll_path)
+static bool niExist(const std::string& path, std::string& ni)
{
- static const char* CHKSMACK = "/usr/bin/chsmack";
- pid_t pid = fork();
- if (pid == -1)
- {
- return;
- }
-
- if (pid > 0)
- {
- int status;
- waitpid(pid, &status, 0);
- if (WIFEXITED(status))
- {
- return;
- }
- }
- else
- {
- const char* args[] = {
- CHKSMACK,
- "-a", "_",
- dll_path,
- nullptr
- };
- execv(CHKSMACK, const_cast<char*const*>(args));
-
- exit(0);
- }
+ // native image of System.Private.CoreLib.dll should have to overwrite
+ // original file to support new coreclr
+ if (path.find("System.Private.CoreLib.dll") != std::string::npos) {
+ std::string coreLibBackup = path + ".Backup";
+ if (!fileNotExist(coreLibBackup)) {
+ ni = path;
+ return true;
+ }
+ return false;
+ }
+
+ static const char* possibleExts[] = {
+ ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL",
+ ".ni.exe", ".NI.exe", ".NI.EXE", ".ni.EXE"
+ };
+ std::string fName = path.substr(0, path.size() - 4);
+
+ struct stat sb;
+
+ for (const char* ext : possibleExts) {
+ std::string f = fName + ext;
+ if (stat(f.c_str(), &sb) == 0) {
+ ni = f;
+ return true;
+ }
+ }
+
+ return false;
}
-static void crossgen(const char* dll_path, const char* app_path)
+static void createCoreLibNI()
{
- //pid_t parent = getpid();
- pid_t pid = fork();
- if (pid == -1)
- {
- return;
- }
-
- if (pid > 0)
- {
- int status;
- waitpid(pid, &status, 0);
- if (WIFEXITED(status))
- {
- return;
- }
- }
- else
- {
- std::vector<std::string> tpaDir = {
- RuntimeDir, DeviceAPIDir
- };
- std::string tpa;
- AssembliesInDirectory(tpaDir, tpa);
-
- std::vector<const char*> argv =
- {
- CrossgenPath,
- "/Trusted_Platform_Assemblies", tpa.c_str(),
- "/JITPath", JITPath,
- "/FragileNonVersionable"
- };
- if (app_path != nullptr)
- {
- argv.push_back("/App_Paths");
- argv.push_back(app_path);
- }
- argv.push_back(dll_path);
- argv.push_back(nullptr);
-
- /*
- for (const char* arg : argv)
- {
- printf("%s ", arg);
- }
- printf("\n");
- */
- printf("+ %s\n", dll_path);
-
- execv(CrossgenPath, const_cast<char* const*>(argv.data()));
- exit(0);
- }
+ std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll");
+ std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll");
+ std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup");
+
+ if (!niExist(coreLib, niCoreLib)) {
+ crossgen(coreLib.c_str(), nullptr);
+ if (!fileNotExist(niCoreLib)) {
+ // change owner and groups for generated ni file.
+ struct stat info;
+ if (!stat(coreLib.c_str(), &info)) {
+ if (chown(niCoreLib.c_str(), info.st_uid, info.st_gid) == -1)
+ _ERR("Failed to change owner and group name");
+ }
+ smack_(niCoreLib.c_str(), "_");
+ rename(coreLib.c_str(), coreLibBackup.c_str());
+ rename(niCoreLib.c_str(), coreLib.c_str());
+ }
+ }
}
-static int get_root_path(const char *pkgid, std::string& root_path)
+void createNiPlatform()
{
- int ret = 0;
- char *path = 0;
-
- uid_t uid = 0;
-
- if (pkgmgr_installer_info_get_target_uid(&uid) < 0)
- {
- _ERR("Failed to get UID");
- return -1;
- }
-
- _INFO("user id is %d", uid);
-
- pkgmgrinfo_pkginfo_h handle;
- if (uid == 0)
- {
- ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
- if (ret != PMINFO_R_OK)
- return -1;
- }
- else
- {
- ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
- if (ret != PMINFO_R_OK)
- return -1;
- }
-
- ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
- if (ret != PMINFO_R_OK) {
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return -1;
- }
- root_path = path;
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
-
- return 0;
+ createCoreLibNI();
+
+ const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"};
+
+ createNiUnderDirs(platformDirs, 3, [](const char* ni) {
+ smack_(ni, "_");
+ });
}
-static bool NIExist(const std::string& path, std::string& ni)
+void createNiSelect(const char* dllPath)
{
- static const char* possible_exts[] = {
- ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL"
- };
- std::string fname = path.substr(0, path.size() - 4);
-
- struct stat sb;
-
- for (const char* ext : possible_exts)
- {
- std::string f = fname + ext;
- if (stat(f.c_str(), &sb) == 0)
- {
- ni = f;
- return true;
- }
- }
-
- return false;
+ createCoreLibNI();
+
+ std::string niPath;
+ if (!fileNotExist(dllPath)) {
+ if (!niExist(dllPath, niPath)) {
+ crossgen(dllPath, nullptr);
+ if (niExist(dllPath, niPath)) {
+ // change owner and groups for generated ni file.
+ struct stat info;
+ if (!stat(dllPath, &info)) {
+ if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1)
+ _ERR("Failed to change owner and group name");
+ }
+ smack_(niPath.c_str(), "_");
+ }
+ }
+ else
+ printf("Already [%s] file is exist\n", niPath.c_str());
+ }
}
-void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb)
+void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb)
{
- std::string app_paths;
- for (int i=0; i<count; i++)
- {
- app_paths += root_paths[i];
- app_paths += ':';
- }
- if (app_paths.back() == ':')
- app_paths.pop_back();
-
- auto convert = [&app_paths, ignores, igcount, &cb](const char* path)
- {
- for (int i=0; i<igcount; i++)
- {
- if (strcmp(path, ignores[i]) == 0)
- return;
- }
- std::string ni;
- if (IsManagedAssembly(path) && !IsNativeImage(path) && !NIExist(path, ni))
- {
- crossgen(path, app_paths.c_str());
- if (NIExist(path, ni))
- {
- if (cb != nullptr)
- {
- cb(ni.c_str());
- }
- }
- }
- };
-
- for (int i=0; i<count; i++)
- {
- ScanFilesInDir(root_paths[i], convert, -1);
- }
+ std::string appPaths;
+ for (int i = 0; i < count; i++) {
+ appPaths += rootPaths[i];
+ appPaths += ':';
+ }
+
+ if (appPaths.back() == ':')
+ appPaths.pop_back();
+
+ auto convert = [&appPaths, ignores, igcount, &cb](const char* path, const char* name) {
+ for (int i = 0; i < igcount; i++) {
+ if (strcmp(path, ignores[i]) == 0)
+ return;
+ }
+ std::string ni;
+ if (isManagedAssembly(path) && !isNativeImage(path) && !niExist(path, ni)) {
+ crossgen(path, appPaths.c_str());
+ if (niExist(path, ni)) {
+ // change owner and groups for generated ni file.
+ struct stat info;
+ if (!stat(path, &info)) {
+ if (chown(ni.c_str(), info.st_uid, info.st_gid) == -1)
+ _ERR("Failed to change owner and group name");
+ }
+
+ if (cb != nullptr)
+ cb(ni.c_str());
+ }
+ }
+ };
+
+ for (int i = 0; i < count; i++)
+ scanFilesInDir(rootPaths[i], convert, -1);
}
-void create_ni_under_dirs(const char* root_paths[], int count, after_create cb)
+void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb)
{
- create_ni_under_dirs(root_paths, count, nullptr, 0, cb);
+ createNiUnderDirs(rootPaths, count, nullptr, 0, cb);
}
-void create_ni_under_dirs(const char* root_paths[], int count)
+void createNiUnderDirs(const char* rootPaths[], int count)
{
- create_ni_under_dirs(root_paths, count, nullptr);
+ createNiUnderDirs(rootPaths, count, nullptr);
}
-int create_ni_under_pkg_root(const char* pkg_name)
+int createNiUnderPkgRoot(const char* pkgName)
{
- std::string pkgroot;
- if (get_root_path(pkg_name, pkgroot) < 0)
- {
- return 1;
- }
-
- //printf("pkgroot : %s\n", pkgroot.c_str());
-
- std::string bindir = ConcatPath(pkgroot, "bin");
- std::string libdir = ConcatPath(pkgroot, "lib");
-
- //printf("bindir : %s\n", bindir.c_str());
- //printf("libdir : %s\n", libdir.c_str());
- _INFO("bindir : %s", bindir.c_str());
- _INFO("libdir : %s", libdir.c_str());
-
- const char* paths[] = {
- bindir.c_str(),
- libdir.c_str()
- };
- create_ni_under_dirs(paths, 2);
-
- return 0;
+ std::string pkgRoot;
+ if (getRootPath(pkgName, pkgRoot) < 0)
+ return 1;
+
+ std::string binDir = concatPath(pkgRoot, "bin");
+ std::string libDir = concatPath(pkgRoot, "lib");
+ _INFO("bindir : %s", binDir.c_str());
+ _INFO("libdir : %s", libDir.c_str());
+
+ const char* paths[] = {
+ binDir.c_str(),
+ libDir.c_str()
+ };
+
+ // change smack label for generated ni file.
+ std::string label = "User::Pkg::" + std::string(pkgName) + "::RO";
+ createNiUnderDirs(paths, 2, [label](const char* ni) {
+ smack_(ni, label.c_str());
+ });
+
+ return 0;
}