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 void createCoreLibNI()
238 std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll");
239 std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll");
240 std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup");
242 if (!niExist(coreLib, niCoreLib)) {
243 crossgen(coreLib.c_str(), nullptr);
244 if (!fileNotExist(niCoreLib)) {
245 // change owner and groups for generated ni file.
247 if (!stat(coreLib.c_str(), &info)) {
248 if (chown(niCoreLib.c_str(), info.st_uid, info.st_gid) == -1)
249 _ERR("Failed to change owner and group name");
251 smack_(niCoreLib.c_str(), "_");
252 rename(coreLib.c_str(), coreLibBackup.c_str());
253 rename(niCoreLib.c_str(), coreLib.c_str());
258 void removeNiUnderDirs(const char* rootPaths[], int count)
260 auto convert = [](const char* path, const char* name) {
262 if (isNativeImage(path)) {
267 for (int i = 0; i < count; i++)
268 scanFilesInDir(rootPaths[i], convert, -1);
271 void removeNiPlatform()
273 std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll");
274 std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll");
275 std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup");
277 if (fileNotExist(coreLibBackup)) {
281 if (remove(coreLib.c_str())) {
282 _ERR("Failed to remove System.Private.CoreLib native image file");
285 rename(coreLibBackup.c_str(), coreLib.c_str());
287 const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"};
289 removeNiUnderDirs(platformDirs, 3);
292 void createNiPlatform()
296 const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"};
298 createNiUnderDirs(platformDirs, 3, [](const char* ni) {
303 void createNiSelect(const char* dllPath)
308 if (!fileNotExist(dllPath)) {
309 if (!niExist(dllPath, niPath)) {
310 crossgen(dllPath, nullptr);
311 if (niExist(dllPath, niPath)) {
312 // change owner and groups for generated ni file.
314 if (!stat(dllPath, &info)) {
315 if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1)
316 _ERR("Failed to change owner and group name");
318 smack_(niPath.c_str(), "_");
322 printf("Already [%s] file is exist\n", niPath.c_str());
326 void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb)
328 std::string appPaths;
329 for (int i = 0; i < count; i++) {
330 appPaths += rootPaths[i];
334 if (appPaths.back() == ':')
337 auto convert = [&appPaths, ignores, igcount, &cb](const char* path, const char* name) {
338 for (int i = 0; i < igcount; i++) {
339 if (strcmp(path, ignores[i]) == 0)
343 if (isManagedAssembly(path) && !isNativeImage(path) && !niExist(path, ni)) {
344 crossgen(path, appPaths.c_str());
345 if (niExist(path, ni)) {
346 // change owner and groups for generated ni file.
348 if (!stat(path, &info)) {
349 if (chown(ni.c_str(), info.st_uid, info.st_gid) == -1)
350 _ERR("Failed to change owner and group name");
359 for (int i = 0; i < count; i++)
360 scanFilesInDir(rootPaths[i], convert, -1);
362 void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb)
364 createNiUnderDirs(rootPaths, count, nullptr, 0, cb);
366 void createNiUnderDirs(const char* rootPaths[], int count)
368 createNiUnderDirs(rootPaths, count, nullptr);
371 int removeNiUnderPkgRoot(const char* pkgName)
374 if (getRootPath(pkgName, pkgRoot) < 0)
377 std::string binDir = concatPath(pkgRoot, "bin");
378 std::string libDir = concatPath(pkgRoot, "lib");
379 _INFO("bindir : %s", binDir.c_str());
380 _INFO("libdir : %s", libDir.c_str());
382 const char* paths[] = {
387 removeNiUnderDirs(paths, 2);
393 int createNiUnderPkgRoot(const char* pkgName)
396 if (getRootPath(pkgName, pkgRoot) < 0)
399 // get interval value
400 const char* intervalFile = "/usr/share/dotnet.tizen/lib/crossgen_interval.txt";
402 std::ifstream inFile(intervalFile);
404 _INFO("crossgen_interval.txt is found");
407 _INFO("fail to read crossgen_interval.txt file");
410 std::string binDir = concatPath(pkgRoot, "bin");
411 std::string libDir = concatPath(pkgRoot, "lib");
412 _INFO("bindir : %s", binDir.c_str());
413 _INFO("libdir : %s", libDir.c_str());
415 const char* paths[] = {
420 // change smack label for generated ni file.
421 std::string label = "User::Pkg::" + std::string(pkgName) + "::RO";
422 createNiUnderDirs(paths, 2, [label, interval](const char* ni) {
423 smack_(ni, label.c_str());
425 _INFO("sleep %d usec", interval);