2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <pkgmgr-info.h>
18 #include <pkgmgr_installer_info.h>
23 #include "pkgmgr_parser_plugin_interface.h"
45 #define LOG_TAG "NETCORE_INSTALLER_PLUGIN"
47 #ifndef DEVICE_API_DIR
48 #error "DEVICE_API_DIR is missed"
52 #error "RUNTIME_DIR is missed"
56 #error "CROSSGEN_PATH is missed"
60 #define __STR(x) __XSTR(x)
61 static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR);
62 static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR);
63 static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH);
64 static const char* __JIT_PATH = __STR(RUNTIME_DIR)"/libclrjit.so";
69 static std::string replace(std::string &str, const std::string& from, const std::string& to)
72 while ((startPos = str.find(from, startPos)) != std::string::npos) {
73 str.replace(startPos, from.length(), to);
74 startPos += to.length();
80 static void smack_(const char* dllPath, const char* label)
82 static const char* chsmack = "/usr/bin/chsmack";
89 waitpid(pid, &status, 0);
90 if (WIFEXITED(status))
93 const char* args[] = {
99 execv(chsmack, const_cast<char*const*>(args));
105 static void crossgen(const char* dllPath, const char* appPath)
107 //pid_t parent = getpid();
114 waitpid(pid, &status, 0);
115 if (WIFEXITED(status))
118 // search dlls in the application directory first, to use application dlls
119 // instead of system dlls when proceeding NI
120 std::vector<std::string> tpaDir;
121 if (appPath != NULL) {
122 std::string path(appPath);
123 std::string::size_type prevPos = 0, pos = 0;
124 while ((pos = path.find(':', pos)) != std::string::npos) {
125 std::string substring(path.substr(prevPos, pos - prevPos));
126 tpaDir.push_back(substring);
129 std::string substring(path.substr(prevPos, pos - prevPos));
130 tpaDir.push_back(substring);
132 tpaDir.push_back(__RUNTIME_DIR);
133 tpaDir.push_back(__DEVICE_API_DIR);
135 // get reference API directory ([DEVICE_API_DIR]/ref)
136 int len = strlen(__DEVICE_API_DIR);
137 char* refAPIDir = (char*)calloc(len + 5, 1);
139 printf("fail to allocate memory for reference API directory\n");
142 snprintf(refAPIDir, len + 5, "%s%s", __DEVICE_API_DIR, "/ref");
143 tpaDir.push_back(refAPIDir);
146 assembliesInDirectory(tpaDir, tpa);
148 std::vector<const char*> argv = {
150 "/Trusted_Platform_Assemblies", tpa.c_str(),
151 "/JITPath", __JIT_PATH,
152 "/FragileNonVersionable"
154 if (appPath != nullptr) {
155 argv.push_back("/App_Paths");
156 argv.push_back(appPath);
158 argv.push_back(dllPath);
159 argv.push_back(nullptr);
161 printf("+ %s\n", dllPath);
163 execv(__CROSSGEN_PATH, const_cast<char* const*>(argv.data()));
168 static int getRootPath(const char *pkgId, std::string& rootPath)
175 if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
176 _ERR("Failed to get UID");
180 _INFO("user id is %d", uid);
182 pkgmgrinfo_pkginfo_h handle;
184 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId, &handle);
185 if (ret != PMINFO_R_OK)
188 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId, uid, &handle);
189 if (ret != PMINFO_R_OK)
193 ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
194 if (ret != PMINFO_R_OK) {
195 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
199 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
204 static bool niExist(const std::string& path, std::string& ni)
206 // native image of System.Private.CoreLib.dll should have to overwrite
207 // original file to support new coreclr
208 if (path.find("System.Private.CoreLib.dll") != std::string::npos) {
209 std::string coreLibBackup = path + ".Backup";
210 if (!fileNotExist(coreLibBackup)) {
217 static const char* possibleExts[] = {
218 ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL",
219 ".ni.exe", ".NI.exe", ".NI.EXE", ".ni.EXE"
221 std::string fName = path.substr(0, path.size() - 4);
225 for (const char* ext : possibleExts) {
226 std::string f = fName + ext;
227 if (stat(f.c_str(), &sb) == 0) {
236 static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData)
241 ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
242 if (ret != PMINFO_R_OK) {
243 _DBG("Failed to get pkgid");
247 // When you create native image with pkgid, ni file is generated even though already ni file exist.
248 if (createNiUnderPkgRoot(pkgId) != 0) {
249 _ERR("Failed to get root path from [%s]", pkgId);
252 _DBG("Complete make application to native image");
258 int regenerateAppNI()
261 pkgmgrinfo_appinfo_metadata_filter_h handle;
263 ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
264 if (ret != PMINFO_R_OK)
267 ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, "http://tizen.org/metadata/prefer_dotnet_aot", "true");
268 if (ret != PMINFO_R_OK) {
269 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
273 ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, appAotCb, NULL);
274 if (ret != PMINFO_R_OK) {
275 _DBG("Failed pkgmgrinfo_appinfo_metadata_filter_foreach");
276 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
280 _DBG("Success pkgmgrinfo_appinfo_metadata_filter_foreach");
282 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
286 static void createCoreLibNI()
288 std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll");
289 std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll");
290 std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup");
292 if (!niExist(coreLib, niCoreLib)) {
293 crossgen(coreLib.c_str(), nullptr);
294 if (!fileNotExist(niCoreLib)) {
295 // change owner and groups for generated ni file.
297 if (!stat(coreLib.c_str(), &info)) {
298 if (chown(niCoreLib.c_str(), info.st_uid, info.st_gid) == -1)
299 _ERR("Failed to change owner and group name");
301 smack_(niCoreLib.c_str(), "_");
302 rename(coreLib.c_str(), coreLibBackup.c_str());
303 rename(niCoreLib.c_str(), coreLib.c_str());
308 void removeNiUnderDirs(const char* rootPaths[], int count)
310 auto convert = [](const char* path, const char* name) {
312 if (isNativeImage(path)) {
317 for (int i = 0; i < count; i++)
318 scanFilesInDir(rootPaths[i], convert, -1);
321 void removeNiPlatform()
323 std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll");
324 std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll");
325 std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup");
327 if (fileNotExist(coreLibBackup)) {
331 if (remove(coreLib.c_str())) {
332 _ERR("Failed to remove System.Private.CoreLib native image file");
335 rename(coreLibBackup.c_str(), coreLib.c_str());
337 const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"};
339 removeNiUnderDirs(platformDirs, 3);
342 void createNiPlatform()
346 const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"};
348 createNiUnderDirs(platformDirs, 3, [](const char* ni) {
353 void createNiSelect(const char* dllPath)
358 if (!fileNotExist(dllPath)) {
359 if (!niExist(dllPath, niPath)) {
360 crossgen(dllPath, nullptr);
361 if (niExist(dllPath, niPath)) {
362 // change owner and groups for generated ni file.
364 if (!stat(dllPath, &info)) {
365 if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1)
366 _ERR("Failed to change owner and group name");
368 smack_(niPath.c_str(), "_");
371 printf("Already [%s] file is exist\n", niPath.c_str());
374 printf("Failed to find dll : %s", dllPath);
378 void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb, bool update)
380 std::string appPaths;
381 for (int i = 0; i < count; i++) {
382 appPaths += rootPaths[i];
386 if (appPaths.back() == ':')
389 auto convert = [&appPaths, ignores, igcount, &cb, update](const char* path, const char* name) {
390 for (int i = 0; i < igcount; i++) {
391 if (strcmp(path, ignores[i]) == 0)
395 if (isManagedAssembly(path) && !isNativeImage(path)) {
396 if (niExist(path, niPath)) {
397 if (update && !niPath.empty()) {
398 _INFO("override [%s] file", niPath.c_str());
400 _INFO("Already [%s] file is exist", niPath.c_str());
404 crossgen(path, appPaths.c_str());
405 if (niExist(path, niPath)) {
406 // change owner and groups for generated ni file.
408 if (!stat(path, &info)) {
409 if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1)
410 _ERR("Failed to change owner and group name");
416 _INFO("Failed to create native image for %s", path);
421 for (int i = 0; i < count; i++)
422 scanFilesInDir(rootPaths[i], convert, 1);
424 void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb, bool update)
426 createNiUnderDirs(rootPaths, count, nullptr, 0, cb, update);
428 void createNiUnderDirs(const char* rootPaths[], int count, bool update)
430 createNiUnderDirs(rootPaths, count, nullptr, update);
433 int removeNiUnderPkgRoot(const char* pkgName)
436 if (getRootPath(pkgName, pkgRoot) < 0)
439 std::string binDir = concatPath(pkgRoot, "bin");
440 std::string libDir = concatPath(pkgRoot, "lib");
441 _INFO("bindir : %s", binDir.c_str());
442 _INFO("libdir : %s", libDir.c_str());
444 const char* paths[] = {
449 removeNiUnderDirs(paths, 2);
455 int createNiUnderPkgRoot(const char* pkgName)
458 if (getRootPath(pkgName, pkgRoot) < 0)
461 // get interval value
462 const char* intervalFile = "/usr/share/dotnet.tizen/lib/crossgen_interval.txt";
464 std::ifstream inFile(intervalFile);
466 _INFO("crossgen_interval.txt is found");
469 _INFO("fail to read crossgen_interval.txt file");
472 std::string binDir = concatPath(pkgRoot, "bin");
473 std::string libDir = concatPath(pkgRoot, "lib");
474 _INFO("bindir : %s", binDir.c_str());
475 _INFO("libdir : %s", libDir.c_str());
477 const char* paths[] = {
482 // change smack label for generated ni file.
483 std::string label = "User::Pkg::" + std::string(pkgName) + "::RO";
484 createNiUnderDirs(paths, 2, [label, interval](const char* ni) {
485 smack_(ni, label.c_str());
487 _INFO("sleep %d usec", interval);