Modified function name for readability (#263)
[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 <regex>
19 #include <json/json.h>
20 #include <pkgmgr-info.h>
21 #include <pkgmgr_installer_info.h>
22
23 #include "log.h"
24 #include "utils.h"
25 #include "tac_common.h"
26 #include "db_manager.h"
27
28 #ifdef  LOG_TAG
29 #undef  LOG_TAG
30 #endif
31 #define LOG_TAG "DOTNET_INSTALLER_PLUGIN"
32
33 #define __XSTR(x) #x
34 #define __STR(x) __XSTR(x)
35 static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
36 #undef __STR
37 #undef __XSTR
38
39 static sqlite3 *tac_db = NULL;
40 static sqlite3 *tlc_db = NULL;
41 std::vector<std::string> restore_nuget;
42 std::vector<std::string> restore_library;
43
44 static void cleanupDirectory()
45 {
46         std::vector<std::string> removeNuget;
47         try {
48                 for (auto& nuget : bf::recursive_directory_iterator(__DOTNET_DIR)) {
49                         bool isExist = false;
50                         std::string nugetPath = nuget.path().string();
51                         for (auto& restore : restore_nuget) {
52                                 if (!bf::is_directory(nugetPath) || nugetPath.find(TLC_LIBRARIES_DIR) != std::string::npos) {
53                                         isExist = true;
54                                         break;
55                                 }
56                                 if (!strcmp(nugetPath.c_str(), restore.c_str()) ||
57                                         !strcmp(nugetPath.c_str(), restore.substr(0, restore.rfind('/')).c_str())) {
58                                         isExist = true;
59                                         break;
60                                 }
61                         }
62                         if (!isExist) {
63                                 removeNuget.push_back(nugetPath);
64                         }
65                 }
66
67                 for (auto& rm : removeNuget) {
68                         if (!removeAll(rm)) {
69                                 fprintf(stderr, "Failed to remove of %s\n", rm.c_str());
70                         }
71                 }
72                 removeNuget.clear();
73         } catch (const bf::filesystem_error& error) {
74                 fprintf(stderr, "Failed to recursive directory: %s\n", error.what());
75                 return;
76         }
77 }
78
79 // callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach"
80 static int tac_restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData)
81 {
82         char *pkgId = NULL;
83         char *root = NULL;
84         char *exec = NULL;
85         std::string rootPath;
86         std::string execName;
87
88         int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
89         if (ret != PMINFO_R_OK) {
90                 fprintf(stderr, "Failed to get pkgid\n");
91                 return -1;
92         }
93
94         enableTACPackage(std::string(pkgId));
95
96         ret = pkgmgrinfo_appinfo_get_root_path(handle, &root);
97         if (ret != PMINFO_R_OK) {
98                 fprintf(stderr, "Failed to get root path\n");
99                 return -1;
100         }
101         rootPath = std::string(root);
102
103         ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
104         if (ret != PMINFO_R_OK) {
105                 fprintf(stderr, "Failed to get exec name\n");
106                 return -1;
107         }
108         execName = std::string(exec).substr(std::string(exec).rfind('/') + 1);
109
110         std::vector<std::string> parserData;
111         std::string binDir = concatPath(rootPath, "bin");
112         std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
113         for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
114                 std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':'));
115                 std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1);
116                 if (bf::exists(tacDir) && bf::exists(concatPath(tacDir, assemblyName))) {
117                         parserData.push_back(nugetPackage);
118                 }
119         }
120         std::sort(parserData.begin(), parserData.end());
121         parserData.erase(unique(parserData.begin(), parserData.end()), parserData.end());
122
123         for (auto& nuget : parserData) {
124                 if (tac_db) {
125                         std::string name = nuget.substr(0, nuget.find('/'));
126                         std::string version = nuget.substr(nuget.rfind('/') + 1);
127                         char *sql = sqlite3_mprintf(
128                                 "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
129                                 "VALUES (%Q, %Q, %Q, %Q);",     pkgId, nuget.c_str(), name.c_str(), version.c_str());
130                         insertDB(tac_db, sql);
131                         restore_nuget.push_back(concatPath(__DOTNET_DIR, nuget));
132                         sqlite3_free(sql);
133                 }
134         }
135         parserData.clear();
136         return 0;
137 }
138
139 tac_error_e tac_restoreDB()
140 {
141         if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
142                 fprintf(stderr, "Failed to remove of %s\n", TAC_APP_LIST_RESTORE_DB);
143                 return TAC_ERROR_UNKNOWN;
144         }
145
146         std::string dbRestoreJournal = TAC_APP_LIST_RESTORE_DB + std::string("-journal");
147         if (!removeFile(dbRestoreJournal)) {
148                 fprintf(stderr, "Failed to remove of %s\n", dbRestoreJournal.c_str());
149                 return TAC_ERROR_UNKNOWN;
150         }
151
152         tac_db = createDB(TAC_APP_LIST_RESTORE_DB, CREATE_TAC_DB_TABLE);
153         if (!tac_db) {
154                 fprintf(stderr, "Sqlite create error\n");
155                 return TAC_ERROR_UNKNOWN;
156         }
157         sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
158
159         pkgmgrinfo_appinfo_metadata_filter_h handle;
160         int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
161         if (ret != PMINFO_R_OK) {
162                 return TAC_ERROR_UNKNOWN;
163         }
164
165         ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE);
166         if (ret != PMINFO_R_OK) {
167                 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
168                 return TAC_ERROR_UNKNOWN;
169         }
170
171         ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, tac_restoreDBCb, NULL);
172         if (ret != PMINFO_R_OK) {
173                 fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n");
174                 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
175                 return TAC_ERROR_UNKNOWN;
176         }
177         fprintf(stdout, "Success pkgmgrinfo_appinfo_metadata_filter_foreach\n");
178
179         pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
180
181         if (tac_db) {
182                 closeDB(tac_db);
183                 tac_db = NULL;
184         }
185
186         const uid_t g_uid = 301; // app_fw
187         const gid_t g_gid = 301; // app_fw
188
189         if (!copyFile(TAC_APP_LIST_RESTORE_DB, TAC_APP_LIST_DB)) {
190                 fprintf(stderr, "Failed to copy of %s\n", TAC_APP_LIST_DB);
191                 return TAC_ERROR_UNKNOWN;
192         }
193         if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
194                 fprintf(stderr, "Failed to remove of %s\n", TAC_APP_LIST_RESTORE_DB);
195                 return TAC_ERROR_UNKNOWN;
196         }
197         if (chown(TAC_APP_LIST_DB, g_uid, g_gid) == -1) {
198                 fprintf(stderr, "Failed to change owner and group name\n");
199         }
200
201         std::string dbJournal = TAC_APP_LIST_DB + std::string("-journal");
202         if (!copyFile(dbRestoreJournal, dbJournal)) {
203                 fprintf(stderr, "Failed to copy of %s\n", dbJournal.c_str());
204                 return TAC_ERROR_UNKNOWN;
205         }
206         if (!removeFile(dbRestoreJournal)) {
207                 fprintf(stderr, "Failed to remove of %s\n", dbRestoreJournal.c_str());
208                 return TAC_ERROR_UNKNOWN;
209         }
210         if (chown(dbJournal.c_str(), g_uid, g_gid) == -1) {
211                 fprintf(stderr, "Failed to change owner and group name\n");
212         }
213
214         cleanupDirectory();
215
216         return TAC_ERROR_NONE;
217 }
218
219 tac_error_e disableTACPackage(const std::string& pkgId)
220 {
221         std::string rootPath = getRootPath(pkgId);
222         if (rootPath.empty()) {
223                 fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str());
224                 return TAC_ERROR_INVALID_PACKAGE;
225         }
226
227         std::string binDir = concatPath(rootPath, "bin");
228         std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
229         std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
230         if (bf::exists(tacDir)) {
231                 try {
232                         for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
233                                 std::string symPath = symlinkAssembly.path().string();
234                                 std::string fileName = symlinkAssembly.path().filename().string();
235                                 if (bf::is_symlink(symPath)) {
236                                         std::string originPath = bf::read_symlink(symPath).string();
237                                         if (!isNativeImage(symPath)) {
238                                                 std::string dllPath = concatPath(binDir, fileName);
239                                                 if (!copyFile(originPath, dllPath)) {
240                                                         fprintf(stderr, "Failed to copy of %s\n", dllPath.c_str());
241                                                         return TAC_ERROR_UNKNOWN;
242                                                 }
243                                                 copySmackAndOwnership(binDir.c_str(), concatPath(binDir, fileName).c_str());
244                                         } else {
245                                                 std::string niPath = concatPath(binNIDir, fileName);
246                                                 if (!copyFile(originPath, niPath)) {
247                                                         fprintf(stderr, "Failed to copy of %s\n", niPath.c_str());
248                                                         return TAC_ERROR_UNKNOWN;
249                                                 }
250                                                 copySmackAndOwnership(binDir.c_str(), niPath.c_str());
251                                         }
252                                 }
253                         }
254                         if (!removeAll(tacDir)) {
255                                 fprintf(stderr, "Failed to remove of %s\n", tacDir.c_str());
256                                 return TAC_ERROR_UNKNOWN;
257                         }
258                 } catch (const bf::filesystem_error& error) {
259                         fprintf(stderr, "Failed to recursive directory: %s\n", error.what());
260                         return TAC_ERROR_UNKNOWN;
261                 }
262         }
263         return TAC_ERROR_NONE;
264 }
265
266 tac_error_e enableTACPackage(const std::string& pkgId)
267 {
268         std::string rootPath = getRootPath(pkgId);
269         if (rootPath.empty()) {
270                 fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str());
271                 return TAC_ERROR_INVALID_PACKAGE;
272         }
273
274         std::string execName = getExecName(pkgId);
275         if (execName.empty()) {
276                 fprintf(stderr, "Failed to get exec name from [%s]\n", pkgId.c_str());
277                 return TAC_ERROR_INVALID_PACKAGE;
278         }
279
280         std::string metaValue = getMetadataValue(pkgId, TAC_METADATA_KEY);
281         if (metaValue.empty()) {
282                 fprintf(stderr, "Failed to get metadata from [%s]\n", pkgId.c_str());
283                 return TAC_ERROR_INVALID_PACKAGE;
284         }
285
286         if (!strcmp(metaValue.c_str(), "true")) {
287                 std::string binDir = concatPath(rootPath, "bin");
288                 std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
289                 std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
290                 if (!bf::exists(tacDir)) {
291                         if (!createDir(tacDir)) {
292                                 fprintf(stderr, "Cannot create directory: %s\n", tacDir.c_str());
293                                 return TAC_ERROR_UNKNOWN;
294                         }
295                         copySmackAndOwnership(binDir.c_str(), tacDir.c_str());
296
297                         std::vector<std::string> enableNuget;
298                         for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
299                                 std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':'));
300                                 std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1);
301                                 std::string nugetPath = concatPath(__DOTNET_DIR, nugetPackage);
302                                 if (bf::exists(nugetPath)) {
303                                         std::string originPath = concatPath(nugetPath, assemblyName);
304                                         if (bf::exists(originPath)) {
305                                                 enableNuget.push_back(originPath);
306                                         }
307                                 }
308                         }
309
310                         for (auto& originPath : enableNuget) {
311                                 if (bf::exists(originPath)) {
312                                         std::string fileName = originPath.substr(originPath.rfind('/') + 1);
313                                         std::string NIFileName = fileName.substr(0, fileName.rfind(".dll")) + ".ni.dll";
314                                         if (bf::exists(binNIDir)) {
315                                                 std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
316                                                 if (bf::exists(originNIPath)) {
317                                                         bf::create_symlink(originNIPath, concatPath(tacDir, NIFileName));
318                                                         fprintf(stdout, "%s symbolic link file generated successfully.\n", concatPath(tacDir, NIFileName).c_str());
319                                                         copySmackAndOwnership(tacDir.c_str(), concatPath(tacDir, NIFileName).c_str(), true);
320
321                                                         if (!removeFile(concatPath(binNIDir, NIFileName))) {
322                                                                 fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, NIFileName).c_str());
323                                                                 return TAC_ERROR_UNKNOWN;
324                                                         }
325                                                 }
326                                         }
327                                         bf::create_symlink(originPath, concatPath(tacDir, fileName));
328                                         fprintf(stdout, "%s symbolic link file generated successfully.\n", concatPath(tacDir, fileName).c_str());
329                                         copySmackAndOwnership(tacDir.c_str(), concatPath(tacDir, fileName).c_str(), true);
330
331                                         if (!removeFile(concatPath(binDir, fileName))) {
332                                                 fprintf(stderr, "Failed to remove of %s\n", concatPath(binDir, fileName).c_str());
333                                                 return TAC_ERROR_UNKNOWN;
334                                         }
335                                 }
336                         }
337                         if (enableNuget.empty()) {
338                                 if (!removeAll(tacDir)) {
339                                         fprintf(stderr, "Failed to remove of %s\n", tacDir.c_str());
340                                 }
341                         }
342                         enableNuget.clear();
343                 }
344         } else {
345                 fprintf(stderr, "The metadata key is missing or the metadata value is false of [%s]\n", pkgId.c_str());
346         }
347         return TAC_ERROR_NONE;
348 }
349
350 //Parser the .deps.json file to get nuget information.
351 std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName)
352 {
353         std::vector<std::string> parserData;
354         std::string depsJsonName = execName.substr(0, execName.rfind(".dll")) + ".deps.json";
355         std::string depsJsonPath = concatPath(rootPath, depsJsonName);
356         try {
357                 if (bf::exists(depsJsonPath)) {
358                         std::ifstream ifs(depsJsonPath);
359                         Json::CharReaderBuilder reader;
360                         Json::Value root;
361                         std::string error;
362                         if (ifs.is_open()) {
363                                 if (!Json::parseFromStream(reader, ifs, &root, &error)) {
364                                         _ERR("Failed to parse of deps.json");
365                                         ifs.close();
366                                         return parserData;
367                                 }
368                                 const Json::Value runtimeTargetName = root["runtimeTarget"]["name"];
369                                 const Json::Value nugetPackages = root["targets"][runtimeTargetName.asString().c_str()];
370                                 std::vector<std::string> appDependencies;
371                                 for (auto& nuget : nugetPackages.getMemberNames()) {
372                                         if (strstr(nuget.c_str(), (execName.substr(0, execName.find(".Tizen."))).c_str()) != NULL ||
373                                                 strstr(nuget.c_str(), (execName.substr(0, execName.find(".dll"))).c_str()) != NULL) {
374                                                 const Json::Value assemblies = nugetPackages[nuget.c_str()]["runtime"];
375                                                 if (assemblies != Json::nullValue) {
376                                                         const Json::Value dependencies = nugetPackages[nuget.c_str()]["dependencies"];
377                                                         for (auto& dependency : dependencies.getMemberNames()) {
378                                                                 appDependencies.push_back(dependency);
379                                                         }
380                                                 }
381                                         }
382                                 }
383                                 for (auto& nuget : nugetPackages.getMemberNames()) {
384                                         //Skip the nuget package related to Tizen
385                                         if (strstr(nuget.c_str(), TIZEN_DOTNET_NUGET) == NULL &&
386                                                 strstr(nuget.c_str(), TIZEN_DOTNET_SDK_NUGET) == NULL &&
387                                                 strstr(nuget.c_str(), (execName.substr(0, execName.find(".Tizen."))).c_str()) == NULL &&
388                                                 strstr(nuget.c_str(), (execName.substr(0, execName.find(".dll"))).c_str()) == NULL) {
389                                                 const Json::Value assemblies = nugetPackages[nuget.c_str()]["runtime"];
390                                                 if (assemblies != Json::nullValue) {
391                                                         const Json::Value dependencies = nugetPackages[nuget.c_str()]["dependencies"];
392                                                         bool hasDependency = false;
393                                                         for (auto& dependency : dependencies.getMemberNames()) {
394                                                                 //Skip the nugget package that is dependent on another nuget package
395                                                                 if (strstr(dependency.c_str(), TIZEN_DOTNET_NUGET) == NULL &&
396                                                                         strstr(dependency.c_str(), NET_STANDARD_LIBRARY_NUGET) == NULL) {
397                                                                         hasDependency = true;
398                                                                         for (auto& ad : appDependencies) {
399                                                                                 if (!strcmp(ad.c_str(), dependency.c_str())) {
400                                                                                         hasDependency = true;
401                                                                                         break;
402                                                                                 } else {
403                                                                                         hasDependency = false;
404                                                                                 }
405                                                                         }
406                                                                         if (hasDependency) break;
407                                                                 }
408                                                         }
409                                                         if (!hasDependency) {
410                                                                 // handle assembly even though that is included in the TPA.
411                                                                 for (auto& assembly : assemblies.getMemberNames()) {
412                                                                         std::string assemblyName = assembly.substr(assembly.rfind('/') + 1);
413                                                                         parserData.push_back(nuget + ":" + assemblyName);
414                                                                         _INFO("Nuget : [%s] / Assembly : [%s]", nuget.c_str(), assemblyName.c_str());
415                                                                 }
416                                                         }
417                                                 }
418                                         }
419                                 }
420                                 appDependencies.clear();
421                                 ifs.close();
422                         }
423                 }
424         } catch (const Json::LogicError& error) {
425                 _ERR("Failed to parse Json: %s", error.what());
426         }
427         return parserData;
428 }
429
430 std::vector<std::string> getLibrariesInfo(const std::string& rootPath)
431 {
432         std::vector<std::string> LibrariesInfo;
433         std::vector<std::string> unusedDir;
434         std::string runtimesDir = concatPath(rootPath, "bin/runtimes");
435         if (!bf::exists(runtimesDir))
436                 return LibrariesInfo;
437
438         char buffer[128];
439         sprintf(buffer, "(tizen|linux|unix|base|any)(.\\d.\\d.\\d)?(-%s)?", ARCHITECTURE_IDENTIFIER);
440         std::regex pattern(buffer);
441
442         try {
443                 for (auto& path : bf::recursive_directory_iterator(runtimesDir)) {
444                         std::string filepath = path.path().string();
445                         std::size_t pos = filepath.rfind("/runtimes/");
446                         if (pos != std::string::npos) {
447                                 std::string targetDir = filepath.substr(pos + 10);
448                                 if (!std::regex_match(targetDir.substr(0, targetDir.find('/')), pattern)) {
449                                         if (isDirectory(filepath))
450                                                 unusedDir.push_back(filepath);
451                                         continue;
452                                 }
453                         }
454                         if (filepath.rfind(".so") == std::string::npos)
455                                 continue;
456
457                         std::string buffer = SHA256(filepath);
458                         LibrariesInfo.push_back(filepath + ":" + buffer);
459                         _INFO("Library : [%s] / SHA256 : [%s]", filepath.substr(filepath.rfind('/') + 1).c_str(), buffer.c_str());
460                 }
461         } catch (const bf::filesystem_error& error) {
462                 _ERR("Failed to recursive directory: %s", error.what());
463         }
464
465         for (auto& path : unusedDir) {
466                 if (!removeAll(path)) {
467                         _ERR("Failed to remove of %s", path.c_str());
468                 }
469         }
470         unusedDir.clear();
471
472         return LibrariesInfo;
473 }
474
475 // callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach"
476 static int tlc_restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData)
477 {
478         char *pkgId = NULL;
479         char *root = NULL;
480         std::string rootPath;
481
482         int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
483         if (ret != PMINFO_R_OK) {
484                 fprintf(stderr, "Failed to get pkgid\n");
485                 return -1;
486         }
487
488         ret = pkgmgrinfo_appinfo_get_root_path(handle, &root);
489         if (ret != PMINFO_R_OK) {
490                 fprintf(stderr, "Failed to get root path\n");
491                 return -1;
492         }
493         rootPath = std::string(root);
494
495         for (auto& librarySha : getLibrariesInfo(rootPath)) {
496                 std::string library = librarySha.substr(0, librarySha.find(':'));
497                 if (bf::exists(library)) {
498                         std::string fileSha = library.substr(library.rfind('/') + 1) + ".." + librarySha.substr(librarySha.find(':') + 1);
499                         char *sql = sqlite3_mprintf("INSERT INTO TLC (PKGID, LIBRARY) VALUES (%Q, %Q);", pkgId, fileSha.c_str());
500                         insertDB(tlc_db, sql);
501                         restore_library.push_back(fileSha);
502                         sqlite3_free(sql);
503                 }
504         }
505         return 0;
506 }
507
508 tac_error_e tlc_restoreDB()
509 {
510         if (!removeFile(TLC_APP_LIST_RESTORE_DB)) {
511                 fprintf(stderr, "Failed to remove of %s\n", TLC_APP_LIST_RESTORE_DB);
512                 return TAC_ERROR_UNKNOWN;
513         }
514
515         std::string dbRestoreJournal = TLC_APP_LIST_RESTORE_DB + std::string("-journal");
516         if (!removeFile(dbRestoreJournal)) {
517                 fprintf(stderr, "Failed to remove of %s\n", dbRestoreJournal.c_str());
518                 return TAC_ERROR_UNKNOWN;
519         }
520
521         tlc_db = createDB(TLC_APP_LIST_RESTORE_DB, CREATE_TLC_DB_TABLE);
522         if (!tlc_db) {
523                 fprintf(stderr, "Sqlite create error\n");
524                 return TAC_ERROR_UNKNOWN;
525         }
526         sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL);
527
528         pkgmgrinfo_appinfo_metadata_filter_h handle;
529         int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
530         if (ret != PMINFO_R_OK) {
531                 return TAC_ERROR_UNKNOWN;
532         }
533
534         ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE);
535         if (ret != PMINFO_R_OK) {
536                 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
537                 return TAC_ERROR_UNKNOWN;
538         }
539
540         ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, tlc_restoreDBCb, NULL);
541         if (ret != PMINFO_R_OK) {
542                 fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n");
543                 pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
544                 return TAC_ERROR_UNKNOWN;
545         }
546         fprintf(stdout, "Success pkgmgrinfo_appinfo_metadata_filter_foreach\n");
547
548         pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
549
550         if (tlc_db) {
551                 closeDB(tlc_db);
552                 tlc_db = NULL;
553         }
554
555         const uid_t g_uid = 301; // app_fw
556         const gid_t g_gid = 301; // app_fw
557
558         if (!copyFile(TLC_APP_LIST_RESTORE_DB, TLC_APP_LIST_DB)) {
559                 fprintf(stderr, "Failed to copy of %s\n", TLC_APP_LIST_DB);
560                 return TAC_ERROR_UNKNOWN;
561         }
562         if (!removeFile(TLC_APP_LIST_RESTORE_DB)) {
563                 fprintf(stderr, "Failed to remove of %s\n", TLC_APP_LIST_RESTORE_DB);
564                 return TAC_ERROR_UNKNOWN;
565         }
566         if (chown(TLC_APP_LIST_DB, g_uid, g_gid) == -1) {
567                 fprintf(stderr, "Failed to change owner and group name\n");
568         }
569
570         std::string dbJournal = TLC_APP_LIST_DB + std::string("-journal");
571         if (!copyFile(dbRestoreJournal, dbJournal)) {
572                 fprintf(stderr, "Failed to copy of %s\n", dbJournal.c_str());
573                 return TAC_ERROR_UNKNOWN;
574         }
575         if (!removeFile(dbRestoreJournal)) {
576                 fprintf(stderr, "Failed to remove of %s\n", dbRestoreJournal.c_str());
577                 return TAC_ERROR_UNKNOWN;
578         }
579         if (chown(dbJournal.c_str(), g_uid, g_gid) == -1) {
580                 fprintf(stderr, "Failed to change owner and group name\n");
581         }
582
583         auto convert = [](const std::string& path, const std::string& filename) {
584                 bool isExist = false;
585                 for (auto& library : restore_library) {
586                         if (!strcmp(filename.c_str(), library.c_str())) {
587                                 isExist = true;
588                                 break;
589                         }
590                 }
591                 if (!isExist) {
592                         if (!removeFile(path)) {
593                                 _ERR("Failed to remove of %s", path.c_str());
594                         }
595                 }
596         };
597
598         scanFilesInDirectory(concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR), convert, 0);
599
600         return TAC_ERROR_NONE;
601 }