2 * Copyright (c) 2022 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.
19 #include "db_manager.h"
20 #include "tac_common.h"
21 #include "tac_installer.h"
28 #include <boost/filesystem.hpp>
29 #include <json/json.h>
30 #include <pkgmgr-info.h>
35 #define LOG_TAG "DOTNET_INSTALLER_PLUGIN"
38 #define __STR(x) __XSTR(x)
39 static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
43 std::vector<std::string> nugetPackagesAssembliesSha;
44 std::vector<std::string> tacDB;
45 std::vector<std::string> createDirectories;
46 std::vector<std::string> createLibraries;
47 std::vector<std::string> updateTac;
48 tac_state tacState = TAC_STATE_NONE;
49 static sqlite3 *tac_db = NULL;
50 static sqlite3 *tlc_db = NULL;
51 bool tacPluginInstalled = false;
52 bool tacPluginFinished = false;
54 static void createSHA256Info(std::string sha256Info, std::string nugetPackage)
56 std::ofstream ofs(sha256Info, std::ios::app);
57 int assembly_count = 0;
58 for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
59 std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind(':'));
60 std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind(':'));
61 std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind(':') + 1);
62 std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1);
63 if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) {
64 ofs << assembly << ":" << sha << std::endl;
68 ofs << assembly_count << std::endl;
72 static bool compareSHA256Info(std::string sha256Info, std::string nugetPackage)
74 int compare_count = 0;
75 int assembly_count = 0;
76 std::string sha256_count = "0";
77 for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
78 std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind(':'));
79 std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind(':'));
80 std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind(':') + 1);
81 std::string sha = npAssemblySha.substr(npAssemblySha.rfind(':') + 1);
82 if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) {
84 std::ifstream ifs(sha256Info);
87 while (getline(ifs, get_str)) {
88 if (!strcmp(get_str.c_str(), (assembly + ":" + sha).c_str())) {
91 sha256_count = get_str;
97 if (!strcmp(std::to_string(assembly_count).c_str(), std::to_string(compare_count).c_str()) &&
98 !strcmp(std::to_string(assembly_count).c_str(), sha256_count.c_str())) {
99 _INFO("Same nuget : %s", nugetPackage.c_str());
105 static bool copyAssemblyCreateSymlink(std::string binPath, std::string tacDir, std::string nugetPackage, bool isCreateTacDir)
107 std::string binNiPath = concatPath(binPath, APP_NI_SUB_DIR);
108 std::string tac_version_dir = concatPath(__DOTNET_DIR, nugetPackage);
109 bool nuget_restoration = false;
110 for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
111 std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind(':'));
112 std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind(':'));
113 std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind(':') + 1);
114 if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) {
115 if (exist(concatPath(binPath, assembly))) {
116 std::string niFile = changeExtension(assembly, ".dll", ".ni.dll");
117 bs::error_code error;
118 if (isCreateTacDir) {
119 if (!copyFile(concatPath(binPath, assembly), concatPath(tac_version_dir, assembly))) {
120 _ERR("Failed to copy of %s", assembly.c_str());
121 nuget_restoration = true;
124 if (exist(binNiPath) && !copyFile(concatPath(binNiPath, niFile), concatPath(tac_version_dir, niFile))) {
125 _ERR("Failed to copy of %s", niFile.c_str());
128 bf::create_symlink(concatPath(tac_version_dir, assembly), concatPath(tacDir, assembly), error);
130 _ERR("Failed to create symlink %s file", concatPath(tacDir, assembly).c_str());
131 nuget_restoration = true;
134 if (exist(concatPath(tac_version_dir, niFile)) && exist(binNiPath)) {
135 bf::create_symlink(concatPath(tac_version_dir, niFile), concatPath(tacDir, niFile), error);
137 _ERR("Failed to create symlink %s file", concatPath(tacDir, niFile).c_str());
141 copySmackAndOwnership(tacDir, concatPath(tacDir, assembly), true);
143 if (!removeFile(concatPath(binPath, assembly))) {
144 _ERR("Failed to remove of %s", assembly.c_str());
145 nuget_restoration = true;
148 if (!removeFile(concatPath(binNiPath, niFile))) {
149 _ERR("Failed to remove of %s", niFile.c_str());
155 if (nuget_restoration) {
156 for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
157 std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind(':'));
158 std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind(':'));
159 std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind(':') + 1);
160 if (!strcmp(nuget_package.c_str(), nugetPackage.c_str())) {
161 copyFile(concatPath(tac_version_dir, assembly), concatPath(binPath, assembly));
162 copySmackAndOwnership(binPath, concatPath(binPath, assembly));
163 removeFile(concatPath(tacDir, assembly));
168 return nuget_restoration;
171 static void copyLibraryCreateSymlink(const std::string pkgId, std::vector<std::string> LibrariesInfo, std::string tlcDir)
173 if (LibrariesInfo.empty()) {
177 for (auto& librarySha : LibrariesInfo) {
178 std::string library = librarySha.substr(0, librarySha.find(':'));
179 std::string filename = library.substr(library.rfind('/') + 1);
180 std::string fileSha = filename + ".." + librarySha.substr(librarySha.find(':') + 1);
181 bool fileCopied = false;
182 if (!exist(concatPath(tlcDir, fileSha))) {
183 if (!copyFile(library, concatPath(tlcDir, fileSha))) {
184 _ERR("Failed to copy of %s", filename.c_str());
188 createLibraries.push_back(concatPath(tlcDir, fileSha));
190 if (!removeFile(library)) {
191 _ERR("Failed to remove of %s", library.c_str());
193 removeFile(concatPath(tlcDir, fileSha));
197 bs::error_code error;
198 bf::create_symlink(concatPath(tlcDir, fileSha), library, error);
200 _ERR("Failed to create symlink %s file", library.c_str());
201 copyFile(concatPath(tlcDir, fileSha), library);
202 copySmackAndOwnership(getBaseName(library), library);
204 removeFile(concatPath(tlcDir, fileSha));
208 copySmackAndOwnership(getBaseName(library), library, true);
210 char *sql = sqlite3_mprintf("INSERT INTO TLC (PKGID, LIBRARY) VALUES (%Q, %Q);", pkgId.c_str(), fileSha.c_str());
211 if (!insertDB(tlc_db, sql)) {
212 _ERR("Sqlite insert error");
214 copyFile(concatPath(tlcDir, fileSha), library);
215 copySmackAndOwnership(getBaseName(library), library);
217 removeFile(concatPath(tlcDir, fileSha));
225 static void checkDepsJson(std::string rootPath, std::string binPath, std::string execName)
227 for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
228 std::string nuget_package = npAssembly.substr(0, npAssembly.rfind(':'));
229 std::string assembly_name = npAssembly.substr(npAssembly.rfind(':') + 1);
230 tacDB.push_back(nuget_package);
231 std::string buffer = SHA256(concatPath(binPath, assembly_name));
232 nugetPackagesAssembliesSha.push_back(nuget_package + ":" + assembly_name + ":" + buffer);
233 _INFO("Assembly : [%s] / SHA256 : [%s]", assembly_name.c_str(), buffer.c_str());
235 std::sort(tacDB.begin(), tacDB.end());
236 tacDB.erase(unique(tacDB.begin(), tacDB.end()), tacDB.end());
239 int tacInstall(const std::string& pkgId, tac_state state, bool tacForce)
241 _DBG("[===== PKGMGR_MDPARSER_PLUGIN_INSTALL =====]");
242 _INFO("PackageID : %s", pkgId.c_str());
244 // Can be multiple apps in one package
245 if (tacPluginInstalled) {
246 _INFO("TAC plugin already installed");
249 tacPluginInstalled = true;
251 std::string appType = getAppType(pkgId);
252 if (strstr(appType.c_str(), "dotnet") == NULL) {
253 _ERR("App type is not dotnet");
256 std::string execName = getExecName(pkgId);
257 std::string rootPath = getRootPath(pkgId);
258 if (execName.empty() || rootPath.empty()) {
262 std::string binPath = concatPath(rootPath, "bin");
263 if (exist(concatPath(binPath, PRE_COMPILED_PACKAGE_FILE))) {
264 _INFO("The %s is a Pre-Compiled package. So, skip the TAC", pkgId.c_str());
268 std::string metaValue = getMetadataValue(pkgId, TAC_METADATA_KEY);
270 if (metaValue.empty()) {
274 if (metaValue == METADATA_VALUE_TRUE || tacForce) {
275 checkDepsJson(rootPath, binPath, execName);
283 tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE);
285 _ERR("Sqlite create error. So restore the database.");
286 if (tac_restoreDB() != TAC_ERROR_NONE) {
287 _ERR("Sqlite create error");
290 tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE);
292 _ERR("Sqlite create error");
296 sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
298 std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR);
299 if (!createDir(tac_dir)) {
300 _ERR("Cannot create directory: %s", tac_dir.c_str());
303 copySmackAndOwnership(binPath.c_str(), tac_dir.c_str());
305 for (auto& np : tacDB) {
306 std::string tac_name = np.substr(0, np.find('/'));
307 std::string tac_version = np.substr(np.rfind('/') + 1);
308 _INFO("TAC name : %s", tac_name.c_str());
309 _INFO("TAC version : %s", tac_version.c_str());
311 bs::error_code error;
312 std::string tac_version_dir = concatPath(__DOTNET_DIR, np);
313 std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO);
314 if (!exist(tac_version_dir)) {
315 _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str());
316 if (!createDir(tac_version_dir)) {
317 _ERR("Cannot create directory: %s", tac_version_dir.c_str());
318 tacState = TAC_STATE_RESTORE;
321 createDirectories.push_back(tac_version_dir);
322 if (!isSymlinkFile(sha256_info)) {
323 createSHA256Info(sha256_info, np);
325 _ERR("Failed to create sha256_info. Symbolic link is detected");
326 tacState = TAC_STATE_RESTORE;
330 if (!exist(sha256_info)) {
331 tacState = TAC_STATE_RESTORE;
335 if (copyAssemblyCreateSymlink(binPath, tac_dir, np, true)) {
336 _ERR("Failed to create symlink");
337 tacState = TAC_STATE_RESTORE;
341 char *sql = sqlite3_mprintf(
342 "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
343 "VALUES (%Q, %Q, %Q, %Q);", pkgId.c_str(), np.c_str(), tac_name.c_str(), tac_version.c_str());
344 if (!insertDB(tac_db, sql)) {
345 _ERR("Sqlite insert error");
347 tacState = TAC_STATE_RESTORE;
352 _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str());
353 if (!isSymlinkFile(sha256_info)) {
354 if (compareSHA256Info(sha256_info, np)) {
355 if (copyAssemblyCreateSymlink(binPath, tac_dir, np, false)) {
356 _ERR("Failed to create symlink");
357 tacState = TAC_STATE_RESTORE;
361 char *sql = sqlite3_mprintf(
362 "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
363 "VALUES (%Q, %Q, %Q, %Q);", pkgId.c_str(), np.c_str(), tac_name.c_str(), tac_version.c_str());
364 if (!insertDB(tac_db, sql)) {
365 _ERR("Sqlite insert error");
367 tacState = TAC_STATE_RESTORE;
372 _INFO("Different nuget : %s", np.c_str());
376 _ERR("Failed to create sha256_info. Symbolic link is detected");
377 tacState = TAC_STATE_RESTORE;
384 std::string tlcDir = concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR);
385 if (!createDir(tlcDir)) {
386 _ERR("Cannot create directory: %s", tlcDir.c_str());
389 copySmackAndOwnership(__DOTNET_DIR, tlcDir);
391 tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE);
393 _ERR("Sqlite create error. So restore the database.");
394 if (tlc_restoreDB() != TAC_ERROR_NONE) {
395 _ERR("Sqlite create error");
398 tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE);
400 _ERR("Sqlite create error");
404 sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL);
406 copyLibraryCreateSymlink(pkgId, getLibrariesInfo(rootPath), tlcDir);
411 static int sqliteCb(void *count, int argc, char **argv, char **colName)
413 int *c = (int*)count;
418 static void tac_updateDB(sqlite3 *sqlite)
420 for (auto& unp : updateTac) {
422 char *sql = sqlite3_mprintf("SELECT COUNT(NUGET) FROM TAC WHERE NUGET = %Q;", unp.c_str());
423 int ret = sqlite3_exec(sqlite, sql, sqliteCb, &count, NULL);
424 if (ret != SQLITE_OK) {
425 _ERR("Sqlite select error");
430 std::string tac_version_dir_prev = concatPath(__DOTNET_DIR, unp);
431 std::string tac_version_dir_backup = tac_version_dir_prev + ".bck";
432 if (!copyDir(tac_version_dir_prev, tac_version_dir_backup)) {
433 _ERR("Failed to copy of %s to %s", tac_version_dir_prev.c_str(), tac_version_dir_backup.c_str());
437 if (!removeAll(tac_version_dir_prev)) {
438 _ERR("Failed to remove of %s", tac_version_dir_prev.c_str());
447 static void tlc_updateDB(sqlite3 *sqlite, std::vector<std::string> updateTlc, std::string tlcDir)
449 for (auto& ulp : updateTlc) {
451 char *sql = sqlite3_mprintf("SELECT COUNT(LIBRARY) FROM TLC WHERE LIBRARY = %Q;", ulp.c_str());
452 int ret = sqlite3_exec(sqlite, sql, sqliteCb, &count, NULL);
453 if (ret != SQLITE_OK) {
454 _ERR("Sqlite select error");
459 std::string library_prev = concatPath(tlcDir, ulp);
460 std::string library_backup = library_prev + ".bck";
461 if (!copyFile(library_prev, library_backup)) {
462 _ERR("Failed to copy of %s", library_prev.c_str());
466 if (!removeFile(library_prev)) {
467 _ERR("Failed to remove of %s", library_prev.c_str());
476 int tacUpgrade(const std::string& pkgId, tac_state state, bool tacForce)
478 _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UPGRADE =====]");
479 _INFO("PackageID : %s", pkgId.c_str());
481 // Can be multiple apps in one package
482 if (tacPluginInstalled) {
483 _INFO("TAC plugin already upgraded");
486 tacPluginInstalled = true;
488 std::string appType = getAppType(pkgId);
489 if (strstr(appType.c_str(), "dotnet") == NULL) {
490 _ERR("App type is not dotnet");
493 std::string execName = getExecName(pkgId);
494 std::string rootPath = getRootPath(pkgId);
495 if (execName.empty() || rootPath.empty()) {
499 std::string binPath = concatPath(rootPath, "bin");
500 if (exist(concatPath(binPath, PRE_COMPILED_PACKAGE_FILE))) {
501 _INFO("The %s is a Pre-Compiled package. So, skip the TAC", pkgId.c_str());
502 state = TAC_STATE_REMOVED;
505 if (state == TAC_STATE_REMOVED) {
506 _INFO("Skipped to parse of deps.json");
507 } else { //TAC_STATE_UPGRADE
508 std::string metaValue = getMetadataValue(pkgId, TAC_METADATA_KEY);
510 if (metaValue.empty()) {
514 if (metaValue == METADATA_VALUE_TRUE || tacForce) {
515 checkDepsJson(rootPath, binPath, execName);
519 tacState = TAC_STATE_UPGRADE;
520 tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE);
522 _ERR("Sqlite create error. So restore the database.");
523 if (tac_restoreDB() != TAC_ERROR_NONE) {
524 _ERR("Sqlite create error");
527 tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE);
529 _ERR("Sqlite create error");
533 sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
535 char *sql = sqlite3_mprintf("SELECT * FROM TAC WHERE PKGID = %Q;", pkgId.c_str());
536 updateTac = selectDB(tac_db, sql);
539 bool skipTLC = false;
541 sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q;", pkgId.c_str());
542 if (!deleteDB(tac_db, sql)) {
543 _ERR("Sqlite delete error");
549 tac_updateDB(tac_db);
553 std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR);
554 if (!createDir(tac_dir)) {
555 _ERR("Cannot create directory: %s", tac_dir.c_str());
558 copySmackAndOwnership(binPath.c_str(), tac_dir.c_str());
560 for (auto& np : tacDB) {
561 std::string tac_name = np.substr(0, np.find('/'));
562 std::string tac_version = np.substr(np.rfind('/') + 1);
563 _INFO("TAC name : %s", tac_name.c_str());
564 _INFO("TAC version : %s", tac_version.c_str());
566 bs::error_code error;
567 std::string tac_version_dir = concatPath(__DOTNET_DIR, np);
568 std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO);
569 if (!exist(tac_version_dir)) {
570 _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str());
571 if (!createDir(tac_version_dir)) {
572 _ERR("Cannot create directory: %s", tac_version_dir.c_str());
573 tacState = TAC_STATE_RESTORE;
576 createDirectories.push_back(tac_version_dir);
577 if (!isSymlinkFile(sha256_info)) {
578 createSHA256Info(sha256_info, np);
580 _ERR("Failed to create sha256_info. Symbolic link is detected");
581 tacState = TAC_STATE_RESTORE;
585 if (!exist(sha256_info)) {
586 tacState = TAC_STATE_RESTORE;
590 if (copyAssemblyCreateSymlink(binPath, tac_dir, np, true)) {
591 _ERR("Failed to create symlink");
592 tacState = TAC_STATE_RESTORE;
597 sql = sqlite3_mprintf(
598 "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = %Q AND NAME = %Q;", pkgId.c_str(), tac_name.c_str());
599 int ret = sqlite3_exec(tac_db, sql, sqliteCb, &count, NULL);
600 if (ret != SQLITE_OK) {
601 _ERR("Sqlite select error");
603 tacState = TAC_STATE_RESTORE;
608 sql = sqlite3_mprintf(
609 "UPDATE TAC SET NAME = %Q, VERSION = %Q, NUGET = %Q WHERE PKGID = %Q AND NAME = %Q;",
610 tac_name.c_str(), tac_version.c_str(), np.c_str(), pkgId.c_str(), tac_name.c_str());
611 if (!updateDB(tac_db, sql)) {
612 _ERR("Sqlite update error");
614 tacState = TAC_STATE_RESTORE;
618 } else if (count == 0) {
619 sql = sqlite3_mprintf(
620 "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
621 "VALUES (%Q, %Q, %Q, %Q);", pkgId.c_str(), np.c_str(), tac_name.c_str(), tac_version.c_str());
622 if (!insertDB(tac_db, sql)) {
623 _ERR("Sqlite insert error");
625 tacState = TAC_STATE_RESTORE;
631 _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str());
632 if (!isSymlinkFile(sha256_info)) {
633 if (compareSHA256Info(sha256_info, np)) {
634 if (copyAssemblyCreateSymlink(binPath, tac_dir, np, false)) {
635 _ERR("Failed to create symlink");
636 tacState = TAC_STATE_RESTORE;
641 char *sql = sqlite3_mprintf(
642 "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = %Q AND NAME = %Q;", pkgId.c_str(), tac_name.c_str());
643 int ret = sqlite3_exec(tac_db, sql, sqliteCb, &count, NULL);
644 if (ret != SQLITE_OK) {
645 _ERR("Sqlite select error");
647 tacState = TAC_STATE_RESTORE;
652 sql = sqlite3_mprintf(
653 "UPDATE TAC SET NAME = %Q, VERSION = %Q, NUGET = %Q WHERE PKGID = %Q AND NAME = %Q;",
654 tac_name.c_str(), tac_version.c_str(), np.c_str(), pkgId.c_str(), tac_name.c_str());
655 if (!updateDB(tac_db, sql)) {
656 _ERR("Sqlite update error");
658 tacState = TAC_STATE_RESTORE;
662 } else if (count == 0) {
663 sql = sqlite3_mprintf(
664 "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
665 "VALUES (%Q, %Q, %Q, %Q);", pkgId.c_str(), np.c_str(), tac_name.c_str(), tac_version.c_str());
666 if (!insertDB(tac_db, sql)) {
667 _ERR("Sqlite insert error");
669 tacState = TAC_STATE_RESTORE;
675 _INFO("Different nuget : %s", np.c_str());
679 _ERR("Failed to create sha256_info. Symbolic link is detected");
680 tacState = TAC_STATE_RESTORE;
685 for (auto& unp : updateTac) {
686 bool isExits = false;
687 for (auto& np : tacDB) {
688 if (!strcmp(unp.c_str(), np.c_str())) {
694 char *sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q AND NUGET = %Q;", pkgId.c_str(), unp.c_str());
695 if (!deleteDB(tac_db, sql)) {
696 _ERR("Sqlite delete error");
698 tacState = TAC_STATE_RESTORE;
704 tac_updateDB(tac_db);
708 std::string tlcDir = concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR);
709 if (!createDir(tlcDir)) {
710 _ERR("Cannot create directory: %s", tlcDir.c_str());
713 copySmackAndOwnership(__DOTNET_DIR, tlcDir);
715 tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE);
717 _ERR("Sqlite create error. So restore the database.");
718 if (tlc_restoreDB() != TAC_ERROR_NONE) {
719 _ERR("Sqlite create error");
722 tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE);
724 _ERR("Sqlite create error");
728 sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL);
730 sql = sqlite3_mprintf("SELECT * FROM TLC WHERE PKGID = %Q;", pkgId.c_str());
731 std::vector<std::string> updateTlc = selectDB(tlc_db, sql);
734 sql = sqlite3_mprintf("DELETE FROM TLC WHERE PKGID = %Q;", pkgId.c_str());
735 if (!deleteDB(tlc_db, sql)) {
736 _ERR("Sqlite delete error");
742 std::vector<std::string> librariesInfo;
744 librariesInfo = getLibrariesInfo(rootPath);
747 copyLibraryCreateSymlink(pkgId, librariesInfo, tlcDir);
749 tlc_updateDB(tlc_db, updateTlc, tlcDir);
754 int tacUninstall(const std::string& pkgId, tac_state state)
756 _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNINSTALL =====]");
757 _INFO("PackageID : %s", pkgId.c_str());
759 // Can be multiple apps in one package
760 if (tacPluginInstalled) {
761 _INFO("TAC plugin already uninstalled");
764 tacPluginInstalled = true;
767 tac_db = openDB(TAC_APP_LIST_DB);
769 _ERR("Sqlite open error. So restore the database.");
770 if (tac_restoreDB() != TAC_ERROR_NONE) {
771 _ERR("Sqlite open error");
774 tac_db = openDB(TAC_APP_LIST_DB);
776 _ERR("Sqlite open error");
780 sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
782 char *sql = sqlite3_mprintf("SELECT * FROM TAC WHERE PKGID = %Q;", pkgId.c_str());
783 updateTac = selectDB(tac_db, sql);
786 sql = sqlite3_mprintf("DELETE FROM TAC WHERE PKGID = %Q;", pkgId.c_str());
788 if (!deleteDB(tac_db, sql)) {
789 _ERR("Sqlite delete error");
791 tacState = TAC_STATE_RESTORE;
796 tac_updateDB(tac_db);
799 tlc_db = openDB(TLC_APP_LIST_DB);
801 _ERR("Sqlite open error. So restore the database.");
802 if (tlc_restoreDB() != TAC_ERROR_NONE) {
803 _ERR("Sqlite open error");
806 tlc_db = openDB(TLC_APP_LIST_DB);
808 _ERR("Sqlite open error");
812 sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL);
814 sql = sqlite3_mprintf("SELECT * FROM TLC WHERE PKGID = %Q;", pkgId.c_str());
815 std::vector<std::string> updateTlc = selectDB(tlc_db, sql);
818 sql = sqlite3_mprintf("DELETE FROM TLC WHERE PKGID = %Q;", pkgId.c_str());
819 if (!deleteDB(tlc_db, sql)) {
820 _ERR("Sqlite delete error");
826 tlc_updateDB(tlc_db, updateTlc, concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR));
831 int tacRemoved(const std::string& pkgId)
833 _DBG("[===== PKGMGR_MDPARSER_PLUGIN_REMOVED =====]");
834 _INFO("PackageID : %s", pkgId.c_str());
836 return tacUpgrade(pkgId, TAC_STATE_REMOVED);
839 void undoStep(std::string tac)
841 std::string current_tac = concatPath(__DOTNET_DIR, tac.substr(0, tac.find('/')));
843 for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
844 std::string bck_path = bck.path().string();
845 if (bf::is_directory(bck_path) && strstr(bck_path.c_str(), ".bck") != NULL) {
846 if (!moveFile(bck_path, bck_path.substr(0, bck_path.rfind(".bck")))) {
847 _ERR("Failed to move %s", bck_path.c_str());
852 } catch (const bf::filesystem_error& error) {
853 _ERR("Failed to recursive directory: %s", error.what());
858 auto convert = [](const std::string& path, const std::string& filename) {
859 if (filename.rfind(".bck") != std::string::npos) {
860 if (!moveFile(path, replaceAll(path, ".bck", ""))) {
861 _ERR("Failed to move %s", path.c_str());
866 scanFilesInDirectory(concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR), convert, 0);
871 for (auto& cd : createDirectories) {
872 if (!removeAll(cd)) {
873 _ERR("Failed to remove of %s", cd.c_str());
877 for (auto& cl : createLibraries) {
878 if (!removeFile(cl)) {
879 _ERR("Failed to remove of %s", cl.c_str());
884 void unInstall_Undo()
886 for (auto& unp : updateTac) {
894 if (!tacDB.empty()) {
895 for (auto& np : tacDB) {
902 int tacUndo(const std::string& pkgId)
904 _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNDO =====]");
905 _INFO("PackageID : %s", pkgId.c_str());
907 // Can be multiple apps in one package
908 if (tacPluginFinished) {
909 _INFO("TAC plugin already finished(UNDO)");
912 tacPluginFinished = true;
914 if (tacState == TAC_STATE_INSTALL) {
916 } else if (tacState == TAC_STATE_UPGRADE) {
918 } else if (tacState == TAC_STATE_UNINSTALL) {
920 } else if (tacState == TAC_STATE_RESTORE) {
937 void changeOwnershipTAC(std::string current_tac)
939 copySmackAndOwnership(__DOTNET_DIR, current_tac);
941 for (auto& path : bf::recursive_directory_iterator(current_tac))
942 copySmackAndOwnership(__DOTNET_DIR, path.path().string());
943 } catch (const bf::filesystem_error& error) {
944 _ERR("Failed to recursive directory: %s", error.what());
948 void cleanStep(std::string tac)
950 std::string current_tac = concatPath(__DOTNET_DIR, tac.substr(0, tac.find('/')));
952 for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
953 std::string bck_path = bck.path().string();
954 if (bf::is_directory(bck_path) && strstr(bck_path.c_str(), ".bck") != NULL) {
955 if (!removeAll(bck_path)) {
956 _ERR("Failed to remove of %s", bck_path.c_str());
962 bool isExist = false;
963 for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
964 std::string bck_path = bck.path().string();
965 if (exist(bck_path) && bf::is_directory(bck_path) && strstr(bck_path.c_str(), ".bck") == NULL) {
971 if (!removeAll(current_tac)) {
972 _ERR("Failed to remove of %s", current_tac.c_str());
975 } catch (const bf::filesystem_error& error) {
976 _ERR("Failed to recursive directory: %s", error.what());
981 auto convert = [](const std::string& path, const std::string& filename) {
982 if (filename.rfind(".bck") != std::string::npos) {
983 if (!removeFile(path)) {
984 _ERR("Failed to remove of %s", path.c_str());
989 scanFilesInDirectory(concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR), convert, 0);
994 for (auto& cd : createDirectories) {
995 changeOwnershipTAC(cd);
996 copySmackAndOwnership(__DOTNET_DIR, cd.substr(0, cd.rfind('/')));
999 for (auto& cl : createLibraries) {
1000 changeOwnershipTAC(cl);
1004 void unInstall_Clean()
1006 for (auto& unp : updateTac) {
1014 if (!tacDB.empty()) {
1015 for (auto& np : tacDB) {
1017 changeOwnershipTAC(concatPath(__DOTNET_DIR, np.substr(0, np.find('/'))));
1023 int tacClean(const std::string& pkgId)
1025 if (tacState == TAC_STATE_RESTORE) {
1026 disableTACPackage(pkgId);
1028 std::string rootPath = getRootPath(pkgId);
1029 if (!rootPath.empty()) {
1030 std::string binPath = concatPath(rootPath, "bin");
1031 removeAll(concatPath(binPath, TAC_SYMLINK_SUB_DIR));
1034 std::string runtimesDir = concatPath(rootPath, "bin/runtimes");
1035 if (exist(runtimesDir)) {
1037 sprintf(buffer, "(tizen|linux|unix|base|any)(.\\d.\\d.\\d)?(-%s)?", ARCHITECTURE_IDENTIFIER);
1038 std::regex pattern(buffer);
1041 for (auto& path : bf::recursive_directory_iterator(runtimesDir)) {
1042 std::string symPath = path.path().string();
1043 if (isDirectory(symPath) || !isSymlinkFile(symPath))
1045 std::string targetDir = symPath.substr(symPath.rfind("/runtimes/") + 10);
1046 if (!std::regex_match(targetDir.substr(0, targetDir.find('/')), pattern))
1048 if (symPath.rfind(".so") == std::string::npos)
1050 copyFile(bf::read_symlink(symPath).string(), symPath);
1052 } catch (const bf::filesystem_error& error) {
1053 _ERR("Failed to recursive directory: %s", error.what());
1057 return tacUndo(pkgId);
1060 _DBG("[===== PKGMGR_MDPARSER_PLUGIN_CLEAN =====]");
1061 _INFO("PackageID : %s", pkgId.c_str());
1063 // Can be multiple apps in one package
1064 if (tacPluginFinished) {
1065 _INFO("TAC plugin already finished(CLEAN)");
1068 tacPluginFinished = true;
1070 if (tacState == TAC_STATE_INSTALL) {
1072 } else if (tacState == TAC_STATE_UPGRADE) {
1074 } else if (tacState == TAC_STATE_UNINSTALL) {
1081 copySmackAndOwnership(__DOTNET_DIR, TAC_APP_LIST_DB);
1082 copySmackAndOwnership(__DOTNET_DIR, TAC_APP_LIST_DB + std::string("-journal"));
1088 copySmackAndOwnership(__DOTNET_DIR, TLC_APP_LIST_DB);
1089 copySmackAndOwnership(__DOTNET_DIR, TLC_APP_LIST_DB + std::string("-journal"));