Code refactoring
[platform/core/dotnet/launcher.git] / NativeLauncher / tool / tac_common.cc
1 /*
2  * Copyright (c) 2019 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 <fstream>
18 #include <pkgmgr-info.h>
19 #include <pkgmgr_installer_info.h>
20 #include <json/json.h>
21
22 #include "log.h"
23 #include "utils.h"
24 #include "ni_common.h"
25 #include "tac_common.h"
26 #include "db_manager.h"
27 #include "path_manager.h"
28
29 #ifdef  LOG_TAG
30 #undef  LOG_TAG
31 #endif
32 #define LOG_TAG "DOTNET_INSTALLER_PLUGIN"
33
34 #define __XSTR(x) #x
35 #define __STR(x) __XSTR(x)
36 static const char* __TAC_DIR = __STR(TAC_DIR);
37 #undef __STR
38 #undef __XSTR
39
40 static sqlite3 *tac_db = NULL;
41 std::vector<std::string> restoreNuget;
42 std::vector<std::string> enableNuget;
43
44 void cleanupDirectory()
45 {
46         std::vector<std::string> removeNuget;
47         for (auto& nuget : bf::recursive_directory_iterator(__TAC_DIR)) {
48                 bool isExist = false;
49                 for (auto& restore : restoreNuget) {
50                         if (!bf::is_directory(nuget.path())) {
51                                 isExist = true;
52                         }
53                         if (strstr(nuget.path().c_str(), restore.c_str()) != NULL) {
54                                 isExist = true;
55                                 break;
56                         }
57                 }
58                 if (!isExist) {
59                         removeNuget.push_back(nuget.path().string());
60                 }
61         }
62
63         for (auto& rm : removeNuget) {
64                 if (!removeAll(rm)) {
65                         _ERR("Failed to remove of %s", rm.c_str());
66                 }
67         }
68         removeNuget.clear();
69 }
70
71 // callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach"
72 static int restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData)
73 {
74         char *pkgId = NULL;
75         char *root = NULL;
76         char *exec = NULL;
77         std::string rootPath;
78         std::string execName;
79
80         int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
81         if (ret != PMINFO_R_OK) {
82                 fprintf(stderr, "Failed to get pkgid\n");
83                 return -1;
84         }
85
86         ret = pkgmgrinfo_appinfo_get_root_path(handle, &root);
87         if (ret != PMINFO_R_OK) {
88                 fprintf(stderr, "Failed to get root path\n");
89                 return -1;
90         }
91         rootPath = root;
92
93         ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
94         if (ret != PMINFO_R_OK) {
95                 fprintf(stderr, "Failed to get exec name\n");
96                 return -1;
97         }
98         execName = std::string(exec).substr(std::string(exec).rfind('/') + 1);
99
100         restoreNuget = depsJsonParser(pkgId, rootPath, execName, getTPA(), true, tac_db);
101         return 0;
102 }
103
104 tac_error_e restoreTACDB()
105 {
106         if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
107                 fprintf(stderr, "Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
108                 return TAC_ERROR_UNKNOWN;
109         }
110
111         std::string dbRestoreJournal = TAC_APP_LIST_RESTORE_DB + std::string("-journal");
112         if (!removeFile(dbRestoreJournal)) {
113                 fprintf(stderr, "Failed to remove of %s", dbRestoreJournal.c_str());
114                 return TAC_ERROR_UNKNOWN;
115         }
116
117         if (initializePathManager(std::string(), std::string(), std::string())) {
118                 fprintf(stderr, "Fail to initialize PathManger");
119                 return TAC_ERROR_UNKNOWN;
120         }
121
122         tac_db = dbCreate(TAC_APP_LIST_RESTORE_DB);
123         if (tac_db) {
124                 if (!dbOpen(tac_db, TAC_APP_LIST_RESTORE_DB)) {
125                         return TAC_ERROR_UNKNOWN;
126                 }
127         } else {
128                 return TAC_ERROR_UNKNOWN;
129         }
130
131         pkgmgrinfo_appinfo_metadata_filter_h handle;
132         int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
133         if (ret != PMINFO_R_OK) {
134                 return TAC_ERROR_UNKNOWN;
135         }
136
137         ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE);
138         if (ret != PMINFO_R_OK) {
139                 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
140                 return TAC_ERROR_UNKNOWN;
141         }
142
143         ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, restoreDBCb, NULL);
144         if (ret != PMINFO_R_OK) {
145                 fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n");
146                 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
147                 return TAC_ERROR_UNKNOWN;
148         }
149         fprintf(stderr, "Success pkgmgrinfo_appinfo_metadata_filter_foreach\n");
150
151         pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
152
153         if (tac_db) {
154                 dbClose(tac_db);
155                 tac_db = NULL;
156         }
157
158         if (!copyFile(TAC_APP_LIST_RESTORE_DB, TAC_APP_LIST_DB)) {
159                 fprintf(stderr, "Failed to copy of %s", TAC_APP_LIST_DB);
160                 return TAC_ERROR_UNKNOWN;
161         }
162         if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
163                 fprintf(stderr, "Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
164                 return TAC_ERROR_UNKNOWN;
165         }
166
167         std::string dbJournal = TAC_APP_LIST_DB + std::string("-journal");
168         if (!copyFile(dbRestoreJournal, dbJournal)) {
169                 fprintf(stderr, "Failed to copy of %s", dbJournal.c_str());
170                 return TAC_ERROR_UNKNOWN;
171         }
172         if (!removeFile(dbRestoreJournal)) {
173                 fprintf(stderr, "Failed to remove of %s", dbRestoreJournal.c_str());
174                 return TAC_ERROR_UNKNOWN;
175         }
176
177         cleanupDirectory();
178         return TAC_ERROR_NONE;
179 }
180
181 tac_error_e resetTACPackage(const std::string& pkgId)
182 {
183         std::string pkgRoot;
184         if (getRootPath(pkgId, pkgRoot) < 0) {
185                 return TAC_ERROR_INVALID_PACKAGE;
186         }
187
188         std::vector<std::string> tacNativeImage;
189         std::string binDir = concatPath(pkgRoot, "bin");
190         std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
191         if (bf::exists(tacDir)) {
192                 for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
193                         std::string symPath = symlinkAssembly.path().string();
194                         if (bf::is_symlink(symPath)) {
195                                 if (isNativeImage(symPath)) {
196                                         tacNativeImage.push_back(symPath);
197                                 }
198                         }
199                 }
200                 for (auto& path : tacNativeImage) {
201                         if (!removeFile(path)) {
202                                 fprintf(stderr, "Failed to remove of %s", path.c_str());
203                                 return TAC_ERROR_UNKNOWN;
204                         }
205                 }
206         }
207         tacNativeImage.clear();
208         return TAC_ERROR_NONE;
209 }
210
211 tac_error_e createTACPackage(const std::string& pkgId)
212 {
213         std::string pkgRoot;
214         if (getRootPath(pkgId, pkgRoot) < 0) {
215                 return TAC_ERROR_INVALID_PACKAGE;
216         }
217
218         std::string binDir = concatPath(pkgRoot, "bin");
219         std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
220         std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
221         if (bf::exists(tacDir)) {
222                 for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
223                         std::string symPath = symlinkAssembly.path().string();
224                         if (bf::is_symlink(symPath)) {
225                                 if (!isNativeImage(symPath)) {
226                                         std::string originPath = bf::read_symlink(symPath).string();
227                                         std::string originNiPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
228                                         if (!bf::exists(originNiPath)) {
229                                                 if(createNiDll(originPath, false) != NI_ERROR_NONE) {
230                                                         fprintf(stderr, "Failed to create NI file [%s]\n", originPath.c_str());
231                                                         return TAC_ERROR_UNKNOWN;
232                                                 }
233                                         }
234                                         std::string symNIPath = symPath.substr(0, symPath.rfind(".dll")) + ".ni.dll";
235                                         if (!bf::exists(symNIPath)) {
236                                                 bf::create_symlink(originNiPath, symNIPath);
237                                                 fprintf(stderr, "%s symbolic link file generated successfully.\n", symNIPath.c_str());
238                                                 updateAssemblyInfo(tacDir.c_str(), symNIPath.c_str(), true);
239
240                                                 std::string NIFileName = symNIPath.substr(symNIPath.rfind('/') + 1);
241                                                 if (!removeFile(concatPath(binNIDir, NIFileName))) {
242                                                         fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, NIFileName).c_str());
243                                                         return TAC_ERROR_UNKNOWN;
244                                                 }
245                                         }
246                                 }
247                         }
248                 }
249         }
250         return TAC_ERROR_NONE;
251 }
252
253 tac_error_e regenerateTAC()
254 {
255         const std::string tacDir[] = {__TAC_DIR};
256         removeNiUnderDirs(tacDir, 1);
257
258         auto convert = [](const std::string& path, std::string name) {
259                 if (strstr(path.c_str(), TAC_APP_LIST_DB) != NULL ||
260                         strstr(path.c_str(), TAC_APP_LIST_RESTORE_DB) != NULL ||
261                         strstr(path.c_str(), TAC_SHA_256_INFO) != NULL)
262                         return;
263                 if(createNiDll(path, false) != NI_ERROR_NONE) {
264                         fprintf(stderr, "Failed to create NI file [%s]\n", path.c_str());
265                         return;
266                 }
267         };
268         scanFilesInDir(tacDir[0], convert, -1);
269         return TAC_ERROR_NONE;
270 }
271
272 tac_error_e disableTACPackage(const std::string& pkgId)
273 {
274         std::string pkgRoot;
275         if (getRootPath(pkgId, pkgRoot) < 0) {
276                 return TAC_ERROR_INVALID_PACKAGE;
277         }
278
279         std::string binDir = concatPath(pkgRoot, "bin");
280         std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
281         std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
282         if (bf::exists(tacDir)) {
283                 for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
284                         std::string symPath = symlinkAssembly.path().string();
285                         std::string fileName = symlinkAssembly.path().filename().string();
286                         if (bf::is_symlink(symPath)) {
287                                 std::string originPath = bf::read_symlink(symPath).string();
288                                 if (!isNativeImage(symPath)) {
289                                         if (!copyFile(originPath, concatPath(binDir, fileName))) {
290                                                 fprintf(stderr, "Failed to copy of %s\n", concatPath(binDir, fileName).c_str());
291                                                 return TAC_ERROR_UNKNOWN;
292                                         }
293                                         updateAssemblyInfo(binDir.c_str(), concatPath(binDir, fileName).c_str());
294                                 } else {
295                                         if (!copyFile(originPath, concatPath(binNIDir, fileName))) {
296                                                 fprintf(stderr, "Failed to copy of %s\n", concatPath(binNIDir, fileName).c_str());
297                                                 return TAC_ERROR_UNKNOWN;
298                                         }
299                                         updateAssemblyInfo(binDir.c_str(), concatPath(binNIDir, fileName).c_str());
300                                 }
301                         }
302                 }
303         }
304         if (!removeAll(tacDir)) {
305                 fprintf(stderr, "Failed to remove of %s\n", tacDir.c_str());
306                 return TAC_ERROR_UNKNOWN;
307         }
308         return TAC_ERROR_NONE;
309 }
310
311 tac_error_e enableTACPackage(const std::string& pkgId)
312 {
313         std::string rootPath;
314         if (getRootPath(pkgId, rootPath) < 0) {
315                 return TAC_ERROR_INVALID_PACKAGE;
316         }
317
318         std::string execName;
319         if (getExecName(pkgId, execName) < 0) {
320                 return TAC_ERROR_INVALID_PACKAGE;
321         }
322
323         std::string metaValue;
324         if (getMetadataValue(pkgId, TAC_METADATA_KEY, metaValue) < 0) {
325                 return TAC_ERROR_INVALID_PACKAGE;
326         }
327
328         if (initializePathManager(std::string(), std::string(), std::string())) {
329                 fprintf(stderr, "Fail to initialize PathManger");
330                 return TAC_ERROR_UNKNOWN;
331         }
332
333         if (!strcmp(metaValue.c_str(), "true")) {
334                 std::string binDir = concatPath(rootPath, "bin");
335                 std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
336                 std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
337                 if (!bf::exists(tacDir)) {
338                         if (!createDir(tacDir)) {
339                                 fprintf(stderr, "Cannot create directory: %s\n", tacDir.c_str());
340                                 return TAC_ERROR_UNKNOWN;
341                         }
342                         updateAssemblyInfo(binDir.c_str(), tacDir.c_str());
343
344                         enableNuget = depsJsonParser(pkgId, rootPath, execName, getTPA(), true);
345
346                         for (auto& originPath : enableNuget) {
347                                 if (bf::exists(originPath)) {
348                                         std::string fileName = originPath.substr(originPath.rfind('/') + 1);
349                                         std::string NIFileName = fileName.substr(0, fileName.rfind(".dll")) + ".ni.dll";
350                                         if (bf::exists(binNIDir)) {
351                                                 std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
352                                                 if (bf::exists(originNIPath)) {
353                                                         bf::create_symlink(originNIPath, concatPath(tacDir, NIFileName));
354                                                         fprintf(stderr, "%s symbolic link file generated successfully.\n", concatPath(tacDir, NIFileName).c_str());
355                                                         updateAssemblyInfo(tacDir.c_str(), concatPath(tacDir, NIFileName).c_str(), true);
356
357                                                         if (!removeFile(concatPath(binNIDir, NIFileName))) {
358                                                                 fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, NIFileName).c_str());
359                                                                 return TAC_ERROR_UNKNOWN;
360                                                         }
361                                                 }
362                                         }
363                                         bf::create_symlink(originPath, concatPath(tacDir, fileName));
364                                         fprintf(stderr, "%s symbolic link file generated successfully.\n", concatPath(tacDir, fileName).c_str());
365                                         updateAssemblyInfo(tacDir.c_str(), concatPath(tacDir, fileName).c_str(), true);
366
367                                         if (!removeFile(concatPath(binDir, fileName))) {
368                                                 fprintf(stderr, "Failed to remove of %s\n", concatPath(binDir, fileName).c_str());
369                                                 return TAC_ERROR_UNKNOWN;
370                                         }
371                                 }
372                         }
373                         if (enableNuget.empty()) {
374                                 if (!removeAll(tacDir)) {
375                                         _ERR("Failed to remove of %s", tacDir.c_str());
376                                 }
377                         }
378                 }
379         } else {
380                 fprintf(stderr, "The metadata key is missing or the metadata value is false of [%s]\n", pkgId.c_str());
381         }
382         return TAC_ERROR_NONE;
383 }