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"
42 #define LOG_TAG "NETCORE_INSTALLER_PLUGIN"
44 #ifndef DEVICE_API_DIR
45 #error "DEVICE_API_DIR is missed"
49 #error "RUNTIME_DIR is missed"
53 #error "CROSSGEN_PATH is missed"
57 #define __STR(x) __XSTR(x)
58 static const char* DeviceAPIDir = __STR(DEVICE_API_DIR);
59 static const char* RuntimeDir = __STR(RUNTIME_DIR);
60 static const char* CrossgenPath = __STR(CROSSGEN_PATH);
61 static const char* JITPath = __STR(RUNTIME_DIR)"/libclrjit.so";
65 static void crossgen(const char* dll_path, const char* app_path);
66 static void smack_(const char* dll_path, const char* label);
68 std::string Replace(std::string &str, const std::string& from, const std::string& to)
71 while((start_pos = str.find(from, start_pos)) != std::string::npos)
73 str.replace(start_pos, from.length(), to);
74 start_pos += to.length();
79 void create_ni_platform()
81 std::string corlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.dll");
82 std::string nicorlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.ni.dll");
84 if (FileNotExist(nicorlib))
86 crossgen(corlib.c_str(), nullptr);
87 smack_(nicorlib.c_str(), "_");
90 const char* platform_dirs[] = {RuntimeDir, DeviceAPIDir, "/usr/bin"};
91 const char* ignores[] = {corlib.c_str()};
93 create_ni_under_dirs(platform_dirs, 3, ignores, 1, [](const char* ni){
98 void create_ni_select(const char* dll_path)
100 std::string corlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.dll");
101 std::string nicorlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.ni.dll");
103 if (FileNotExist(nicorlib))
105 crossgen(corlib.c_str(), nullptr);
106 smack_(nicorlib.c_str(), "_");
109 if (!FileNotExist(dll_path))
111 std::string str_path = dll_path;
112 std::string ni_path = Replace(str_path, std::string(".dll"), std::string(".ni.dll"));
113 if (FileNotExist(ni_path))
114 crossgen(dll_path, nullptr);
116 printf("Already [%s] file is exist\n", ni_path.c_str());
117 smack_(ni_path.c_str(), "_");
121 static void smack_(const char* dll_path, const char* label)
123 static const char* CHKSMACK = "/usr/bin/chsmack";
133 waitpid(pid, &status, 0);
134 if (WIFEXITED(status))
141 const char* args[] = {
147 execv(CHKSMACK, const_cast<char*const*>(args));
153 static void crossgen(const char* dll_path, const char* app_path)
155 //pid_t parent = getpid();
165 waitpid(pid, &status, 0);
166 if (WIFEXITED(status))
173 // search dlls in the application directory first, to use application dlls
174 // instead of system dlls when proceeding NI
175 std::vector<std::string> tpaDir;
176 if (app_path != NULL)
178 std::string path(app_path);
179 std::string::size_type prev_pos = 0, pos = 0;
180 while((pos = path.find(':', pos)) != std::string::npos)
182 std::string substring(path.substr(prev_pos, pos - prev_pos));
183 tpaDir.push_back(substring);
186 std::string substring(path.substr(prev_pos, pos - prev_pos));
187 tpaDir.push_back(substring);
189 tpaDir.push_back(RuntimeDir);
190 tpaDir.push_back(DeviceAPIDir);
193 AssembliesInDirectory(tpaDir, tpa);
195 std::vector<const char*> argv =
198 "/Trusted_Platform_Assemblies", tpa.c_str(),
200 "/FragileNonVersionable"
202 if (app_path != nullptr)
204 argv.push_back("/App_Paths");
205 argv.push_back(app_path);
207 argv.push_back(dll_path);
208 argv.push_back(nullptr);
211 for (const char* arg : argv)
217 printf("+ %s\n", dll_path);
219 execv(CrossgenPath, const_cast<char* const*>(argv.data()));
224 static int get_root_path(const char *pkgid, std::string& root_path)
231 if (pkgmgr_installer_info_get_target_uid(&uid) < 0)
233 _ERR("Failed to get UID");
237 _INFO("user id is %d", uid);
239 pkgmgrinfo_pkginfo_h handle;
242 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
243 if (ret != PMINFO_R_OK)
248 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
249 if (ret != PMINFO_R_OK)
253 ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
254 if (ret != PMINFO_R_OK) {
255 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
259 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
264 static bool NIExist(const std::string& path, std::string& ni)
266 static const char* possible_exts[] = {
267 ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL",
268 ".ni.exe", ".NI.exe", ".NI.EXE", ".ni.EXE"
270 std::string fname = path.substr(0, path.size() - 4);
274 for (const char* ext : possible_exts)
276 std::string f = fname + ext;
277 if (stat(f.c_str(), &sb) == 0)
287 void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb)
289 std::string app_paths;
290 for (int i=0; i<count; i++)
292 app_paths += root_paths[i];
295 if (app_paths.back() == ':')
296 app_paths.pop_back();
298 auto convert = [&app_paths, ignores, igcount, &cb](const char* path, const char* name)
300 for (int i=0; i<igcount; i++)
302 if (strcmp(path, ignores[i]) == 0)
306 if (IsManagedAssembly(path) && !IsNativeImage(path) && !NIExist(path, ni))
308 crossgen(path, app_paths.c_str());
309 if (NIExist(path, ni))
311 // change owner and groups for generated ni file.
313 if (!stat(path, &info))
315 if (chown(ni.c_str(), info.st_uid, info.st_gid) == -1)
317 _ERR("Failed to change owner and group name");
329 for (int i=0; i<count; i++)
331 ScanFilesInDir(root_paths[i], convert, -1);
334 void create_ni_under_dirs(const char* root_paths[], int count, after_create cb)
336 create_ni_under_dirs(root_paths, count, nullptr, 0, cb);
338 void create_ni_under_dirs(const char* root_paths[], int count)
340 create_ni_under_dirs(root_paths, count, nullptr);
343 int create_ni_under_pkg_root(const char* pkg_name)
346 if (get_root_path(pkg_name, pkgroot) < 0)
351 //printf("pkgroot : %s\n", pkgroot.c_str());
353 std::string bindir = ConcatPath(pkgroot, "bin");
354 std::string libdir = ConcatPath(pkgroot, "lib");
356 //printf("bindir : %s\n", bindir.c_str());
357 //printf("libdir : %s\n", libdir.c_str());
358 _INFO("bindir : %s", bindir.c_str());
359 _INFO("libdir : %s", libdir.c_str());
361 const char* paths[] = {
366 // change smack label for generated ni file.
367 std::string label = "User::Pkg::" + std::string(pkg_name) + "::RO";
368 create_ni_under_dirs(paths, 2, [label](const char* ni){
369 smack_(ni, label.c_str());