Add "--resolve-all-app" option to dotnettool
[platform/core/dotnet/launcher.git] / NativeLauncher / tool / multi_target_resolver.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <string>
18
19 #include <pkgmgr-info.h>
20 #include <vconf.h>
21
22 #include "log.h"
23 #include "utils.h"
24 #include "multi_target_resolver.h"
25
26 static const char* __TIZEN_RID_VERSION_KEY = "db/dotnet/tizen_rid_version";
27 static const char* __TIZEN_TFM_SUPPORT_KEY = "db/dotnet/tizen_tfm_support";
28
29 static std::vector<std::string> getRidFallbackGraph()
30 {
31         std::vector<std::string> RID_FALLBACK_GRAPH;
32         char* tizen_rid = vconf_get_str(__TIZEN_RID_VERSION_KEY);
33         if (tizen_rid) {
34                 std::vector<std::string> version;
35                 splitPath(tizen_rid, version);
36                 std::reverse(std::begin(version), std::end(version));
37                 for (unsigned int i = 0; i < version.size(); i++) {
38                         RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i] + "-" + ARCHITECTURE_IDENTIFIER));
39                         RID_FALLBACK_GRAPH.push_back(std::string("tizen." + version[i]));
40                 }
41                 free(tizen_rid);
42         }
43
44         std::vector<std::string> RID_FALLBACK_OS = {"tizen", "linux", "unix"};
45         for (unsigned int i = 0; i < RID_FALLBACK_OS.size(); i++) {
46                 RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i] + "-" + ARCHITECTURE_IDENTIFIER));
47                 RID_FALLBACK_GRAPH.push_back(std::string(RID_FALLBACK_OS[i]));
48         }
49         RID_FALLBACK_GRAPH.push_back("any");
50         RID_FALLBACK_GRAPH.push_back("base");
51
52         return RID_FALLBACK_GRAPH;
53 }
54
55 static std::vector<std::string> getTfmFallbackGraph()
56 {
57         std::vector<std::string> tfmList;
58         char* tizen_tfm = vconf_get_str(__TIZEN_TFM_SUPPORT_KEY);
59         if (tizen_tfm) {
60                 splitPath(tizen_tfm, tfmList);
61                 free(tizen_tfm);
62         }
63
64         return tfmList;
65 }
66
67 // move all files under a certain directory to another directory
68 // ownership / permission / smack label are not changed
69 static bool moveAllFilesTo(const std::string& from, const std::string& to)
70 {
71         std::vector<std::string> files;
72         try {
73                 // make file list to move
74                 for (auto& path : bf::recursive_directory_iterator(from)) {
75                         std::string filePath = path.path().string();
76                         if (isFile(filePath)) {
77                                 files.push_back(filePath);
78                         }
79                 }
80
81                 // move files to target directory
82                 for (auto& f : files) {
83                         bf::rename(f, concatPath(to, getFileName(f)));
84                 }
85         }  catch (const bf::filesystem_error& error) {
86                 _ERR("Failed to iterate directory: %s", error.what());
87                 return false;
88         }
89
90         return true;
91 }
92
93 int resolvePlatformSpecificFiles(const std::string& rootPath)
94 {
95         std::string appBinPath = concatPath(rootPath, "bin");
96         std::string runtimesPath = concatPath(appBinPath, "runtimes");
97
98         // if runtimes directory doesnot exist, return 0
99         if (!isDirectory(runtimesPath)) {
100                 return 0;
101         }
102
103         // found best matched rid and tfm directory and copy all files to bin directory
104         std::vector<std::string> ridFallbackGraph = getRidFallbackGraph();
105         for (auto& rid : ridFallbackGraph) {
106                 std::string ridPath = concatPath(runtimesPath, rid);
107                 if (isDirectory(ridPath)) {
108                         _INFO("Found best matched rid (%s)", rid.c_str());
109                         // copy all files from /runtimes/${rid}/native to appBintPath if exist
110                         std::string nativePath = concatPath(ridPath, "native");
111                         if (isDirectory(nativePath)) {
112                                 _INFO("Found best matched native path");
113                                 if (!moveAllFilesTo(nativePath, appBinPath)) {
114                                         _ERR("Failed to copy files from native path");
115                                         return -1;
116                                 }
117                         }
118
119                         // found best matched tfm folder in the found rid folder
120                         std::string libPath = concatPath(ridPath, "lib");
121                         std::vector<std::string> tfmFallbackGraph = getTfmFallbackGraph();
122                         for (auto& tfm : tfmFallbackGraph) {
123                                 std::string tfmPath = concatPath(libPath, tfm);
124                                 if (isDirectory(tfmPath)) {
125                                         _INFO("Found best matched tfm (%s)", tfm .c_str());
126                                         // copy all files from tfmPath to appBintPath
127                                         if (!moveAllFilesTo(tfmPath, appBinPath)) {
128                                                 _ERR("Failed to copy files from tfm path");
129                                                 return -1;
130                                         }
131                                 }
132                         }
133
134                         break;
135                 }
136         }
137
138         // remove runtimes directory
139         if (!removeAll(runtimesPath)) {
140                 _ERR("Failed to remove bin/runtimes directory");
141                 return -1;
142         }
143
144         return 0;
145 }
146
147 // callback function of "pkgmgrinfo_appinfo_filter_foreach_appinfo"
148 static int appResolveCb(pkgmgrinfo_appinfo_h handle, void *user_data)
149 {
150         int ret = 0;
151         char* rootPath;
152
153         ret = pkgmgrinfo_appinfo_get_root_path(handle, &rootPath);
154         if (ret != PMINFO_R_OK) {
155                 fprintf(stderr, "Failed to get root path");
156                 return -1;
157         }
158
159         if (resolvePlatformSpecificFiles(rootPath) != 0) {
160                 fprintf(stderr, "Failed to resolve platform specific resources (%s)\n", rootPath);
161                 return -1;
162         }
163
164         return 0;
165 }
166
167 int resolveAllApps()
168 {
169         int ret = 0;
170
171         pkgmgrinfo_appinfo_filter_h handle;
172         ret = pkgmgrinfo_appinfo_filter_create(&handle);
173         if (ret != PMINFO_R_OK) {
174                 return -1;
175         }
176
177         ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_TYPE, "dotnet");
178         if (ret != PMINFO_R_OK) {
179                 pkgmgrinfo_appinfo_filter_destroy(handle);
180                 return -1;
181         }
182
183         ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, appResolveCb, NULL);
184         if (ret != PMINFO_R_OK) {
185                 pkgmgrinfo_appinfo_filter_destroy(handle);
186                 return -1;
187         }
188         pkgmgrinfo_appinfo_filter_destroy(handle);
189
190         return 0;
191 }
192