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"
43 #define LOG_TAG "NETCORE_INSTALLER_PLUGIN"
45 #ifndef DEVICE_API_DIR
46 #error "DEVICE_API_DIR is missed"
50 #error "RUNTIME_DIR is missed"
54 #error "CROSSGEN_PATH is missed"
58 #define __STR(x) __XSTR(x)
59 static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR);
60 static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR);
61 static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH);
62 static const char* __JIT_PATH = __STR(RUNTIME_DIR)"/libclrjit.so";
68 static std::string replace(std::string &str, const std::string& from, const std::string& to)
71 while ((startPos = str.find(from, startPos)) != std::string::npos) {
72 str.replace(startPos, from.length(), to);
73 startPos += to.length();
79 static void smack_(const char* dllPath, const char* label)
81 static const char* chsmack = "/usr/bin/chsmack";
88 waitpid(pid, &status, 0);
89 if (WIFEXITED(status))
92 const char* args[] = {
98 execv(chsmack, const_cast<char*const*>(args));
104 static void crossgen(const char* dllPath, const char* appPath)
106 //pid_t parent = getpid();
113 waitpid(pid, &status, 0);
114 if (WIFEXITED(status))
117 // search dlls in the application directory first, to use application dlls
118 // instead of system dlls when proceeding NI
119 std::vector<std::string> tpaDir;
120 if (appPath != NULL) {
121 std::string path(appPath);
122 std::string::size_type prevPos = 0, pos = 0;
123 while ((pos = path.find(':', pos)) != std::string::npos) {
124 std::string substring(path.substr(prevPos, pos - prevPos));
125 tpaDir.push_back(substring);
128 std::string substring(path.substr(prevPos, pos - prevPos));
129 tpaDir.push_back(substring);
131 tpaDir.push_back(__RUNTIME_DIR);
132 tpaDir.push_back(__DEVICE_API_DIR);
134 // get reference API directory ([DEVICE_API_DIR]/ref)
135 int len = strlen(__DEVICE_API_DIR);
136 char* refAPIDir = (char*)calloc(len + 4, 1);
138 printf("fail to allocate memory for reference API directory\n");
141 snprintf(refAPIDir, len + 4, "%s%s", __DEVICE_API_DIR, "/ref");
142 tpaDir.push_back(refAPIDir);
145 assembliesInDirectory(tpaDir, tpa);
147 std::vector<const char*> argv = {
149 "/Trusted_Platform_Assemblies", tpa.c_str(),
150 "/JITPath", __JIT_PATH,
151 "/FragileNonVersionable"
153 if (appPath != nullptr) {
154 argv.push_back("/App_Paths");
155 argv.push_back(appPath);
157 argv.push_back(dllPath);
158 argv.push_back(nullptr);
160 printf("+ %s\n", dllPath);
162 execv(__CROSSGEN_PATH, const_cast<char* const*>(argv.data()));
167 static int getRootPath(const char *pkgId, std::string& rootPath)
174 if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
175 _ERR("Failed to get UID");
179 _INFO("user id is %d", uid);
181 pkgmgrinfo_pkginfo_h handle;
183 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId, &handle);
184 if (ret != PMINFO_R_OK)
187 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId, uid, &handle);
188 if (ret != PMINFO_R_OK)
192 ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
193 if (ret != PMINFO_R_OK) {
194 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
198 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
203 static bool niExist(const std::string& path, std::string& ni)
205 // native image of System.Private.CoreLib.dll should have to overwrite
206 // original file to support new coreclr
207 if (path.find("System.Private.CoreLib.dll") != std::string::npos) {
208 std::string coreLibBackup = path + ".Backup";
209 if (!fileNotExist(coreLibBackup)) {
216 static const char* possibleExts[] = {
217 ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL",
218 ".ni.exe", ".NI.exe", ".NI.EXE", ".ni.EXE"
220 std::string fName = path.substr(0, path.size() - 4);
224 for (const char* ext : possibleExts) {
225 std::string f = fName + ext;
226 if (stat(f.c_str(), &sb) == 0) {
235 static void createCoreLibNI()
237 std::string coreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll");
238 std::string niCoreLib = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.ni.dll");
239 std::string coreLibBackup = concatPath(__RUNTIME_DIR, "System.Private.CoreLib.dll.Backup");
241 if (!niExist(coreLib, niCoreLib)) {
242 crossgen(coreLib.c_str(), nullptr);
243 if (!fileNotExist(niCoreLib)) {
244 // change owner and groups for generated ni file.
246 if (!stat(coreLib.c_str(), &info)) {
247 if (chown(niCoreLib.c_str(), info.st_uid, info.st_gid) == -1)
248 _ERR("Failed to change owner and group name");
250 smack_(niCoreLib.c_str(), "_");
251 rename(coreLib.c_str(), coreLibBackup.c_str());
252 rename(niCoreLib.c_str(), coreLib.c_str());
257 void createNiPlatform()
261 const char* platformDirs[] = {__RUNTIME_DIR, __DEVICE_API_DIR, "/usr/bin"};
263 createNiUnderDirs(platformDirs, 3, [](const char* ni) {
268 void createNiSelect(const char* dllPath)
273 if (!fileNotExist(dllPath)) {
274 if (!niExist(dllPath, niPath)) {
275 crossgen(dllPath, nullptr);
276 if (niExist(dllPath, niPath)) {
277 // change owner and groups for generated ni file.
279 if (!stat(dllPath, &info)) {
280 if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1)
281 _ERR("Failed to change owner and group name");
283 smack_(niPath.c_str(), "_");
287 printf("Already [%s] file is exist\n", niPath.c_str());
291 void createNiUnderDirs(const char* rootPaths[], int count, const char* ignores[], int igcount, afterCreate cb)
293 std::string appPaths;
294 for (int i = 0; i < count; i++) {
295 appPaths += rootPaths[i];
299 if (appPaths.back() == ':')
302 auto convert = [&appPaths, ignores, igcount, &cb](const char* path, const char* name) {
303 for (int i = 0; i < igcount; i++) {
304 if (strcmp(path, ignores[i]) == 0)
308 if (isManagedAssembly(path) && !isNativeImage(path) && !niExist(path, ni)) {
309 crossgen(path, appPaths.c_str());
310 if (niExist(path, ni)) {
311 // change owner and groups for generated ni file.
313 if (!stat(path, &info)) {
314 if (chown(ni.c_str(), info.st_uid, info.st_gid) == -1)
315 _ERR("Failed to change owner and group name");
324 for (int i = 0; i < count; i++)
325 scanFilesInDir(rootPaths[i], convert, -1);
327 void createNiUnderDirs(const char* rootPaths[], int count, afterCreate cb)
329 createNiUnderDirs(rootPaths, count, nullptr, 0, cb);
331 void createNiUnderDirs(const char* rootPaths[], int count)
333 createNiUnderDirs(rootPaths, count, nullptr);
336 int createNiUnderPkgRoot(const char* pkgName)
339 if (getRootPath(pkgName, pkgRoot) < 0)
342 std::string binDir = concatPath(pkgRoot, "bin");
343 std::string libDir = concatPath(pkgRoot, "lib");
344 _INFO("bindir : %s", binDir.c_str());
345 _INFO("libdir : %s", libDir.c_str());
347 const char* paths[] = {
352 // change smack label for generated ni file.
353 std::string label = "User::Pkg::" + std::string(pkgName) + "::RO";
354 createNiUnderDirs(paths, 2, [label](const char* ni) {
355 smack_(ni, label.c_str());